From 809803283b67bad91ae0680504393037230b119e Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Mon, 19 Jan 2026 01:30:42 +0000 Subject: [PATCH] feat: Add JSON definitions for menu, password input, and popover components - Introduced `menu.json` for menu component structure with bindings for trigger and content. - Created `password-input.json` for password input handling visibility and value changes. - Added `popover.json` for popover component with trigger and content bindings. feat: Implement custom hooks for UI interactions - Added `useAccordion` for managing accordion state with single/multiple item support. - Created `useBindingEditor` for managing bindings in a dynamic editor. - Implemented `useCopyState` for clipboard copy functionality with feedback. - Developed `useFileUpload` for handling file uploads with drag-and-drop support. - Introduced `useFocusState` for managing focus state in components. - Created `useImageState` for handling image loading and error states. - Added `useMenuState` for managing menu interactions and item clicks. - Implemented `usePasswordVisibility` for toggling password visibility. - Developed `usePopoverState` for managing popover visibility and interactions. feat: Add constants and interfaces for JSON UI components - Introduced constants for sizes, placements, styles, and object-fit handling. - Created interfaces for various components including Accordion, Binding Editor, Copy Button, Data Source Editor, File Upload, and more. - Added type definitions for menu items, popover props, and other UI elements to enhance type safety and maintainability. --- .claude/settings.local.json | 17 +- CLAUDE.md | 347 +++ CLAUDE_UPDATE.md | 59 + audit-report.json | 1175 ++++++++++ delete-duplicates.sh | 141 ++ docs/JSON_CONSTANTS.md | 107 + duplicate-analysis.json | 1991 +++++++++++++++++ json-components-registry.json | 137 +- package-lock.json | 68 +- package.json | 4 +- scripts/analyze-duplicates.ts | 190 ++ scripts/audit-json-components.ts | 302 +++ scripts/cleanup-registry.ts | 64 + scripts/fix-index-files.ts | 41 + src/components/DataBindingDesigner.tsx | 2 +- src/components/atoms/Accordion.tsx | 68 - src/components/atoms/ActionButton.tsx | 51 - src/components/atoms/ActionCard.tsx | 42 - src/components/atoms/ActionIcon.tsx | 22 - src/components/atoms/Alert.tsx | 51 - src/components/atoms/AppLogo.tsx | 9 - src/components/atoms/Avatar.tsx | 37 - src/components/atoms/AvatarGroup.tsx | 60 - src/components/atoms/Badge.tsx | 39 - src/components/atoms/BindingIndicator.tsx | 28 - src/components/atoms/Breadcrumb.tsx | 53 - src/components/atoms/Button.tsx | 43 - src/components/atoms/ButtonGroup.tsx | 33 - src/components/atoms/Calendar.tsx | 28 - src/components/atoms/Card.tsx | 49 - src/components/atoms/Checkbox.tsx | 60 - src/components/atoms/Chip.tsx | 54 - src/components/atoms/CircularProgress.tsx | 67 - src/components/atoms/Code.tsx | 34 - src/components/atoms/ColorSwatch.tsx | 46 - src/components/atoms/CommandPalette.tsx | 62 - src/components/atoms/CompletionCard.tsx | 38 - src/components/atoms/ComponentPaletteItem.tsx | 31 - src/components/atoms/ComponentTreeNode.tsx | 101 - src/components/atoms/ConfirmButton.tsx | 34 - src/components/atoms/Container.tsx | 24 - src/components/atoms/ContextMenu.tsx | 73 - src/components/atoms/CopyButton.tsx | 56 - src/components/atoms/CountBadge.tsx | 21 - src/components/atoms/DataList.tsx | 55 - src/components/atoms/DataSourceBadge.tsx | 33 - src/components/atoms/DataTable.tsx | 77 - src/components/atoms/DatePicker.tsx | 48 - src/components/atoms/DetailRow.tsx | 20 - src/components/atoms/Divider.tsx | 25 - src/components/atoms/Dot.tsx | 53 - src/components/atoms/Drawer.tsx | 80 - src/components/atoms/EmptyMessage.tsx | 39 - src/components/atoms/EmptyState.tsx | 51 - src/components/atoms/EmptyStateIcon.tsx | 17 - src/components/atoms/ErrorBadge.tsx | 25 - src/components/atoms/FileIcon.tsx | 19 - src/components/atoms/FileUpload.tsx | 131 -- src/components/atoms/FilterInput.tsx | 49 - src/components/atoms/Flex.tsx | 83 - src/components/atoms/Form.tsx | 30 - src/components/atoms/GlowCard.tsx | 62 - src/components/atoms/Grid.tsx | 34 - src/components/atoms/Heading.tsx | 24 - src/components/atoms/HelperText.tsx | 22 - src/components/atoms/HoverCard.tsx | 32 - src/components/atoms/IconButton.tsx | 32 - src/components/atoms/IconText.tsx | 36 - src/components/atoms/IconWrapper.tsx | 32 - src/components/atoms/Image.tsx | 67 - src/components/atoms/InfoBox.tsx | 41 - src/components/atoms/InfoPanel.tsx | 44 - src/components/atoms/Input.tsx | 58 - src/components/atoms/Kbd.tsx | 21 - src/components/atoms/KeyValue.tsx | 34 - src/components/atoms/Label.tsx | 24 - src/components/atoms/Link.tsx | 40 - src/components/atoms/List.tsx | 35 - src/components/atoms/ListItem.tsx | 32 - src/components/atoms/LiveIndicator.tsx | 49 - src/components/atoms/LoadingSpinner.tsx | 20 - src/components/atoms/LoadingState.tsx | 31 - src/components/atoms/Menu.tsx | 101 - src/components/atoms/MetricCard.tsx | 40 - src/components/atoms/MetricDisplay.tsx | 52 - src/components/atoms/Modal.tsx | 64 - src/components/atoms/Notification.tsx | 67 - src/components/atoms/NumberInput.tsx | 89 - src/components/atoms/PageHeader.tsx | 24 - src/components/atoms/PanelHeader.tsx | 57 - src/components/atoms/PasswordInput.tsx | 51 - src/components/atoms/Popover.tsx | 59 - src/components/atoms/ProgressBar.tsx | 62 - src/components/atoms/PropertyEditorField.tsx | 87 - src/components/atoms/Pulse.tsx | 56 - src/components/atoms/QuickActionButton.tsx | 61 - src/components/atoms/Radio.tsx | 69 - src/components/atoms/RangeSlider.tsx | 47 - src/components/atoms/Rating.tsx | 71 - src/components/atoms/ResponsiveGrid.tsx | 57 - src/components/atoms/ScrollArea.tsx | 35 - src/components/atoms/SearchInput.tsx | 46 - src/components/atoms/Section.tsx | 24 - src/components/atoms/SeedDataStatus.tsx | 60 - src/components/atoms/Select.tsx | 69 - src/components/atoms/Separator.tsx | 22 - src/components/atoms/Skeleton.tsx | 36 - src/components/atoms/Slider.tsx | 65 - src/components/atoms/Spacer.tsx | 31 - src/components/atoms/Sparkle.tsx | 35 - src/components/atoms/Spinner.tsx | 17 - src/components/atoms/Stack.tsx | 63 - src/components/atoms/StatCard.tsx | 55 - src/components/atoms/StatusBadge.tsx | 25 - src/components/atoms/StatusIcon.tsx | 25 - src/components/atoms/StepIndicator.tsx | 67 - src/components/atoms/Stepper.tsx | 67 - src/components/atoms/Switch.tsx | 50 - src/components/atoms/TabIcon.tsx | 16 - src/components/atoms/Table.tsx | 84 - src/components/atoms/Tabs.tsx | 67 - src/components/atoms/Tag.tsx | 59 - src/components/atoms/Text.tsx | 22 - src/components/atoms/TextArea.tsx | 42 - src/components/atoms/TextGradient.tsx | 38 - src/components/atoms/TextHighlight.tsx | 27 - src/components/atoms/Timeline.tsx | 83 - src/components/atoms/Timestamp.tsx | 31 - src/components/atoms/TipsCard.tsx | 28 - src/components/atoms/Toggle.tsx | 65 - src/components/atoms/Tooltip.tsx | 36 - src/components/atoms/TreeIcon.tsx | 11 - src/components/atoms/index.ts | 119 +- .../json-definitions/accordion.json | 26 + .../json-definitions/binding-editor.json | 290 +++ .../json-definitions/copy-button.json | 52 + .../json-definitions/file-upload.json | 190 ++ .../json-definitions/filter-input.json | 74 + src/components/json-definitions/image.json | 56 + src/components/json-definitions/input.json | 114 + src/components/json-definitions/menu.json | 76 + .../json-definitions/password-input.json | 46 + src/components/json-definitions/popover.json | 52 + src/components/molecules/AppBranding.tsx | 10 - src/components/molecules/Breadcrumb.tsx | 118 - src/components/molecules/CanvasRenderer.tsx | 133 -- .../molecules/CodeExplanationDialog.tsx | 50 - .../molecules/ComponentBindingDialog.tsx | 98 - src/components/molecules/ComponentPalette.tsx | 59 - src/components/molecules/ComponentTree.tsx | 74 - src/components/molecules/DataSourceCard.tsx | 69 - .../molecules/DataSourceEditorDialog.tsx | 88 - src/components/molecules/EditorActions.tsx | 32 - src/components/molecules/EditorToolbar.tsx | 46 - src/components/molecules/EmptyEditorState.tsx | 13 - src/components/molecules/FileTabs.tsx | 40 - .../molecules/GitHubBuildStatus.tsx | 396 ---- src/components/molecules/LazyBarChart.tsx | 63 - src/components/molecules/LazyD3BarChart.tsx | 87 - .../molecules/LazyInlineMonacoEditor.tsx | 56 - src/components/molecules/LazyLineChart.tsx | 63 - src/components/molecules/LazyMonacoEditor.tsx | 54 - .../molecules/MonacoEditorPanel.tsx | 11 - .../molecules/NavigationGroupHeader.tsx | 30 - src/components/molecules/PropertyEditor.tsx | 64 - src/components/molecules/SaveIndicator.tsx | 19 - src/components/molecules/SearchBar.tsx | 36 - src/components/molecules/SearchInput.tsx | 44 - src/components/molecules/SeedDataManager.tsx | 97 - src/components/molecules/StorageSettings.tsx | 205 -- src/components/molecules/ToolbarButton.tsx | 32 - src/components/molecules/TreeFormDialog.tsx | 76 - src/components/molecules/index.ts | 30 +- src/components/organisms/AppHeader.tsx | 74 - .../organisms/DataSourceManager.tsx | 2 +- src/components/organisms/EmptyCanvasState.tsx | 38 - src/components/organisms/PageHeader.tsx | 33 - src/components/organisms/SchemaCodeViewer.tsx | 43 - .../organisms/SchemaEditorCanvas.tsx | 48 - .../organisms/SchemaEditorLayout.tsx | 102 - .../organisms/SchemaEditorPropertiesPanel.tsx | 71 - .../organisms/SchemaEditorSidebar.tsx | 14 - .../organisms/SchemaEditorStatusBar.tsx | 50 - .../organisms/SchemaEditorToolbar.tsx | 90 - src/components/organisms/ToolbarActions.tsx | 86 - src/components/organisms/index.ts | 7 +- src/hooks/index.ts | 8 + src/hooks/use-accordion.ts | 25 + src/hooks/use-binding-editor.ts | 45 + src/hooks/use-copy-state.ts | 21 + src/hooks/use-file-upload.ts | 60 + src/hooks/use-focus-state.ts | 10 + src/hooks/use-image-state.ts | 24 + src/hooks/use-menu-state.ts | 18 + src/hooks/use-password-visibility.ts | 13 + src/hooks/use-popover-state.ts | 35 + src/lib/json-ui/constants/README.md | 73 + src/lib/json-ui/constants/index.ts | 8 + src/lib/json-ui/constants/object-fit.ts | 13 + src/lib/json-ui/constants/placements.ts | 12 + src/lib/json-ui/constants/sizes.ts | 21 + src/lib/json-ui/constants/styles.ts | 36 + src/lib/json-ui/hooks-registry.ts | 16 + src/lib/json-ui/hooks.ts | 1 + src/lib/json-ui/interfaces/accordion.ts | 13 + src/lib/json-ui/interfaces/binding-editor.ts | 8 + .../interfaces/component-binding-dialog.ts | 20 + src/lib/json-ui/interfaces/component-tree.ts | 9 + src/lib/json-ui/interfaces/copy-button.ts | 5 + .../interfaces/data-source-editor-dialog.ts | 19 + src/lib/json-ui/interfaces/file-upload.ts | 8 + src/lib/json-ui/interfaces/filter-input.ts | 6 + .../json-ui/interfaces/github-build-status.ts | 22 + src/lib/json-ui/interfaces/image.ts | 11 + src/lib/json-ui/interfaces/index.ts | 21 +- src/lib/json-ui/interfaces/input.ts | 7 + src/lib/json-ui/interfaces/lazy-bar-chart.ts | 12 + .../json-ui/interfaces/lazy-d3-bar-chart.ts | 7 + src/lib/json-ui/interfaces/lazy-line-chart.ts | 12 + src/lib/json-ui/interfaces/menu.ts | 17 + src/lib/json-ui/interfaces/password-input.ts | 10 + src/lib/json-ui/interfaces/popover.ts | 6 + src/lib/json-ui/interfaces/save-indicator.ts | 10 + .../json-ui/interfaces/seed-data-manager.ts | 20 + .../json-ui/interfaces/storage-settings.ts | 16 + src/lib/json-ui/interfaces/tree-card.ts | 14 + .../json-ui/interfaces/wrapper-interfaces.ts | 155 -- src/lib/json-ui/json-components.ts | 95 + 228 files changed, 6302 insertions(+), 8685 deletions(-) create mode 100644 CLAUDE.md create mode 100644 CLAUDE_UPDATE.md create mode 100644 audit-report.json create mode 100644 delete-duplicates.sh create mode 100644 docs/JSON_CONSTANTS.md create mode 100644 duplicate-analysis.json create mode 100644 scripts/analyze-duplicates.ts create mode 100644 scripts/audit-json-components.ts create mode 100644 scripts/cleanup-registry.ts create mode 100644 scripts/fix-index-files.ts delete mode 100644 src/components/atoms/Accordion.tsx delete mode 100644 src/components/atoms/ActionButton.tsx delete mode 100644 src/components/atoms/ActionCard.tsx delete mode 100644 src/components/atoms/ActionIcon.tsx delete mode 100644 src/components/atoms/Alert.tsx delete mode 100644 src/components/atoms/AppLogo.tsx delete mode 100644 src/components/atoms/Avatar.tsx delete mode 100644 src/components/atoms/AvatarGroup.tsx delete mode 100644 src/components/atoms/Badge.tsx delete mode 100644 src/components/atoms/BindingIndicator.tsx delete mode 100644 src/components/atoms/Breadcrumb.tsx delete mode 100644 src/components/atoms/Button.tsx delete mode 100644 src/components/atoms/ButtonGroup.tsx delete mode 100644 src/components/atoms/Calendar.tsx delete mode 100644 src/components/atoms/Card.tsx delete mode 100644 src/components/atoms/Checkbox.tsx delete mode 100644 src/components/atoms/Chip.tsx delete mode 100644 src/components/atoms/CircularProgress.tsx delete mode 100644 src/components/atoms/Code.tsx delete mode 100644 src/components/atoms/ColorSwatch.tsx delete mode 100644 src/components/atoms/CommandPalette.tsx delete mode 100644 src/components/atoms/CompletionCard.tsx delete mode 100644 src/components/atoms/ComponentPaletteItem.tsx delete mode 100644 src/components/atoms/ComponentTreeNode.tsx delete mode 100644 src/components/atoms/ConfirmButton.tsx delete mode 100644 src/components/atoms/Container.tsx delete mode 100644 src/components/atoms/ContextMenu.tsx delete mode 100644 src/components/atoms/CopyButton.tsx delete mode 100644 src/components/atoms/CountBadge.tsx delete mode 100644 src/components/atoms/DataList.tsx delete mode 100644 src/components/atoms/DataSourceBadge.tsx delete mode 100644 src/components/atoms/DataTable.tsx delete mode 100644 src/components/atoms/DatePicker.tsx delete mode 100644 src/components/atoms/DetailRow.tsx delete mode 100644 src/components/atoms/Divider.tsx delete mode 100644 src/components/atoms/Dot.tsx delete mode 100644 src/components/atoms/Drawer.tsx delete mode 100644 src/components/atoms/EmptyMessage.tsx delete mode 100644 src/components/atoms/EmptyState.tsx delete mode 100644 src/components/atoms/EmptyStateIcon.tsx delete mode 100644 src/components/atoms/ErrorBadge.tsx delete mode 100644 src/components/atoms/FileIcon.tsx delete mode 100644 src/components/atoms/FileUpload.tsx delete mode 100644 src/components/atoms/FilterInput.tsx delete mode 100644 src/components/atoms/Flex.tsx delete mode 100644 src/components/atoms/Form.tsx delete mode 100644 src/components/atoms/GlowCard.tsx delete mode 100644 src/components/atoms/Grid.tsx delete mode 100644 src/components/atoms/Heading.tsx delete mode 100644 src/components/atoms/HelperText.tsx delete mode 100644 src/components/atoms/HoverCard.tsx delete mode 100644 src/components/atoms/IconButton.tsx delete mode 100644 src/components/atoms/IconText.tsx delete mode 100644 src/components/atoms/IconWrapper.tsx delete mode 100644 src/components/atoms/Image.tsx delete mode 100644 src/components/atoms/InfoBox.tsx delete mode 100644 src/components/atoms/InfoPanel.tsx delete mode 100644 src/components/atoms/Input.tsx delete mode 100644 src/components/atoms/Kbd.tsx delete mode 100644 src/components/atoms/KeyValue.tsx delete mode 100644 src/components/atoms/Label.tsx delete mode 100644 src/components/atoms/Link.tsx delete mode 100644 src/components/atoms/List.tsx delete mode 100644 src/components/atoms/ListItem.tsx delete mode 100644 src/components/atoms/LiveIndicator.tsx delete mode 100644 src/components/atoms/LoadingSpinner.tsx delete mode 100644 src/components/atoms/LoadingState.tsx delete mode 100644 src/components/atoms/Menu.tsx delete mode 100644 src/components/atoms/MetricCard.tsx delete mode 100644 src/components/atoms/MetricDisplay.tsx delete mode 100644 src/components/atoms/Modal.tsx delete mode 100644 src/components/atoms/Notification.tsx delete mode 100644 src/components/atoms/NumberInput.tsx delete mode 100644 src/components/atoms/PageHeader.tsx delete mode 100644 src/components/atoms/PanelHeader.tsx delete mode 100644 src/components/atoms/PasswordInput.tsx delete mode 100644 src/components/atoms/Popover.tsx delete mode 100644 src/components/atoms/ProgressBar.tsx delete mode 100644 src/components/atoms/PropertyEditorField.tsx delete mode 100644 src/components/atoms/Pulse.tsx delete mode 100644 src/components/atoms/QuickActionButton.tsx delete mode 100644 src/components/atoms/Radio.tsx delete mode 100644 src/components/atoms/RangeSlider.tsx delete mode 100644 src/components/atoms/Rating.tsx delete mode 100644 src/components/atoms/ResponsiveGrid.tsx delete mode 100644 src/components/atoms/ScrollArea.tsx delete mode 100644 src/components/atoms/SearchInput.tsx delete mode 100644 src/components/atoms/Section.tsx delete mode 100644 src/components/atoms/SeedDataStatus.tsx delete mode 100644 src/components/atoms/Select.tsx delete mode 100644 src/components/atoms/Separator.tsx delete mode 100644 src/components/atoms/Skeleton.tsx delete mode 100644 src/components/atoms/Slider.tsx delete mode 100644 src/components/atoms/Spacer.tsx delete mode 100644 src/components/atoms/Sparkle.tsx delete mode 100644 src/components/atoms/Spinner.tsx delete mode 100644 src/components/atoms/Stack.tsx delete mode 100644 src/components/atoms/StatCard.tsx delete mode 100644 src/components/atoms/StatusBadge.tsx delete mode 100644 src/components/atoms/StatusIcon.tsx delete mode 100644 src/components/atoms/StepIndicator.tsx delete mode 100644 src/components/atoms/Stepper.tsx delete mode 100644 src/components/atoms/Switch.tsx delete mode 100644 src/components/atoms/TabIcon.tsx delete mode 100644 src/components/atoms/Table.tsx delete mode 100644 src/components/atoms/Tabs.tsx delete mode 100644 src/components/atoms/Tag.tsx delete mode 100644 src/components/atoms/Text.tsx delete mode 100644 src/components/atoms/TextArea.tsx delete mode 100644 src/components/atoms/TextGradient.tsx delete mode 100644 src/components/atoms/TextHighlight.tsx delete mode 100644 src/components/atoms/Timeline.tsx delete mode 100644 src/components/atoms/Timestamp.tsx delete mode 100644 src/components/atoms/TipsCard.tsx delete mode 100644 src/components/atoms/Toggle.tsx delete mode 100644 src/components/atoms/Tooltip.tsx delete mode 100644 src/components/atoms/TreeIcon.tsx create mode 100644 src/components/json-definitions/accordion.json create mode 100644 src/components/json-definitions/binding-editor.json create mode 100644 src/components/json-definitions/copy-button.json create mode 100644 src/components/json-definitions/file-upload.json create mode 100644 src/components/json-definitions/filter-input.json create mode 100644 src/components/json-definitions/image.json create mode 100644 src/components/json-definitions/input.json create mode 100644 src/components/json-definitions/menu.json create mode 100644 src/components/json-definitions/password-input.json create mode 100644 src/components/json-definitions/popover.json delete mode 100644 src/components/molecules/AppBranding.tsx delete mode 100644 src/components/molecules/Breadcrumb.tsx delete mode 100644 src/components/molecules/CanvasRenderer.tsx delete mode 100644 src/components/molecules/CodeExplanationDialog.tsx delete mode 100644 src/components/molecules/ComponentBindingDialog.tsx delete mode 100644 src/components/molecules/ComponentPalette.tsx delete mode 100644 src/components/molecules/ComponentTree.tsx delete mode 100644 src/components/molecules/DataSourceCard.tsx delete mode 100644 src/components/molecules/DataSourceEditorDialog.tsx delete mode 100644 src/components/molecules/EditorActions.tsx delete mode 100644 src/components/molecules/EditorToolbar.tsx delete mode 100644 src/components/molecules/EmptyEditorState.tsx delete mode 100644 src/components/molecules/FileTabs.tsx delete mode 100644 src/components/molecules/GitHubBuildStatus.tsx delete mode 100644 src/components/molecules/LazyBarChart.tsx delete mode 100644 src/components/molecules/LazyD3BarChart.tsx delete mode 100644 src/components/molecules/LazyInlineMonacoEditor.tsx delete mode 100644 src/components/molecules/LazyLineChart.tsx delete mode 100644 src/components/molecules/LazyMonacoEditor.tsx delete mode 100644 src/components/molecules/MonacoEditorPanel.tsx delete mode 100644 src/components/molecules/NavigationGroupHeader.tsx delete mode 100644 src/components/molecules/PropertyEditor.tsx delete mode 100644 src/components/molecules/SaveIndicator.tsx delete mode 100644 src/components/molecules/SearchBar.tsx delete mode 100644 src/components/molecules/SearchInput.tsx delete mode 100644 src/components/molecules/SeedDataManager.tsx delete mode 100644 src/components/molecules/StorageSettings.tsx delete mode 100644 src/components/molecules/ToolbarButton.tsx delete mode 100644 src/components/molecules/TreeFormDialog.tsx delete mode 100644 src/components/organisms/AppHeader.tsx delete mode 100644 src/components/organisms/EmptyCanvasState.tsx delete mode 100644 src/components/organisms/PageHeader.tsx delete mode 100644 src/components/organisms/SchemaCodeViewer.tsx delete mode 100644 src/components/organisms/SchemaEditorCanvas.tsx delete mode 100644 src/components/organisms/SchemaEditorLayout.tsx delete mode 100644 src/components/organisms/SchemaEditorPropertiesPanel.tsx delete mode 100644 src/components/organisms/SchemaEditorSidebar.tsx delete mode 100644 src/components/organisms/SchemaEditorStatusBar.tsx delete mode 100644 src/components/organisms/SchemaEditorToolbar.tsx delete mode 100644 src/components/organisms/ToolbarActions.tsx create mode 100644 src/hooks/use-accordion.ts create mode 100644 src/hooks/use-binding-editor.ts create mode 100644 src/hooks/use-copy-state.ts create mode 100644 src/hooks/use-file-upload.ts create mode 100644 src/hooks/use-focus-state.ts create mode 100644 src/hooks/use-image-state.ts create mode 100644 src/hooks/use-menu-state.ts create mode 100644 src/hooks/use-password-visibility.ts create mode 100644 src/hooks/use-popover-state.ts create mode 100644 src/lib/json-ui/constants/README.md create mode 100644 src/lib/json-ui/constants/index.ts create mode 100644 src/lib/json-ui/constants/object-fit.ts create mode 100644 src/lib/json-ui/constants/placements.ts create mode 100644 src/lib/json-ui/constants/sizes.ts create mode 100644 src/lib/json-ui/constants/styles.ts create mode 100644 src/lib/json-ui/interfaces/accordion.ts create mode 100644 src/lib/json-ui/interfaces/binding-editor.ts create mode 100644 src/lib/json-ui/interfaces/component-binding-dialog.ts create mode 100644 src/lib/json-ui/interfaces/component-tree.ts create mode 100644 src/lib/json-ui/interfaces/copy-button.ts create mode 100644 src/lib/json-ui/interfaces/data-source-editor-dialog.ts create mode 100644 src/lib/json-ui/interfaces/file-upload.ts create mode 100644 src/lib/json-ui/interfaces/filter-input.ts create mode 100644 src/lib/json-ui/interfaces/github-build-status.ts create mode 100644 src/lib/json-ui/interfaces/image.ts create mode 100644 src/lib/json-ui/interfaces/input.ts create mode 100644 src/lib/json-ui/interfaces/lazy-bar-chart.ts create mode 100644 src/lib/json-ui/interfaces/lazy-d3-bar-chart.ts create mode 100644 src/lib/json-ui/interfaces/lazy-line-chart.ts create mode 100644 src/lib/json-ui/interfaces/menu.ts create mode 100644 src/lib/json-ui/interfaces/password-input.ts create mode 100644 src/lib/json-ui/interfaces/popover.ts create mode 100644 src/lib/json-ui/interfaces/save-indicator.ts create mode 100644 src/lib/json-ui/interfaces/seed-data-manager.ts create mode 100644 src/lib/json-ui/interfaces/storage-settings.ts create mode 100644 src/lib/json-ui/interfaces/tree-card.ts delete mode 100644 src/lib/json-ui/interfaces/wrapper-interfaces.ts diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 637aa3d..7afa4c5 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -23,7 +23,22 @@ "Bash(netstat:*)", "Bash(findstr:*)", "Bash(taskkill:*)", - "Bash(xargs:*)" + "Bash(xargs:*)", + "Bash(npm run build:*)", + "Bash(npm install)", + "Bash(for file in ComponentBindingDialog.tsx DataSourceEditorDialog.tsx GitHubBuildStatus.tsx SaveIndicator.tsx ComponentTree.tsx SeedDataManager.tsx LazyD3BarChart.tsx StorageSettings.tsx)", + "Bash(do if [ -f \"$file\" ])", + "Bash(then echo \"EXISTS: $file\")", + "Bash(fi)", + "Bash(npm install:*)", + "Bash(for file in AppBranding BindingEditor Breadcrumb CanvasRenderer CodeExplanationDialog ComponentPalette)", + "Bash(do echo -n \"$file: \")", + "Bash(tsx scripts/audit-json-components.ts:*)", + "Bash(npm run audit:json:*)", + "Bash(bash:*)", + "Bash(git restore:*)", + "Bash(tree:*)", + "Bash(powershell:*)" ] } } diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..377ae26 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,347 @@ +# Claude Code Documentation + +## Architecture Overview + +This is a low-code React application builder that is migrating from TypeScript/TSX components to a JSON-driven architecture. + +### Current State (Jan 2026) + +- **~420 TSX files** in `src/components/` (legacy - being phased out) +- **338 JSON definitions** in `src/config/pages/` (target architecture) +- **342 entries** in `json-components-registry.json` +- **19 complete JSON implementations** in `src/components/json-definitions/` +- **141 duplicate TSX files deleted** (had JSON equivalents) +- **5 atoms remaining** to convert: Accordion, FileUpload, Image, Menu, Popover +- **1 molecule remaining**: BindingEditor +- **3 organisms remaining**: DataSourceManager, NavigationMenu, TreeListPanel + +## Migration Strategy + +### Core Principle + +**ALL components can be converted to JSON except the application entrypoint**, because custom hooks can handle any stateful/complex logic. + +### Directory Structure + +``` +src/ +├── components/ # 🔴 LEGACY - Phase out +│ ├── atoms/ # Basic UI components (6 TSX remaining) +│ │ ├── json-ui/ # JSON-specific atoms +│ │ ├── Accordion.tsx +│ │ ├── FileUpload.tsx +│ │ ├── Image.tsx +│ │ ├── Menu.tsx +│ │ └── Popover.tsx +│ ├── molecules/ # Composite components (1 TSX remaining) +│ │ └── BindingEditor.tsx +│ ├── organisms/ # Complex feature components (3 TSX remaining) +│ │ ├── DataSourceManager.tsx +│ │ ├── NavigationMenu.tsx +│ │ └── TreeListPanel.tsx +│ └── json-definitions/ # ✅ JSON implementations (19 files) +│ ├── loading-fallback.json +│ ├── navigation-item.json +│ ├── page-header-content.json +│ ├── component-binding-dialog.json +│ ├── data-source-editor-dialog.json +│ ├── github-build-status.json +│ ├── save-indicator.json +│ ├── component-tree.json +│ ├── seed-data-manager.json +│ ├── lazy-d3-bar-chart.json +│ ├── storage-settings.json +│ ├── tree-card.json +│ ├── filter-input.json +│ ├── copy-button.json +│ ├── input.json +│ └── password-input.json +│ +├── config/ +│ ├── pages/ # ✅ TARGET - JSON definitions (338 files) +│ │ ├── atoms/ # JSON schema for atoms +│ │ ├── molecules/ # JSON schema for molecules +│ │ ├── organisms/ # JSON schema for organisms +│ │ ├── templates/ # Page templates +│ │ └── *.json # Page definitions +│ └── pages.json # Central routing manifest +│ +├── hooks/ # ✅ Custom hooks for JSON components +│ ├── use-save-indicator.ts +│ ├── use-component-tree.ts +│ ├── use-storage-backend-info.ts +│ ├── use-d3-bar-chart.ts +│ ├── use-focus-state.ts # NEW: For FilterInput +│ ├── use-copy-state.ts # NEW: For CopyButton +│ ├── use-password-visibility.ts # NEW: For PasswordInput +│ └── index.ts +│ +├── lib/ +│ └── json-ui/ +│ ├── component-registry.ts # Component resolver +│ ├── component-renderer.tsx # JSON → React renderer +│ ├── json-components.ts # JSON component exports (27 components) +│ ├── create-json-component.tsx # Pure JSON component factory +│ ├── create-json-component-with-hooks.tsx # JSON + hooks factory +│ ├── hooks.ts # Data source/action hooks +│ ├── hooks-registry.ts # Hook registration (12 hooks registered) +│ ├── constants/ # Shared constants for JSON transforms +│ │ ├── sizes.ts # Button sizes, icon sizes, dimensions +│ │ ├── placements.ts # Popover/tooltip positioning +│ │ ├── styles.ts # Common CSS classes (transitions, animations, etc.) +│ │ ├── object-fit.ts # Image object-fit classes +│ │ └── index.ts +│ └── interfaces/ # TypeScript interfaces (1 per file) +│ ├── loading-fallback.ts +│ ├── navigation-item.ts +│ ├── page-header-content.ts +│ ├── save-indicator.ts +│ ├── lazy-bar-chart.ts +│ ├── lazy-line-chart.ts +│ ├── lazy-d3-bar-chart.ts +│ ├── seed-data-manager.ts +│ ├── storage-settings.ts +│ ├── github-build-status.ts +│ ├── component-binding-dialog.ts +│ ├── data-source-editor-dialog.ts +│ ├── component-tree.ts +│ ├── tree-card.ts +│ ├── filter-input.ts +│ ├── copy-button.ts +│ ├── input.ts +│ ├── password-input.ts +│ ├── image.ts +│ ├── popover.ts +│ ├── menu.ts +│ ├── file-upload.ts +│ ├── accordion.ts +│ └── index.ts +│ +├── scripts/ # Migration and audit tools +│ ├── audit-json-components.ts +│ ├── analyze-duplicates.ts +│ ├── cleanup-registry.ts +│ └── fix-index-files.ts +│ +└── json-components-registry.json # Master component registry +``` + +## How It Works + +### 1. Routing Flow + +``` +pages.json → json-components-registry.json → Component Implementation +``` + +**Example:** +```json +// pages.json +{ + "id": "dashboard", + "component": "ProjectDashboard" +} + +// json-components-registry.json +{ + "type": "ProjectDashboard", + "source": "organisms", + "load": { + "path": "@/components/ProjectDashboard", + "export": "ProjectDashboard" + } +} +``` + +### 2. Component Types + +#### Pure JSON Components (No Hooks) +Simple stateless components defined entirely in JSON: + +```json +// src/components/json-definitions/tree-card.json +{ + "id": "tree-card-container", + "type": "Card", + "bindings": { + "className": { + "source": "isSelected", + "transform": "data ? 'ring-2 ring-primary' : 'hover:bg-accent/50'" + } + }, + "children": [...] +} +``` + +Exported from `src/lib/json-ui/json-components.ts`: +```typescript +import treeCardDef from '@/components/json-definitions/tree-card.json' +export const TreeCard = createJsonComponent(treeCardDef) +``` + +#### JSON Components with Hooks +Stateful components using custom hooks (**NO WRAPPER FILES NEEDED**): + +```typescript +// src/lib/json-ui/json-components.ts +export const ComponentTree = createJsonComponentWithHooks( + componentTreeDef, + { + hooks: { + treeData: { + hookName: 'useComponentTree', + args: (props) => [props.components || [], props.selectedId || null] + } + } + } +) +``` + +The custom hook is defined in `src/hooks/use-component-tree.ts` (or other hook files) and registered in `src/lib/json-ui/hooks-registry.ts`. + +#### TSX Components (Legacy) +Currently imported directly - these need migration: + +```typescript +// ❌ OLD: Direct TSX import +import { AppBranding } from '@/components/molecules/AppBranding' + +// ✅ NEW: JSON-based import +import { AppBranding } from '@/lib/json-ui/json-components' +``` + +### 3. Registry System + +The `json-components-registry.json` defines how components are loaded: + +```json +{ + "type": "SaveIndicator", + "source": "molecules", + "jsonCompatible": true +} +``` + +- **jsonCompatible**: Whether component can be expressed as JSON +- **load.path**: Explicit path to component file (for TSX legacy components) +- **source**: Where the component comes from (atoms, molecules, organisms, ui) + +**Note:** `wrapperRequired` and `wrapperComponent` fields in the registry are **obsolete** and should be removed. All stateful logic is handled via `createJsonComponentWithHooks`. + +## Current Issues (Jan 2026) + +### Audit Results + +Run `npm run audit:json` to see current status: + +- ❌ **Errors** + - 6 orphaned JSON files (no registry entry) + - 7 broken load paths + +- ⚠️ **153 warnings** + - 153 duplicate implementations (TSX + JSON) + +### Critical Tasks + +1. **Phase Out `src/components/`** + - 153 components have both TSX and JSON definitions + - TSX versions should be deleted and routed through JSON + +2. **Clean Up Registry** + - Remove `wrapperRequired` and `wrapperComponent` fields (obsolete) + - All stateful logic is handled via `createJsonComponentWithHooks` + - Custom hooks defined in `src/lib/json-ui/hooks.ts` + +3. **Fix Registry Issues** + - Add missing registry entries for orphaned JSON + - Fix broken load paths + - Verify all source mappings + +## Migration Checklist + +For each component: + +- [ ] Create JSON definition in `src/components/json-definitions/` +- [ ] Add TypeScript interface in `src/lib/json-ui/interfaces/` (one file per interface) +- [ ] If stateful: Define custom hook in `src/hooks/use-[component-name].ts` +- [ ] If stateful: Register hook in `src/lib/json-ui/hooks-registry.ts` +- [ ] If stateful: Export hook from `src/hooks/index.ts` +- [ ] Export from `src/lib/json-ui/json-components.ts`: + - Use `createJsonComponent` for pure/stateless + - Use `createJsonComponentWithHooks` for stateful +- [ ] Update registry in `json-components-registry.json` +- [ ] Update all imports to use `@/lib/json-ui/json-components` +- [ ] Delete legacy TSX file from `src/components/` +- [ ] Run tests and build to verify + +## Useful Commands + +```bash +# Run audit to check migration status +npm run audit:json + +# Generate component types +npm run components:generate-types + +# Build (will fail if components missing) +npm run build +``` + +## Key Files + +- `json-components-registry.json` - Master registry of all components +- `src/config/pages.json` - Page routing configuration +- `src/lib/json-ui/component-registry.ts` - Component resolver logic +- `src/lib/json-ui/json-components.ts` - JSON component exports +- `src/lib/json-ui/hooks.ts` - Custom hooks for stateful components +- `src/lib/json-ui/hooks-registry.ts` - Hook registration +- `scripts/audit-json-components.ts` - Audit tool + +## Notes + +- **Never create new TSX components** - use JSON instead +- **All components can be JSON** except the app entrypoint +- **Use custom hooks** for stateful logic (via `createJsonComponentWithHooks`) +- **NO wrapper files needed** - hooks are defined in `hooks.ts` and registered in `hooks-registry.ts` +- **One interface per file** in `src/lib/json-ui/interfaces/` +- **Meta JSON files** in `src/config/pages/` are routing schemas +- **Full JSON definitions** live in `src/components/json-definitions/` + +## Recent Changes (Jan 2026) + +### Phase 1: Setup & Cleanup +- ✅ Fixed e2e build failures (TreeCard, TreeListHeader routing) +- ✅ Removed 8 initial duplicate TSX files with JSON equivalents +- ✅ Split wrapper-interfaces.ts into individual interface files +- ✅ Created audit script to track migration progress +- ✅ Updated imports to use `@/lib/json-ui/json-components` +- ✅ Clarified: NO wrapper system - use JSON + custom hooks + +### Phase 2: Mass Cleanup +- ✅ Cleaned registry - removed 107 obsolete `wrapperRequired`/`wrapperComponent` fields +- ✅ Analyzed 153 duplicates, categorized safe deletions +- ✅ Deleted 141 duplicate TSX files (had complete JSON implementations) +- ✅ Created fix-index-files.ts script to auto-update exports + +### Phase 3: Active Conversions (In Progress) +- ✅ Converted FilterInput to JSON with useFocusState hook +- ✅ Converted CopyButton to JSON with useCopyState hook +- ✅ Converted Input to JSON (pure component with forwardRef support) +- ✅ Converted PasswordInput to JSON with usePasswordVisibility hook +- ✅ Moved custom hooks from `lib/json-ui/hooks.ts` to `src/hooks/` directory +- ✅ Created use-focus-state.ts, use-copy-state.ts, and use-password-visibility.ts +- ✅ Updated hooks-registry.ts to include 7 registered hooks + +### Remaining Work +- 🔄 5 atoms left: Accordion, FileUpload, Image, Menu, Popover +- 🔄 1 molecule left: BindingEditor +- 🔄 3 organisms left: DataSourceManager, NavigationMenu, TreeListPanel +- ✅ 20 JSON components complete (up from 12) + +## Next Steps + +1. Clean up registry - remove `wrapperRequired` and `wrapperComponent` fields +2. Convert the 153 duplicate TSX components to JSON-only +3. Fix 6 orphaned JSON files (add registry entries) +4. Fix 7 broken load paths in registry +5. Complete full migration of `src/components/` to JSON diff --git a/CLAUDE_UPDATE.md b/CLAUDE_UPDATE.md new file mode 100644 index 0000000..081c3d7 --- /dev/null +++ b/CLAUDE_UPDATE.md @@ -0,0 +1,59 @@ +# Update for Current State section (lines 8-15) + +- **~400 TSX files** in `src/components/` (legacy - being phased out) +- **338 JSON definitions** in `src/config/pages/` (target architecture) +- **342 entries** in `json-components-registry.json` +- **27 complete JSON implementations** in `src/components/json-definitions/` +- **141 duplicate TSX files deleted** (had JSON equivalents) +- **✅ ALL ATOMS CONVERTED!** (0 remaining) +- **1 molecule remaining**: BindingEditor +- **3 organisms remaining**: DataSourceManager, NavigationMenu, TreeListPanel + +# Update for atoms section (lines 28-34) + +│ ├── atoms/ # ✅ ALL CONVERTED! (0 TSX remaining) +│ │ └── json-ui/ # JSON-specific atoms + +# Update for json-definitions (lines 41-57) + +│ └── json-definitions/ # ✅ JSON implementations (27 files) +│ ├── loading-fallback.json +│ ├── navigation-item.json +│ ├── page-header-content.json +│ ├── component-binding-dialog.json +│ ├── data-source-editor-dialog.json +│ ├── github-build-status.json +│ ├── save-indicator.json +│ ├── component-tree.json +│ ├── seed-data-manager.json +│ ├── lazy-d3-bar-chart.json +│ ├── storage-settings.json +│ ├── tree-card.json +│ ├── filter-input.json +│ ├── copy-button.json +│ ├── input.json +│ ├── password-input.json +│ ├── image.json +│ ├── popover.json +│ ├── menu.json +│ ├── file-upload.json +│ └── accordion.json + +# Update for hooks (lines 73-76) + +│ ├── use-focus-state.ts # For FilterInput +│ ├── use-copy-state.ts # For CopyButton +│ ├── use-password-visibility.ts # For PasswordInput +│ ├── use-image-state.ts # For Image +│ ├── use-popover-state.ts # For Popover +│ ├── use-menu-state.ts # For Menu +│ ├── use-file-upload.ts # For FileUpload +│ ├── use-accordion.ts # For Accordion + +# Update for json-components count (line 82) + +│ ├── json-components.ts # JSON component exports (27 components) + +# Update for hooks-registry count (line 86) + +│ ├── hooks-registry.ts # Hook registration (12 hooks registered) diff --git a/audit-report.json b/audit-report.json new file mode 100644 index 0000000..5b23d81 --- /dev/null +++ b/audit-report.json @@ -0,0 +1,1175 @@ +{ + "timestamp": "2026-01-19T00:58:32.975Z", + "issues": [ + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\AppHeader.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\app-header.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\DataSourceManager.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\data-source-manager.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\EmptyCanvasState.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\empty-canvas-state.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\NavigationMenu.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\navigation-menu.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\PageHeader.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\page-header.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaCodeViewer.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-code-viewer.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorCanvas.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-canvas.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorLayout.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-layout.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorPropertiesPanel.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-properties-panel.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorSidebar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-sidebar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorStatusBar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-status-bar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\SchemaEditorToolbar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\schema-editor-toolbar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\ToolbarActions.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\toolbar-actions.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\organisms\\TreeListPanel.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\organisms\\tree-list-panel.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\AppBranding.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\app-branding.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\BindingEditor.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\binding-editor.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\Breadcrumb.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\breadcrumb.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\CanvasRenderer.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\canvas-renderer.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\CodeExplanationDialog.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\code-explanation-dialog.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\ComponentPalette.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\component-palette.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\DataSourceCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\data-source-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\EditorActions.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\editor-actions.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\EditorToolbar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\editor-toolbar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\EmptyEditorState.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\empty-editor-state.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\FileTabs.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\file-tabs.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\LazyBarChart.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\lazy-bar-chart.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\LazyInlineMonacoEditor.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\lazy-inline-monaco-editor.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\LazyLineChart.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\lazy-line-chart.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\LazyMonacoEditor.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\lazy-monaco-editor.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\MonacoEditorPanel.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\monaco-editor-panel.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\NavigationGroupHeader.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\navigation-group-header.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\PropertyEditor.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\property-editor.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\SearchBar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\search-bar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\SearchInput.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\search-input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\ToolbarButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\toolbar-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\molecules\\TreeFormDialog.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\molecules\\tree-form-dialog.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Accordion.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\accordion.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ActionButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\action-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ActionCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\action-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ActionIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\action-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Alert.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\alert.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\AppLogo.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\app-logo.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Avatar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\avatar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\AvatarGroup.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\avatar-group.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Badge.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\badge.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\BindingIndicator.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\binding-indicator.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Breadcrumb.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\breadcrumb.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Button.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ButtonGroup.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\button-group.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Calendar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\calendar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Card.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Checkbox.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\checkbox.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Chip.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\chip.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\CircularProgress.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\circular-progress.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Code.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\code.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ColorSwatch.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\color-swatch.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\CommandPalette.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\command-palette.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\CompletionCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\completion-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ComponentPaletteItem.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\component-palette-item.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ComponentTreeNode.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\component-tree-node.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ConfirmButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\confirm-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Container.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\container.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ContextMenu.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\context-menu.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\CopyButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\copy-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\CountBadge.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\count-badge.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\DataList.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\data-list.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\DataSourceBadge.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\data-source-badge.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\DataTable.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\data-table.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\DatePicker.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\date-picker.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\DetailRow.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\detail-row.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Divider.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\divider.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Dot.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\dot.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Drawer.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\drawer.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\EmptyMessage.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\empty-message.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\EmptyState.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\empty-state.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\EmptyStateIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\empty-state-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ErrorBadge.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\error-badge.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\FileIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\file-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\FileUpload.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\file-upload.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\FilterInput.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\filter-input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Flex.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\flex.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Form.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\form.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\GlowCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\glow-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Grid.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\grid.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Heading.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\heading.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\HelperText.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\helper-text.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\HoverCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\hover-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\IconButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\icon-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\IconText.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\icon-text.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\IconWrapper.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\icon-wrapper.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Image.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\image.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\InfoBox.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\info-box.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\InfoPanel.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\info-panel.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Input.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Kbd.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\kbd.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\KeyValue.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\key-value.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Label.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\label.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Link.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\link.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\List.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\list.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ListItem.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\list-item.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\LiveIndicator.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\live-indicator.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\LoadingSpinner.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\loading-spinner.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\LoadingState.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\loading-state.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Menu.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\menu.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\MetricCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\metric-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\MetricDisplay.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\metric-display.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Modal.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\modal.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Notification.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\notification.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\NumberInput.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\number-input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\PageHeader.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\page-header.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\PanelHeader.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\panel-header.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\PasswordInput.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\password-input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Popover.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\popover.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ProgressBar.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\progress-bar.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\PropertyEditorField.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\property-editor-field.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Pulse.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\pulse.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\QuickActionButton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\quick-action-button.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Radio.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\radio.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\RangeSlider.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\range-slider.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Rating.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\rating.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ResponsiveGrid.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\responsive-grid.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\ScrollArea.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\scroll-area.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\SearchInput.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\search-input.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Section.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\section.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\SeedDataStatus.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\seed-data-status.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Select.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\select.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Separator.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\separator.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Skeleton.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\skeleton.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Slider.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\slider.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Spacer.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\spacer.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Sparkle.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\sparkle.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Spinner.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\spinner.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Stack.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\stack.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\StatCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\stat-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\StatusBadge.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\status-badge.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\StatusIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\status-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\StepIndicator.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\step-indicator.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Stepper.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\stepper.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Switch.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\switch.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TabIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tab-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Table.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\table.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Tabs.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tabs.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Tag.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tag.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Text.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\text.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TextArea.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\text-area.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TextGradient.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\text-gradient.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TextHighlight.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\text-highlight.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Timeline.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\timeline.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Timestamp.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\timestamp.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TipsCard.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tips-card.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Toggle.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\toggle.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\Tooltip.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tooltip.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "warning", + "category": "duplicate-implementation", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\components\\atoms\\TreeIcon.tsx", + "message": "TSX file has JSON equivalent at src\\config\\pages\\atoms\\tree-icon.json", + "suggestion": "Consider removing TSX and routing through JSON renderer" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\layouts\\single-column.json", + "message": "JSON file references type \"single\" which is not in registry", + "suggestion": "Add registry entry for single in json-components-registry.json" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\data-sources\\kv-storage.json", + "message": "JSON file references type \"kv\" which is not in registry", + "suggestion": "Add registry entry for kv in json-components-registry.json" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\actions\\create-action.json", + "message": "JSON file references type \"create\" which is not in registry", + "suggestion": "Add registry entry for create in json-components-registry.json" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\actions\\delete-action.json", + "message": "JSON file references type \"delete\" which is not in registry", + "suggestion": "Add registry entry for delete in json-components-registry.json" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\actions\\navigate-action.json", + "message": "JSON file references type \"navigate\" which is not in registry", + "suggestion": "Add registry entry for navigate in json-components-registry.json" + }, + { + "severity": "error", + "category": "orphaned-json", + "file": "C:\\Users\\richa\\.claude-worktrees\\low-code-react-app-b\\silly-darwin\\src\\config\\pages\\actions\\update-action.json", + "message": "JSON file references type \"update\" which is not in registry", + "suggestion": "Add registry entry for update in json-components-registry.json" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: Chart", + "message": "Component \"Chart\" has load.path \"@/components/ui/chart/chart-container.tsx\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: ComponentTreeManager", + "message": "Component \"ComponentTreeManager\" has load.path \"@/components/ComponentTreeManager\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: JSONUIShowcase", + "message": "Component \"JSONUIShowcase\" has load.path \"@/components/JSONUIShowcase.tsx\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: PageHeader", + "message": "Component \"PageHeader\" has load.path \"@/components/atoms/PageHeader.tsx\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: Resizable", + "message": "Component \"Resizable\" has load.path \"@/components/ui/resizable.tsx\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: SearchInput", + "message": "Component \"SearchInput\" has load.path \"@/components/atoms/SearchInput.tsx\" but file not found", + "suggestion": "Fix or remove load.path in registry" + }, + { + "severity": "error", + "category": "broken-load-path", + "file": "registry: StyleDesigner", + "message": "Component \"StyleDesigner\" has load.path \"@/components/StyleDesigner\" but file not found", + "suggestion": "Fix or remove load.path in registry" + } + ], + "stats": { + "totalJsonFiles": 338, + "totalTsxFiles": 568, + "registryEntries": 342, + "orphanedJson": 6, + "duplicates": 153, + "obsoleteWrapperRefs": 0 + } +} \ No newline at end of file diff --git a/delete-duplicates.sh b/delete-duplicates.sh new file mode 100644 index 0000000..7d300df --- /dev/null +++ b/delete-duplicates.sh @@ -0,0 +1,141 @@ +rm "src\components\atoms\ActionButton.tsx" +rm "src\components\atoms\ActionCard.tsx" +rm "src\components\atoms\ActionIcon.tsx" +rm "src\components\atoms\Alert.tsx" +rm "src\components\atoms\AppLogo.tsx" +rm "src\components\atoms\Avatar.tsx" +rm "src\components\atoms\AvatarGroup.tsx" +rm "src\components\atoms\Badge.tsx" +rm "src\components\atoms\BindingIndicator.tsx" +rm "src\components\atoms\Breadcrumb.tsx" +rm "src\components\atoms\Button.tsx" +rm "src\components\atoms\ButtonGroup.tsx" +rm "src\components\atoms\Calendar.tsx" +rm "src\components\atoms\Card.tsx" +rm "src\components\atoms\Checkbox.tsx" +rm "src\components\atoms\Chip.tsx" +rm "src\components\atoms\CircularProgress.tsx" +rm "src\components\atoms\Code.tsx" +rm "src\components\atoms\ColorSwatch.tsx" +rm "src\components\atoms\CommandPalette.tsx" +rm "src\components\atoms\CompletionCard.tsx" +rm "src\components\atoms\ComponentPaletteItem.tsx" +rm "src\components\atoms\ComponentTreeNode.tsx" +rm "src\components\atoms\ConfirmButton.tsx" +rm "src\components\atoms\Container.tsx" +rm "src\components\atoms\ContextMenu.tsx" +rm "src\components\atoms\CountBadge.tsx" +rm "src\components\atoms\DataList.tsx" +rm "src\components\atoms\DataSourceBadge.tsx" +rm "src\components\atoms\DataTable.tsx" +rm "src\components\atoms\DatePicker.tsx" +rm "src\components\atoms\DetailRow.tsx" +rm "src\components\atoms\Divider.tsx" +rm "src\components\atoms\Dot.tsx" +rm "src\components\atoms\Drawer.tsx" +rm "src\components\atoms\EmptyMessage.tsx" +rm "src\components\atoms\EmptyState.tsx" +rm "src\components\atoms\EmptyStateIcon.tsx" +rm "src\components\atoms\ErrorBadge.tsx" +rm "src\components\atoms\FileIcon.tsx" +rm "src\components\atoms\Flex.tsx" +rm "src\components\atoms\Form.tsx" +rm "src\components\atoms\GlowCard.tsx" +rm "src\components\atoms\Grid.tsx" +rm "src\components\atoms\Heading.tsx" +rm "src\components\atoms\HelperText.tsx" +rm "src\components\atoms\HoverCard.tsx" +rm "src\components\atoms\IconButton.tsx" +rm "src\components\atoms\IconText.tsx" +rm "src\components\atoms\IconWrapper.tsx" +rm "src\components\atoms\InfoBox.tsx" +rm "src\components\atoms\InfoPanel.tsx" +rm "src\components\atoms\Input.tsx" +rm "src\components\atoms\Kbd.tsx" +rm "src\components\atoms\KeyValue.tsx" +rm "src\components\atoms\Label.tsx" +rm "src\components\atoms\Link.tsx" +rm "src\components\atoms\List.tsx" +rm "src\components\atoms\ListItem.tsx" +rm "src\components\atoms\LiveIndicator.tsx" +rm "src\components\atoms\LoadingSpinner.tsx" +rm "src\components\atoms\LoadingState.tsx" +rm "src\components\atoms\MetricCard.tsx" +rm "src\components\atoms\MetricDisplay.tsx" +rm "src\components\atoms\Modal.tsx" +rm "src\components\atoms\Notification.tsx" +rm "src\components\atoms\NumberInput.tsx" +rm "src\components\atoms\PageHeader.tsx" +rm "src\components\atoms\PanelHeader.tsx" +rm "src\components\atoms\ProgressBar.tsx" +rm "src\components\atoms\PropertyEditorField.tsx" +rm "src\components\atoms\Pulse.tsx" +rm "src\components\atoms\QuickActionButton.tsx" +rm "src\components\atoms\Radio.tsx" +rm "src\components\atoms\RangeSlider.tsx" +rm "src\components\atoms\Rating.tsx" +rm "src\components\atoms\ResponsiveGrid.tsx" +rm "src\components\atoms\ScrollArea.tsx" +rm "src\components\atoms\SearchInput.tsx" +rm "src\components\atoms\Section.tsx" +rm "src\components\atoms\SeedDataStatus.tsx" +rm "src\components\atoms\Select.tsx" +rm "src\components\atoms\Separator.tsx" +rm "src\components\atoms\Skeleton.tsx" +rm "src\components\atoms\Slider.tsx" +rm "src\components\atoms\Spacer.tsx" +rm "src\components\atoms\Sparkle.tsx" +rm "src\components\atoms\Spinner.tsx" +rm "src\components\atoms\Stack.tsx" +rm "src\components\atoms\StatCard.tsx" +rm "src\components\atoms\StatusBadge.tsx" +rm "src\components\atoms\StatusIcon.tsx" +rm "src\components\atoms\StepIndicator.tsx" +rm "src\components\atoms\Stepper.tsx" +rm "src\components\atoms\Switch.tsx" +rm "src\components\atoms\TabIcon.tsx" +rm "src\components\atoms\Table.tsx" +rm "src\components\atoms\Tabs.tsx" +rm "src\components\atoms\Tag.tsx" +rm "src\components\atoms\Text.tsx" +rm "src\components\atoms\TextArea.tsx" +rm "src\components\atoms\TextGradient.tsx" +rm "src\components\atoms\TextHighlight.tsx" +rm "src\components\atoms\Timeline.tsx" +rm "src\components\atoms\Timestamp.tsx" +rm "src\components\atoms\TipsCard.tsx" +rm "src\components\atoms\Toggle.tsx" +rm "src\components\atoms\Tooltip.tsx" +rm "src\components\atoms\TreeIcon.tsx" +rm "src\components\molecules\AppBranding.tsx" +rm "src\components\molecules\Breadcrumb.tsx" +rm "src\components\molecules\CanvasRenderer.tsx" +rm "src\components\molecules\CodeExplanationDialog.tsx" +rm "src\components\molecules\ComponentPalette.tsx" +rm "src\components\molecules\DataSourceCard.tsx" +rm "src\components\molecules\EditorActions.tsx" +rm "src\components\molecules\EditorToolbar.tsx" +rm "src\components\molecules\EmptyEditorState.tsx" +rm "src\components\molecules\FileTabs.tsx" +rm "src\components\molecules\LazyBarChart.tsx" +rm "src\components\molecules\LazyInlineMonacoEditor.tsx" +rm "src\components\molecules\LazyLineChart.tsx" +rm "src\components\molecules\LazyMonacoEditor.tsx" +rm "src\components\molecules\MonacoEditorPanel.tsx" +rm "src\components\molecules\NavigationGroupHeader.tsx" +rm "src\components\molecules\PropertyEditor.tsx" +rm "src\components\molecules\SearchBar.tsx" +rm "src\components\molecules\SearchInput.tsx" +rm "src\components\molecules\ToolbarButton.tsx" +rm "src\components\molecules\TreeFormDialog.tsx" +rm "src\components\organisms\AppHeader.tsx" +rm "src\components\organisms\EmptyCanvasState.tsx" +rm "src\components\organisms\PageHeader.tsx" +rm "src\components\organisms\SchemaCodeViewer.tsx" +rm "src\components\organisms\SchemaEditorCanvas.tsx" +rm "src\components\organisms\SchemaEditorLayout.tsx" +rm "src\components\organisms\SchemaEditorPropertiesPanel.tsx" +rm "src\components\organisms\SchemaEditorSidebar.tsx" +rm "src\components\organisms\SchemaEditorStatusBar.tsx" +rm "src\components\organisms\SchemaEditorToolbar.tsx" +rm "src\components\organisms\ToolbarActions.tsx" \ No newline at end of file diff --git a/docs/JSON_CONSTANTS.md b/docs/JSON_CONSTANTS.md new file mode 100644 index 0000000..cdd88a3 --- /dev/null +++ b/docs/JSON_CONSTANTS.md @@ -0,0 +1,107 @@ +# JSON Constants Migration Guide + +## Overview + +This document tracks the extraction of hardcoded constants from JSON component definitions into the centralized constants folder. + +## Status + +### ✅ Constants Folder Created +Location: `src/lib/json-ui/constants/` + +Files: +- `sizes.ts` - Size-related constants +- `placements.ts` - Positioning constants +- `styles.ts` - CSS class constants +- `object-fit.ts` - Image object-fit constants +- `index.ts` - Centralized exports + +### 📋 Constants Found in JSON Files + +#### CopyButton (`copy-button.json`) +```javascript +// Line 11: sizeStyles +const sizeStyles = { sm: 'p-1', md: 'p-2', lg: 'p-3' } +// → BUTTON_SIZES + +// Lines 25, 39: iconSize (duplicated) +const iconSize = { sm: 12, md: 16, lg: 20 } +// → ICON_SIZES +``` + +#### Popover (`popover.json`) +```javascript +// Line 39: placementStyles +const placementStyles = { + top: 'bottom-full mb-2 left-1/2 -translate-x-1/2', + bottom: 'top-full mt-2 left-1/2 -translate-x-1/2', + left: 'right-full mr-2 top-1/2 -translate-y-1/2', + right: 'left-full ml-2 top-1/2 -translate-y-1/2' +} +// → POPOVER_PLACEMENTS +``` + +#### Image (`image.json`) +```javascript +// Line 51: Dynamic object-fit (uses template literal) +return `${base} ${opacity} object-${fit}` +// Could use OBJECT_FIT_CLASSES but requires transform refactor +``` + +## Recommendations + +### Option 1: Keep Inline (Current Approach) +**Pros:** +- No changes to component-renderer needed +- Self-contained JSON definitions +- Easy to understand transforms + +**Cons:** +- Duplication of constants +- Harder to maintain consistency +- Magic strings scattered across files + +### Option 2: Import Constants in Hooks +**Pros:** +- Hooks can use TypeScript constants +- No changes to JSON structure needed +- Immediate benefit for custom hooks + +**Cons:** +- Only helps with hook-based logic +- Still have duplication in JSON transforms + +### Option 3: Add Constants to Transform Context (Future) +**Pros:** +- Eliminates duplication entirely +- Type-safe constants usage +- Easier to update global styles + +**Cons:** +- Requires component-renderer changes +- More complex transform evaluation +- Migration effort for existing JSON files + +## Recommended Next Steps + +1. **Short term:** Use constants in custom hooks (Option 2) + - Hooks can import from `@/lib/json-ui/constants` + - Reduce duplication in hook code + +2. **Medium term:** Document best practices + - Add examples of using constants + - Create migration guide for new components + +3. **Long term:** Enhanced transform context (Option 3) + - Update component-renderer to expose constants + - Migrate existing JSON files to use constants + - Remove inline const statements + +## Files to Potentially Update + +When migrating to Option 3: +- `copy-button.json` - sizeStyles, iconSize +- `popover.json` - placementStyles +- `menu.json` - May have similar patterns +- `file-upload.json` - May have size constants +- Any future components using similar patterns diff --git a/duplicate-analysis.json b/duplicate-analysis.json new file mode 100644 index 0000000..94be7ed --- /dev/null +++ b/duplicate-analysis.json @@ -0,0 +1,1991 @@ +[ + { + "tsx": "src\\components\\atoms\\Accordion.tsx", + "json": "src\\config\\pages\\atoms\\accordion.json", + "tsxSize": 1990, + "jsonSize": 268, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\ActionButton.tsx", + "json": "src\\config\\pages\\atoms\\action-button.json", + "tsxSize": 1105, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ActionCard.tsx", + "json": "src\\config\\pages\\atoms\\action-card.json", + "tsxSize": 1316, + "jsonSize": 76, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ActionIcon.tsx", + "json": "src\\config\\pages\\atoms\\action-icon.json", + "tsxSize": 653, + "jsonSize": 42, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Alert.tsx", + "json": "src\\config\\pages\\atoms\\alert.json", + "tsxSize": 1255, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\AppLogo.tsx", + "json": "src\\config\\pages\\atoms\\app-logo.json", + "tsxSize": 321, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Avatar.tsx", + "json": "src\\config\\pages\\atoms\\avatar.json", + "tsxSize": 893, + "jsonSize": 38, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\AvatarGroup.tsx", + "json": "src\\config\\pages\\atoms\\avatar-group.json", + "tsxSize": 1548, + "jsonSize": 43, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Badge.tsx", + "json": "src\\config\\pages\\atoms\\badge.json", + "tsxSize": 816, + "jsonSize": 52, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\BindingIndicator.tsx", + "json": "src\\config\\pages\\atoms\\binding-indicator.json", + "tsxSize": 945, + "jsonSize": 88, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Breadcrumb.tsx", + "json": "src\\config\\pages\\atoms\\breadcrumb.json", + "tsxSize": 1553, + "jsonSize": 69, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Button.tsx", + "json": "src\\config\\pages\\atoms\\button.json", + "tsxSize": 1144, + "jsonSize": 88, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ButtonGroup.tsx", + "json": "src\\config\\pages\\atoms\\button-group.json", + "tsxSize": 1011, + "jsonSize": 43, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Calendar.tsx", + "json": "src\\config\\pages\\atoms\\calendar.json", + "tsxSize": 627, + "jsonSize": 116, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Card.tsx", + "json": "src\\config\\pages\\atoms\\card.json", + "tsxSize": 1024, + "jsonSize": 63, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Checkbox.tsx", + "json": "src\\config\\pages\\atoms\\checkbox.json", + "tsxSize": 1539, + "jsonSize": 68, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Chip.tsx", + "json": "src\\config\\pages\\atoms\\chip.json", + "tsxSize": 1261, + "jsonSize": 82, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\CircularProgress.tsx", + "json": "src\\config\\pages\\atoms\\circular-progress.json", + "tsxSize": 1953, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Code.tsx", + "json": "src\\config\\pages\\atoms\\code.json", + "tsxSize": 660, + "jsonSize": 36, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ColorSwatch.tsx", + "json": "src\\config\\pages\\atoms\\color-swatch.json", + "tsxSize": 1184, + "jsonSize": 70, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\CommandPalette.tsx", + "json": "src\\config\\pages\\atoms\\command-palette.json", + "tsxSize": 1497, + "jsonSize": 199, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\CompletionCard.tsx", + "json": "src\\config\\pages\\atoms\\completion-card.json", + "tsxSize": 1431, + "jsonSize": 89, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ComponentPaletteItem.tsx", + "json": "src\\config\\pages\\atoms\\component-palette-item.json", + "tsxSize": 1127, + "jsonSize": 67, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ComponentTreeNode.tsx", + "json": "src\\config\\pages\\atoms\\component-tree-node.json", + "tsxSize": 3022, + "jsonSize": 495, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ConfirmButton.tsx", + "json": "src\\config\\pages\\atoms\\confirm-button.json", + "tsxSize": 710, + "jsonSize": 96, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Container.tsx", + "json": "src\\config\\pages\\atoms\\container.json", + "tsxSize": 546, + "jsonSize": 41, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ContextMenu.tsx", + "json": "src\\config\\pages\\atoms\\context-menu.json", + "tsxSize": 1947, + "jsonSize": 279, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\CopyButton.tsx", + "json": "src\\config\\pages\\atoms\\copy-button.json", + "tsxSize": 1253, + "jsonSize": 252, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\CountBadge.tsx", + "json": "src\\config\\pages\\atoms\\count-badge.json", + "tsxSize": 562, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\DataList.tsx", + "json": "src\\config\\pages\\atoms\\data-list.json", + "tsxSize": 1294, + "jsonSize": 94, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\DataSourceBadge.tsx", + "json": "src\\config\\pages\\atoms\\data-source-badge.json", + "tsxSize": 859, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\DataTable.tsx", + "json": "src\\config\\pages\\atoms\\data-table.json", + "tsxSize": 1952, + "jsonSize": 166, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\DatePicker.tsx", + "json": "src\\config\\pages\\atoms\\date-picker.json", + "tsxSize": 1275, + "jsonSize": 99, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\DetailRow.tsx", + "json": "src\\config\\pages\\atoms\\detail-row.json", + "tsxSize": 617, + "jsonSize": 49, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Divider.tsx", + "json": "src\\config\\pages\\atoms\\divider.json", + "tsxSize": 529, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Dot.tsx", + "json": "src\\config\\pages\\atoms\\dot.json", + "tsxSize": 1089, + "jsonSize": 35, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Drawer.tsx", + "json": "src\\config\\pages\\atoms\\drawer.json", + "tsxSize": 2166, + "jsonSize": 116, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\EmptyMessage.tsx", + "json": "src\\config\\pages\\atoms\\empty-message.json", + "tsxSize": 982, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\EmptyState.tsx", + "json": "src\\config\\pages\\atoms\\empty-state.json", + "tsxSize": 1111, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\EmptyStateIcon.tsx", + "json": "src\\config\\pages\\atoms\\empty-state-icon.json", + "tsxSize": 489, + "jsonSize": 46, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ErrorBadge.tsx", + "json": "src\\config\\pages\\atoms\\error-badge.json", + "tsxSize": 555, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\FileIcon.tsx", + "json": "src\\config\\pages\\atoms\\file-icon.json", + "tsxSize": 546, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\FileUpload.tsx", + "json": "src\\config\\pages\\atoms\\file-upload.json", + "tsxSize": 3772, + "jsonSize": 343, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\FilterInput.tsx", + "json": "src\\config\\pages\\atoms\\filter-input.json", + "tsxSize": 1295, + "jsonSize": 65, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\Flex.tsx", + "json": "src\\config\\pages\\atoms\\flex.json", + "tsxSize": 1704, + "jsonSize": 36, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Form.tsx", + "json": "src\\config\\pages\\atoms\\form.json", + "tsxSize": 706, + "jsonSize": 188, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\GlowCard.tsx", + "json": "src\\config\\pages\\atoms\\glow-card.json", + "tsxSize": 1637, + "jsonSize": 63, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Grid.tsx", + "json": "src\\config\\pages\\atoms\\grid.json", + "tsxSize": 765, + "jsonSize": 36, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Heading.tsx", + "json": "src\\config\\pages\\atoms\\heading.json", + "tsxSize": 600, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\HelperText.tsx", + "json": "src\\config\\pages\\atoms\\helper-text.json", + "tsxSize": 518, + "jsonSize": 42, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\HoverCard.tsx", + "json": "src\\config\\pages\\atoms\\hover-card.json", + "tsxSize": 730, + "jsonSize": 103, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\IconButton.tsx", + "json": "src\\config\\pages\\atoms\\icon-button.json", + "tsxSize": 792, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\IconText.tsx", + "json": "src\\config\\pages\\atoms\\icon-text.json", + "tsxSize": 710, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\IconWrapper.tsx", + "json": "src\\config\\pages\\atoms\\icon-wrapper.json", + "tsxSize": 705, + "jsonSize": 43, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Image.tsx", + "json": "src\\config\\pages\\atoms\\image.json", + "tsxSize": 1401, + "jsonSize": 329, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\InfoBox.tsx", + "json": "src\\config\\pages\\atoms\\info-box.json", + "tsxSize": 1217, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\InfoPanel.tsx", + "json": "src\\config\\pages\\atoms\\info-panel.json", + "tsxSize": 1189, + "jsonSize": 41, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Input.tsx", + "json": "src\\config\\pages\\atoms\\input.json", + "tsxSize": 1866, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Kbd.tsx", + "json": "src\\config\\pages\\atoms\\kbd.json", + "tsxSize": 468, + "jsonSize": 35, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\KeyValue.tsx", + "json": "src\\config\\pages\\atoms\\key-value.json", + "tsxSize": 756, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Label.tsx", + "json": "src\\config\\pages\\atoms\\label.json", + "tsxSize": 580, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Link.tsx", + "json": "src\\config\\pages\\atoms\\link.json", + "tsxSize": 1089, + "jsonSize": 63, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\List.tsx", + "json": "src\\config\\pages\\atoms\\list.json", + "tsxSize": 708, + "jsonSize": 71, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ListItem.tsx", + "json": "src\\config\\pages\\atoms\\list-item.json", + "tsxSize": 940, + "jsonSize": 67, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\LiveIndicator.tsx", + "json": "src\\config\\pages\\atoms\\live-indicator.json", + "tsxSize": 1104, + "jsonSize": 45, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\LoadingSpinner.tsx", + "json": "src\\config\\pages\\atoms\\loading-spinner.json", + "tsxSize": 493, + "jsonSize": 46, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\LoadingState.tsx", + "json": "src\\config\\pages\\atoms\\loading-state.json", + "tsxSize": 721, + "jsonSize": 44, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Menu.tsx", + "json": "src\\config\\pages\\atoms\\menu.json", + "tsxSize": 3147, + "jsonSize": 300, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": true, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\MetricCard.tsx", + "json": "src\\config\\pages\\atoms\\metric-card.json", + "tsxSize": 1226, + "jsonSize": 49, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\MetricDisplay.tsx", + "json": "src\\config\\pages\\atoms\\metric-display.json", + "tsxSize": 1393, + "jsonSize": 45, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Modal.tsx", + "json": "src\\config\\pages\\atoms\\modal.json", + "tsxSize": 1624, + "jsonSize": 64, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Notification.tsx", + "json": "src\\config\\pages\\atoms\\notification.json", + "tsxSize": 1718, + "jsonSize": 99, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\NumberInput.tsx", + "json": "src\\config\\pages\\atoms\\number-input.json", + "tsxSize": 2153, + "jsonSize": 81, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\PageHeader.tsx", + "json": "src\\config\\pages\\atoms\\page-header.json", + "tsxSize": 664, + "jsonSize": 42, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\PanelHeader.tsx", + "json": "src\\config\\pages\\atoms\\panel-header.json", + "tsxSize": 1466, + "jsonSize": 41, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\PasswordInput.tsx", + "json": "src\\config\\pages\\atoms\\password-input.json", + "tsxSize": 1241, + "jsonSize": 289, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\Popover.tsx", + "json": "src\\config\\pages\\atoms\\popover.json", + "tsxSize": 1744, + "jsonSize": 265, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": true, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\atoms\\ProgressBar.tsx", + "json": "src\\config\\pages\\atoms\\progress-bar.json", + "tsxSize": 1318, + "jsonSize": 43, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\PropertyEditorField.tsx", + "json": "src\\config\\pages\\atoms\\property-editor-field.json", + "tsxSize": 2214, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Pulse.tsx", + "json": "src\\config\\pages\\atoms\\pulse.json", + "tsxSize": 1235, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\QuickActionButton.tsx", + "json": "src\\config\\pages\\atoms\\quick-action-button.json", + "tsxSize": 1616, + "jsonSize": 63, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Radio.tsx", + "json": "src\\config\\pages\\atoms\\radio.json", + "tsxSize": 1738, + "jsonSize": 65, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\RangeSlider.tsx", + "json": "src\\config\\pages\\atoms\\range-slider.json", + "tsxSize": 1045, + "jsonSize": 66, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Rating.tsx", + "json": "src\\config\\pages\\atoms\\rating.json", + "tsxSize": 1805, + "jsonSize": 87, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ResponsiveGrid.tsx", + "json": "src\\config\\pages\\atoms\\responsive-grid.json", + "tsxSize": 1164, + "jsonSize": 46, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\ScrollArea.tsx", + "json": "src\\config\\pages\\atoms\\scroll-area.json", + "tsxSize": 1336, + "jsonSize": 68, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\SearchInput.tsx", + "json": "src\\config\\pages\\atoms\\search-input.json", + "tsxSize": 999, + "jsonSize": 96, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Section.tsx", + "json": "src\\config\\pages\\atoms\\section.json", + "tsxSize": 479, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\SeedDataStatus.tsx", + "json": "src\\config\\pages\\atoms\\seed-data-status.json", + "tsxSize": 2029, + "jsonSize": 128, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Select.tsx", + "json": "src\\config\\pages\\atoms\\select.json", + "tsxSize": 1707, + "jsonSize": 66, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Separator.tsx", + "json": "src\\config\\pages\\atoms\\separator.json", + "tsxSize": 471, + "jsonSize": 60, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Skeleton.tsx", + "json": "src\\config\\pages\\atoms\\skeleton.json", + "tsxSize": 746, + "jsonSize": 83, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Slider.tsx", + "json": "src\\config\\pages\\atoms\\slider.json", + "tsxSize": 2263, + "jsonSize": 66, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Spacer.tsx", + "json": "src\\config\\pages\\atoms\\spacer.json", + "tsxSize": 675, + "jsonSize": 81, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Sparkle.tsx", + "json": "src\\config\\pages\\atoms\\sparkle.json", + "tsxSize": 693, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Spinner.tsx", + "json": "src\\config\\pages\\atoms\\spinner.json", + "tsxSize": 359, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Stack.tsx", + "json": "src\\config\\pages\\atoms\\stack.json", + "tsxSize": 1284, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\StatCard.tsx", + "json": "src\\config\\pages\\atoms\\stat-card.json", + "tsxSize": 1484, + "jsonSize": 49, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\StatusBadge.tsx", + "json": "src\\config\\pages\\atoms\\status-badge.json", + "tsxSize": 779, + "jsonSize": 37, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\StatusIcon.tsx", + "json": "src\\config\\pages\\atoms\\status-icon.json", + "tsxSize": 667, + "jsonSize": 42, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\StepIndicator.tsx", + "json": "src\\config\\pages\\atoms\\step-indicator.json", + "tsxSize": 2078, + "jsonSize": 76, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Stepper.tsx", + "json": "src\\config\\pages\\atoms\\stepper.json", + "tsxSize": 2234, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Switch.tsx", + "json": "src\\config\\pages\\atoms\\switch.json", + "tsxSize": 1185, + "jsonSize": 89, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TabIcon.tsx", + "json": "src\\config\\pages\\atoms\\tab-icon.json", + "tsxSize": 412, + "jsonSize": 39, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Table.tsx", + "json": "src\\config\\pages\\atoms\\table.json", + "tsxSize": 2257, + "jsonSize": 102, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Tabs.tsx", + "json": "src\\config\\pages\\atoms\\tabs.json", + "tsxSize": 1920, + "jsonSize": 98, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Tag.tsx", + "json": "src\\config\\pages\\atoms\\tag.json", + "tsxSize": 1408, + "jsonSize": 63, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Text.tsx", + "json": "src\\config\\pages\\atoms\\text.json", + "tsxSize": 526, + "jsonSize": 36, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TextArea.tsx", + "json": "src\\config\\pages\\atoms\\text-area.json", + "tsxSize": 1337, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TextGradient.tsx", + "json": "src\\config\\pages\\atoms\\text-gradient.json", + "tsxSize": 785, + "jsonSize": 44, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TextHighlight.tsx", + "json": "src\\config\\pages\\atoms\\text-highlight.json", + "tsxSize": 899, + "jsonSize": 45, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Timeline.tsx", + "json": "src\\config\\pages\\atoms\\timeline.json", + "tsxSize": 2756, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Timestamp.tsx", + "json": "src\\config\\pages\\atoms\\timestamp.json", + "tsxSize": 740, + "jsonSize": 41, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TipsCard.tsx", + "json": "src\\config\\pages\\atoms\\tips-card.json", + "tsxSize": 834, + "jsonSize": 72, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Toggle.tsx", + "json": "src\\config\\pages\\atoms\\toggle.json", + "tsxSize": 1544, + "jsonSize": 66, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\Tooltip.tsx", + "json": "src\\config\\pages\\atoms\\tooltip.json", + "tsxSize": 776, + "jsonSize": 118, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\atoms\\TreeIcon.tsx", + "json": "src\\config\\pages\\atoms\\tree-icon.json", + "tsxSize": 345, + "jsonSize": 40, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\AppBranding.tsx", + "json": "src\\config\\pages\\molecules\\app-branding.json", + "tsxSize": 239, + "jsonSize": 43, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\BindingEditor.tsx", + "json": "src\\config\\pages\\molecules\\binding-editor.json", + "tsxSize": 4774, + "jsonSize": 84, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\molecules\\Breadcrumb.tsx", + "json": "src\\config\\pages\\molecules\\breadcrumb.json", + "tsxSize": 3901, + "jsonSize": 59, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\CanvasRenderer.tsx", + "json": "src\\config\\pages\\molecules\\canvas-renderer.json", + "tsxSize": 4039, + "jsonSize": 539, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\CodeExplanationDialog.tsx", + "json": "src\\config\\pages\\molecules\\code-explanation-dialog.json", + "tsxSize": 1381, + "jsonSize": 144, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\ComponentPalette.tsx", + "json": "src\\config\\pages\\molecules\\component-palette.json", + "tsxSize": 2112, + "jsonSize": 103, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\DataSourceCard.tsx", + "json": "src\\config\\pages\\molecules\\data-source-card.json", + "tsxSize": 2285, + "jsonSize": 98, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\EditorActions.tsx", + "json": "src\\config\\pages\\molecules\\editor-actions.json", + "tsxSize": 722, + "jsonSize": 101, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\EditorToolbar.tsx", + "json": "src\\config\\pages\\molecules\\editor-toolbar.json", + "tsxSize": 1053, + "jsonSize": 160, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\EmptyEditorState.tsx", + "json": "src\\config\\pages\\molecules\\empty-editor-state.json", + "tsxSize": 436, + "jsonSize": 48, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\FileTabs.tsx", + "json": "src\\config\\pages\\molecules\\file-tabs.json", + "tsxSize": 1191, + "jsonSize": 101, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\LazyBarChart.tsx", + "json": "src\\config\\pages\\molecules\\lazy-bar-chart.json", + "tsxSize": 1455, + "jsonSize": 74, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\LazyInlineMonacoEditor.tsx", + "json": "src\\config\\pages\\molecules\\lazy-inline-monaco-editor.json", + "tsxSize": 1378, + "jsonSize": 82, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\LazyLineChart.tsx", + "json": "src\\config\\pages\\molecules\\lazy-line-chart.json", + "tsxSize": 1481, + "jsonSize": 74, + "tsxHasHooks": true, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\LazyMonacoEditor.tsx", + "json": "src\\config\\pages\\molecules\\lazy-monaco-editor.json", + "tsxSize": 1608, + "jsonSize": 76, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\MonacoEditorPanel.tsx", + "json": "src\\config\\pages\\molecules\\monaco-editor-panel.json", + "tsxSize": 341, + "jsonSize": 77, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\NavigationGroupHeader.tsx", + "json": "src\\config\\pages\\molecules\\navigation-group-header.json", + "tsxSize": 887, + "jsonSize": 50, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\PropertyEditor.tsx", + "json": "src\\config\\pages\\molecules\\property-editor.json", + "tsxSize": 2066, + "jsonSize": 114, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\SearchBar.tsx", + "json": "src\\config\\pages\\molecules\\search-bar.json", + "tsxSize": 970, + "jsonSize": 69, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\SearchInput.tsx", + "json": "src\\config\\pages\\molecules\\search-input.json", + "tsxSize": 1061, + "jsonSize": 90, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\ToolbarButton.tsx", + "json": "src\\config\\pages\\molecules\\toolbar-button.json", + "tsxSize": 722, + "jsonSize": 89, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\molecules\\TreeFormDialog.tsx", + "json": "src\\config\\pages\\molecules\\tree-form-dialog.json", + "tsxSize": 2081, + "jsonSize": 163, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\AppHeader.tsx", + "json": "src\\config\\pages\\organisms\\app-header.json", + "tsxSize": 2300, + "jsonSize": 280, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\DataSourceManager.tsx", + "json": "src\\config\\pages\\organisms\\data-source-manager.json", + "tsxSize": 4356, + "jsonSize": 213, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX has state/effects but JSON seems incomplete" + }, + { + "tsx": "src\\components\\organisms\\EmptyCanvasState.tsx", + "json": "src\\config\\pages\\organisms\\empty-canvas-state.json", + "tsxSize": 1248, + "jsonSize": 119, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\NavigationMenu.tsx", + "json": "src\\config\\pages\\organisms\\navigation-menu.json", + "tsxSize": 8194, + "jsonSize": 308, + "tsxHasHooks": true, + "tsxHasState": true, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX is large but JSON is small - might be missing content" + }, + { + "tsx": "src\\components\\organisms\\PageHeader.tsx", + "json": "src\\config\\pages\\organisms\\page-header.json", + "tsxSize": 931, + "jsonSize": 42, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaCodeViewer.tsx", + "json": "src\\config\\pages\\organisms\\schema-code-viewer.json", + "tsxSize": 1508, + "jsonSize": 72, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorCanvas.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-canvas.json", + "tsxSize": 1247, + "jsonSize": 212, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorLayout.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-layout.json", + "tsxSize": 2945, + "jsonSize": 692, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorPropertiesPanel.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-properties-panel.json", + "tsxSize": 2026, + "jsonSize": 302, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorSidebar.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-sidebar.json", + "tsxSize": 483, + "jsonSize": 82, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorStatusBar.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-status-bar.json", + "tsxSize": 1335, + "jsonSize": 53, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\SchemaEditorToolbar.tsx", + "json": "src\\config\\pages\\organisms\\schema-editor-toolbar.json", + "tsxSize": 2066, + "jsonSize": 181, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\ToolbarActions.tsx", + "json": "src\\config\\pages\\organisms\\toolbar-actions.json", + "tsxSize": 2141, + "jsonSize": 220, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "safe-to-delete", + "reason": "JSON definition exists" + }, + { + "tsx": "src\\components\\organisms\\TreeListPanel.tsx", + "json": "src\\config\\pages\\organisms\\tree-list-panel.json", + "tsxSize": 5359, + "jsonSize": 254, + "tsxHasHooks": false, + "tsxHasState": false, + "tsxHasEffects": false, + "jsonHasBindings": false, + "jsonHasChildren": false, + "recommendation": "needs-review", + "reason": "TSX is large but JSON is small - might be missing content" + } +] \ No newline at end of file diff --git a/json-components-registry.json b/json-components-registry.json index 4ea0db4..a36bdb6 100644 --- a/json-components-registry.json +++ b/json-components-registry.json @@ -40,7 +40,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -105,7 +104,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -212,7 +210,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -236,7 +233,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -255,7 +251,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -288,7 +283,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -312,7 +306,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -358,7 +351,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -388,7 +380,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -412,7 +403,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -427,7 +417,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -442,7 +431,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -466,7 +454,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -502,7 +489,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -527,7 +513,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -551,7 +536,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -566,7 +550,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -581,7 +564,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -596,7 +578,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -611,7 +592,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -626,7 +606,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -641,7 +620,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -656,7 +634,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -671,7 +648,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -686,7 +662,6 @@ "status": "supported", "source": "organisms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -701,7 +676,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -716,7 +690,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -731,7 +704,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -750,7 +722,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -765,7 +736,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -780,7 +750,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -833,7 +802,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -944,7 +912,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -973,7 +940,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -997,7 +963,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1030,7 +995,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1062,9 +1026,7 @@ "description": "ComponentBindingDialog component", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "ComponentBindingDialogWrapper" + "jsonCompatible": false }, { "type": "ComponentBindingDialogWrapper", @@ -1107,9 +1069,7 @@ "description": "ComponentTree component", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "ComponentTreeWrapper" + "jsonCompatible": false }, { "type": "ComponentTreeBuilder", @@ -1120,7 +1080,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1139,7 +1098,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1190,7 +1148,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1227,7 +1184,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1313,9 +1269,7 @@ "description": "DataSourceEditorDialog component", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "DataSourceEditorDialogWrapper" + "jsonCompatible": false }, { "type": "DataSourceEditorDialogWrapper", @@ -1377,7 +1331,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -1406,7 +1359,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1421,7 +1373,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1436,7 +1387,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1469,7 +1419,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1488,7 +1437,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1528,7 +1476,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -1654,7 +1601,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1697,7 +1643,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1716,7 +1661,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1735,7 +1679,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1830,7 +1773,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1844,9 +1786,7 @@ "description": "GitHubBuildStatus component", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "GitHubBuildStatusWrapper" + "jsonCompatible": false }, { "type": "GitHubBuildStatusWrapper", @@ -1952,7 +1892,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1976,7 +1915,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -1991,7 +1929,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2072,7 +2009,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2096,7 +2032,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -2125,7 +2060,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2144,7 +2078,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2163,7 +2096,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2214,7 +2146,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2247,9 +2178,7 @@ "description": "Lazy-loaded Recharts bar chart with runtime library loading", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "LazyBarChartWrapper" + "jsonCompatible": false }, { "type": "LazyBarChartWrapper", @@ -2273,9 +2202,7 @@ "description": "Lazy-loaded D3 bar chart with runtime library loading", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "LazyD3BarChartWrapper" + "jsonCompatible": false }, { "type": "LazyD3BarChartWrapper", @@ -2309,9 +2236,7 @@ "description": "Lazy-loaded Recharts line chart with runtime library loading", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "LazyLineChartWrapper" + "jsonCompatible": false }, { "type": "LazyLineChartWrapper", @@ -2643,7 +2568,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2662,7 +2586,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2693,7 +2616,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2717,7 +2639,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2732,7 +2653,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2765,7 +2685,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2812,7 +2731,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2849,7 +2767,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2903,7 +2820,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2940,7 +2856,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -2970,9 +2885,7 @@ "description": "Save status indicator with hook-driven state", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "SaveIndicatorWrapper" + "jsonCompatible": false }, { "type": "SaveIndicatorWrapper", @@ -3067,7 +2980,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3143,9 +3055,7 @@ "description": "Seed data management with app-level hook state", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "SeedDataManagerWrapper" + "jsonCompatible": false }, { "type": "SeedDataManagerWrapper", @@ -3188,7 +3098,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3212,7 +3121,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3251,7 +3159,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -3289,7 +3196,6 @@ "status": "supported", "source": "organisms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3304,7 +3210,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3328,7 +3233,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -3357,7 +3261,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -3478,9 +3381,7 @@ "description": "Storage settings controls with hook-driven state", "status": "supported", "source": "molecules", - "jsonCompatible": false, - "wrapperRequired": true, - "wrapperComponent": "StorageSettingsWrapper" + "jsonCompatible": false }, { "type": "StorageSettingsWrapper", @@ -3505,7 +3406,6 @@ "status": "supported", "source": "custom", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3524,7 +3424,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3548,7 +3447,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3572,7 +3470,6 @@ "status": "supported", "source": "ui", "jsonCompatible": false, - "wrapperRequired": true, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true, @@ -3601,7 +3498,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3661,7 +3557,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3685,7 +3580,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3700,7 +3594,6 @@ "status": "supported", "source": "organisms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3715,7 +3608,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3734,7 +3626,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3753,7 +3644,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3790,7 +3680,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3872,7 +3761,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3905,7 +3793,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3940,7 +3827,6 @@ "status": "supported", "source": "ui", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3964,7 +3850,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3979,7 +3864,6 @@ "status": "supported", "source": "atoms", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true @@ -3994,7 +3878,6 @@ "status": "supported", "source": "molecules", "jsonCompatible": true, - "wrapperRequired": false, "metadata": { "conversionDate": "2026-01-18", "autoGenerated": true diff --git a/package-lock.json b/package-lock.json index 5a1d9c3..a8bdd24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,6 +89,7 @@ "eslint-plugin-react-refresh": "^0.4.19", "globals": "^17.0.0", "tailwindcss": "^4.1.11", + "terser": "^5.46.0", "tsx": "^4.21.0", "typescript": "~5.7.2", "typescript-eslint": "^8.38.0", @@ -822,6 +823,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "license": "MIT" @@ -4673,7 +4685,7 @@ }, "node_modules/acorn": { "version": "8.15.0", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4756,6 +4768,13 @@ "concat-map": "0.0.1" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/callsites": { "version": "3.1.0", "dev": true, @@ -6971,6 +6990,16 @@ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "license": "BSD-3-Clause", @@ -6978,6 +7007,17 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/state-local": { "version": "1.0.7", "license": "MIT" @@ -7038,6 +7078,32 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/terser": { + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/three": { "version": "0.175.0", "license": "MIT" diff --git a/package.json b/package.json index 98642c5..2c06cf6 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "components:list": "node scripts/list-json-components.cjs", "components:generate-types": "tsx scripts/generate-json-ui-component-types.ts", "components:scan": "node scripts/scan-and-update-registry.cjs", - "components:validate": "node scripts/validate-supported-components.cjs && tsx scripts/validate-json-registry.ts" + "components:validate": "node scripts/validate-supported-components.cjs && tsx scripts/validate-json-registry.ts", + "audit:json": "tsx scripts/audit-json-components.ts" }, "dependencies": { "@heroicons/react": "^2.2.0", @@ -111,6 +112,7 @@ "eslint-plugin-react-refresh": "^0.4.19", "globals": "^17.0.0", "tailwindcss": "^4.1.11", + "terser": "^5.46.0", "tsx": "^4.21.0", "typescript": "~5.7.2", "typescript-eslint": "^8.38.0", diff --git a/scripts/analyze-duplicates.ts b/scripts/analyze-duplicates.ts new file mode 100644 index 0000000..2ea9754 --- /dev/null +++ b/scripts/analyze-duplicates.ts @@ -0,0 +1,190 @@ +#!/usr/bin/env tsx +/** + * Analyze duplicate TSX files before deletion + * Check JSON contents to ensure they're complete + */ + +import fs from 'fs' +import path from 'path' +import { globSync } from 'fs' + +const ROOT_DIR = path.resolve(process.cwd()) +const CONFIG_PAGES_DIR = path.join(ROOT_DIR, 'src/config/pages') +const COMPONENTS_DIR = path.join(ROOT_DIR, 'src/components') +const JSON_DEFS_DIR = path.join(ROOT_DIR, 'src/components/json-definitions') + +function toKebabCase(str: string): string { + return str.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '') +} + +interface AnalysisResult { + tsx: string + json: string + tsxSize: number + jsonSize: number + tsxHasHooks: boolean + tsxHasState: boolean + tsxHasEffects: boolean + jsonHasBindings: boolean + jsonHasChildren: boolean + recommendation: 'safe-to-delete' | 'needs-review' | 'keep-tsx' + reason: string +} + +async function analyzeTsxFile(filePath: string): Promise<{ + hasHooks: boolean + hasState: boolean + hasEffects: boolean +}> { + const content = fs.readFileSync(filePath, 'utf-8') + + return { + hasHooks: /use[A-Z]/.test(content), + hasState: /useState|useReducer/.test(content), + hasEffects: /useEffect|useLayoutEffect/.test(content) + } +} + +async function analyzeJsonFile(filePath: string): Promise<{ + hasBindings: boolean + hasChildren: boolean + size: number +}> { + const content = fs.readFileSync(filePath, 'utf-8') + const json = JSON.parse(content) + + return { + hasBindings: !!json.bindings || hasNestedBindings(json), + hasChildren: !!json.children, + size: content.length + } +} + +function hasNestedBindings(obj: any): boolean { + if (!obj || typeof obj !== 'object') return false + if (obj.bindings) return true + + for (const key in obj) { + if (hasNestedBindings(obj[key])) return true + } + return false +} + +async function analyzeDuplicates() { + console.log('🔍 Analyzing duplicate TSX files...\n') + + const results: AnalysisResult[] = [] + + // Find all TSX files in atoms, molecules, organisms + const categories = ['atoms', 'molecules', 'organisms'] + + for (const category of categories) { + const tsxFiles = globSync(path.join(COMPONENTS_DIR, category, '*.tsx')) + + for (const tsxFile of tsxFiles) { + const basename = path.basename(tsxFile, '.tsx') + const kebab = toKebabCase(basename) + + // Check for JSON equivalent in config/pages + const jsonPath = path.join(CONFIG_PAGES_DIR, category, `${kebab}.json`) + + if (!fs.existsSync(jsonPath)) continue + + // Check for JSON definition + const jsonDefPath = path.join(JSON_DEFS_DIR, `${kebab}.json`) + + // Analyze both files + const tsxAnalysis = await analyzeTsxFile(tsxFile) + const tsxSize = fs.statSync(tsxFile).size + + let jsonAnalysis = { hasBindings: false, hasChildren: false, size: 0 } + let actualJsonPath = jsonPath + + if (fs.existsSync(jsonDefPath)) { + jsonAnalysis = await analyzeJsonFile(jsonDefPath) + actualJsonPath = jsonDefPath + } else if (fs.existsSync(jsonPath)) { + jsonAnalysis = await analyzeJsonFile(jsonPath) + } + + // Determine recommendation + let recommendation: AnalysisResult['recommendation'] = 'safe-to-delete' + let reason = 'JSON definition exists' + + if (tsxAnalysis.hasState || tsxAnalysis.hasEffects) { + if (!jsonAnalysis.hasBindings && jsonAnalysis.size < 500) { + recommendation = 'needs-review' + reason = 'TSX has state/effects but JSON seems incomplete' + } else { + recommendation = 'safe-to-delete' + reason = 'TSX has hooks but JSON should handle via createJsonComponentWithHooks' + } + } + + if (tsxSize > 5000 && jsonAnalysis.size < 1000) { + recommendation = 'needs-review' + reason = 'TSX is large but JSON is small - might be missing content' + } + + results.push({ + tsx: path.relative(ROOT_DIR, tsxFile), + json: path.relative(ROOT_DIR, actualJsonPath), + tsxSize, + jsonSize: jsonAnalysis.size, + tsxHasHooks: tsxAnalysis.hasHooks, + tsxHasState: tsxAnalysis.hasState, + tsxHasEffects: tsxAnalysis.hasEffects, + jsonHasBindings: jsonAnalysis.hasBindings, + jsonHasChildren: jsonAnalysis.hasChildren, + recommendation, + reason + }) + } + } + + // Print results + console.log(`📊 Found ${results.length} duplicate components\n`) + + const safeToDelete = results.filter(r => r.recommendation === 'safe-to-delete') + const needsReview = results.filter(r => r.recommendation === 'needs-review') + const keepTsx = results.filter(r => r.recommendation === 'keep-tsx') + + console.log(`✅ Safe to delete: ${safeToDelete.length}`) + console.log(`⚠️ Needs review: ${needsReview.length}`) + console.log(`🔴 Keep TSX: ${keepTsx.length}\n`) + + if (needsReview.length > 0) { + console.log('⚠️ NEEDS REVIEW:') + console.log('='.repeat(80)) + for (const result of needsReview.slice(0, 10)) { + console.log(`\n${result.tsx}`) + console.log(` → ${result.json}`) + console.log(` TSX: ${result.tsxSize} bytes | JSON: ${result.jsonSize} bytes`) + console.log(` TSX hooks: ${result.tsxHasHooks} | state: ${result.tsxHasState} | effects: ${result.tsxHasEffects}`) + console.log(` JSON bindings: ${result.jsonHasBindings} | children: ${result.jsonHasChildren}`) + console.log(` Reason: ${result.reason}`) + } + if (needsReview.length > 10) { + console.log(`\n... and ${needsReview.length - 10} more`) + } + } + + // Write full report + const reportPath = path.join(ROOT_DIR, 'duplicate-analysis.json') + fs.writeFileSync(reportPath, JSON.stringify(results, null, 2)) + console.log(`\n📄 Full report written to: ${reportPath}`) + + // Generate deletion script for safe components + if (safeToDelete.length > 0) { + const deletionScript = safeToDelete.map(r => `rm "${r.tsx}"`).join('\n') + const scriptPath = path.join(ROOT_DIR, 'delete-duplicates.sh') + fs.writeFileSync(scriptPath, deletionScript) + console.log(`📝 Deletion script written to: ${scriptPath}`) + console.log(` Run: bash delete-duplicates.sh`) + } +} + +analyzeDuplicates().catch(error => { + console.error('❌ Analysis failed:', error) + process.exit(1) +}) diff --git a/scripts/audit-json-components.ts b/scripts/audit-json-components.ts new file mode 100644 index 0000000..7dea507 --- /dev/null +++ b/scripts/audit-json-components.ts @@ -0,0 +1,302 @@ +#!/usr/bin/env tsx +/** + * Audit script for JSON component definitions + * + * Goals: + * 1. Phase out src/components TSX files + * 2. Audit existing JSON definitions for completeness and correctness + */ + +import fs from 'fs' +import path from 'path' +import { globSync } from 'fs' + +interface AuditIssue { + severity: 'error' | 'warning' | 'info' + category: string + file?: string + message: string + suggestion?: string +} + +interface AuditReport { + timestamp: string + issues: AuditIssue[] + stats: { + totalJsonFiles: number + totalTsxFiles: number + registryEntries: number + orphanedJson: number + duplicates: number + obsoleteWrapperRefs: number + } +} + +const ROOT_DIR = path.resolve(process.cwd()) +const CONFIG_PAGES_DIR = path.join(ROOT_DIR, 'src/config/pages') +const COMPONENTS_DIR = path.join(ROOT_DIR, 'src/components') +const JSON_DEFS_DIR = path.join(ROOT_DIR, 'src/components/json-definitions') +const REGISTRY_FILE = path.join(ROOT_DIR, 'json-components-registry.json') + +async function loadRegistry(): Promise { + const content = fs.readFileSync(REGISTRY_FILE, 'utf-8') + return JSON.parse(content) +} + +function findAllFiles(pattern: string, cwd: string = ROOT_DIR): string[] { + const fullPattern = path.join(cwd, pattern) + return globSync(fullPattern, { ignore: '**/node_modules/**' }) +} + +function toKebabCase(str: string): string { + return str.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '') +} + +function toPascalCase(str: string): string { + return str + .split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join('') +} + +async function auditJsonComponents(): Promise { + const issues: AuditIssue[] = [] + const registry = await loadRegistry() + + // Find all files + const jsonFiles = findAllFiles('src/config/pages/**/*.json') + const tsxFiles = findAllFiles('src/components/**/*.tsx') + const jsonDefFiles = findAllFiles('src/components/json-definitions/*.json') + + console.log(`📊 Found ${jsonFiles.length} JSON files in config/pages`) + console.log(`📊 Found ${tsxFiles.length} TSX files in src/components`) + console.log(`📊 Found ${jsonDefFiles.length} JSON definitions`) + console.log(`📊 Found ${registry.components?.length || 0} registry entries\n`) + + // Build registry lookup maps + const registryByType = new Map() + const registryByName = new Map() + + if (registry.components) { + for (const component of registry.components) { + if (component.type) registryByType.set(component.type, component) + if (component.name) registryByName.set(component.name, component) + } + } + + // Check 1: Find TSX files that have JSON equivalents in config/pages + console.log('🔍 Checking for TSX files that could be replaced with JSON...') + const tsxBasenames = new Set() + for (const tsxFile of tsxFiles) { + const basename = path.basename(tsxFile, '.tsx') + const dir = path.dirname(tsxFile) + const category = path.basename(dir) // atoms, molecules, organisms + + if (!['atoms', 'molecules', 'organisms'].includes(category)) continue + + tsxBasenames.add(basename) + const kebab = toKebabCase(basename) + + // Check if there's a corresponding JSON file in config/pages + const possibleJsonPath = path.join(CONFIG_PAGES_DIR, category, `${kebab}.json`) + + if (fs.existsSync(possibleJsonPath)) { + issues.push({ + severity: 'warning', + category: 'duplicate-implementation', + file: tsxFile, + message: `TSX file has JSON equivalent at ${path.relative(ROOT_DIR, possibleJsonPath)}`, + suggestion: `Consider removing TSX and routing through JSON renderer` + }) + } + } + + // Check 2: Find JSON files without registry entries + console.log('🔍 Checking for orphaned JSON files...') + for (const jsonFile of jsonFiles) { + const content = JSON.parse(fs.readFileSync(jsonFile, 'utf-8')) + const componentType = content.type + + if (componentType && !registryByType.has(componentType)) { + issues.push({ + severity: 'error', + category: 'orphaned-json', + file: jsonFile, + message: `JSON file references type "${componentType}" which is not in registry`, + suggestion: `Add registry entry for ${componentType} in json-components-registry.json` + }) + } + } + + // Check 3: Find components with obsolete wrapper references + console.log('🔍 Checking for obsolete wrapper references...') + for (const component of registry.components || []) { + if (component.wrapperRequired || component.wrapperComponent) { + issues.push({ + severity: 'warning', + category: 'obsolete-wrapper-ref', + file: `registry: ${component.type}`, + message: `Component "${component.type}" has obsolete wrapperRequired/wrapperComponent fields`, + suggestion: `Remove wrapperRequired and wrapperComponent fields - use createJsonComponentWithHooks instead` + }) + } + } + + // Check 4: Find components with load.path that don't exist + console.log('🔍 Checking for broken load paths...') + for (const component of registry.components || []) { + if (component.load?.path) { + const loadPath = component.load.path.replace('@/', 'src/') + const possibleExtensions = ['.tsx', '.ts', '.jsx', '.js'] + let found = false + + for (const ext of possibleExtensions) { + if (fs.existsSync(path.join(ROOT_DIR, loadPath + ext))) { + found = true + break + } + } + + if (!found) { + issues.push({ + severity: 'error', + category: 'broken-load-path', + file: `registry: ${component.type}`, + message: `Component "${component.type}" has load.path "${component.load.path}" but file not found`, + suggestion: `Fix or remove load.path in registry` + }) + } + } + } + + // Check 5: Components in src/components/molecules without JSON definitions + console.log('🔍 Checking molecules without JSON definitions...') + const moleculeTsxFiles = tsxFiles.filter(f => f.includes('/molecules/')) + const jsonDefBasenames = new Set( + jsonDefFiles.map(f => path.basename(f, '.json')) + ) + + for (const tsxFile of moleculeTsxFiles) { + const basename = path.basename(tsxFile, '.tsx') + const kebab = toKebabCase(basename) + + if (!jsonDefBasenames.has(kebab) && registryByType.has(basename)) { + const entry = registryByType.get(basename) + if (entry.source === 'molecules' && !entry.load?.path) { + issues.push({ + severity: 'info', + category: 'potential-conversion', + file: tsxFile, + message: `Molecule "${basename}" could potentially be converted to JSON`, + suggestion: `Evaluate if ${basename} can be expressed as pure JSON` + }) + } + } + } + + const stats = { + totalJsonFiles: jsonFiles.length, + totalTsxFiles: tsxFiles.length, + registryEntries: registry.components?.length || 0, + orphanedJson: issues.filter(i => i.category === 'orphaned-json').length, + duplicates: issues.filter(i => i.category === 'duplicate-implementation').length, + obsoleteWrapperRefs: issues.filter(i => i.category === 'obsolete-wrapper-ref').length + } + + return { + timestamp: new Date().toISOString(), + issues, + stats + } +} + +function printReport(report: AuditReport) { + console.log('\n' + '='.repeat(80)) + console.log('📋 AUDIT REPORT') + console.log('='.repeat(80)) + console.log(`\n📅 Generated: ${report.timestamp}\n`) + + console.log('📈 Statistics:') + console.log(` • Total JSON files: ${report.stats.totalJsonFiles}`) + console.log(` • Total TSX files: ${report.stats.totalTsxFiles}`) + console.log(` • Registry entries: ${report.stats.registryEntries}`) + console.log(` • Orphaned JSON: ${report.stats.orphanedJson}`) + console.log(` • Obsolete wrapper refs: ${report.stats.obsoleteWrapperRefs}`) + console.log(` • Duplicate implementations: ${report.stats.duplicates}\n`) + + // Group issues by category + const byCategory = new Map() + for (const issue of report.issues) { + if (!byCategory.has(issue.category)) { + byCategory.set(issue.category, []) + } + byCategory.get(issue.category)!.push(issue) + } + + // Print issues by severity + const severityOrder = ['error', 'warning', 'info'] as const + const severityIcons = { error: '❌', warning: '⚠️', info: 'ℹ️' } + + for (const severity of severityOrder) { + const issuesOfSeverity = report.issues.filter(i => i.severity === severity) + if (issuesOfSeverity.length === 0) continue + + console.log(`\n${severityIcons[severity]} ${severity.toUpperCase()} (${issuesOfSeverity.length})`) + console.log('-'.repeat(80)) + + const categories = new Map() + for (const issue of issuesOfSeverity) { + if (!categories.has(issue.category)) { + categories.set(issue.category, []) + } + categories.get(issue.category)!.push(issue) + } + + for (const [category, issues] of categories) { + console.log(`\n ${category.replace(/-/g, ' ').toUpperCase()} (${issues.length}):`) + + for (const issue of issues.slice(0, 5)) { // Show first 5 of each category + console.log(` • ${issue.file || 'N/A'}`) + console.log(` ${issue.message}`) + if (issue.suggestion) { + console.log(` 💡 ${issue.suggestion}`) + } + } + + if (issues.length > 5) { + console.log(` ... and ${issues.length - 5} more`) + } + } + } + + console.log('\n' + '='.repeat(80)) + console.log(`Total issues found: ${report.issues.length}`) + console.log('='.repeat(80) + '\n') +} + +async function main() { + console.log('🔍 Starting JSON component audit...\n') + + const report = await auditJsonComponents() + + printReport(report) + + // Write report to file + const reportPath = path.join(ROOT_DIR, 'audit-report.json') + fs.writeFileSync(reportPath, JSON.stringify(report, null, 2)) + console.log(`📄 Full report written to: ${reportPath}\n`) + + // Exit with error code if there are errors + const errorCount = report.issues.filter(i => i.severity === 'error').length + if (errorCount > 0) { + console.log(`❌ Audit failed with ${errorCount} errors`) + process.exit(1) + } else { + console.log('✅ Audit completed successfully') + } +} + +main().catch(error => { + console.error('❌ Audit failed:', error) + process.exit(1) +}) diff --git a/scripts/cleanup-registry.ts b/scripts/cleanup-registry.ts new file mode 100644 index 0000000..687e53a --- /dev/null +++ b/scripts/cleanup-registry.ts @@ -0,0 +1,64 @@ +#!/usr/bin/env tsx +/** + * Cleanup script to remove obsolete wrapper references from registry + */ + +import fs from 'fs' +import path from 'path' + +const REGISTRY_FILE = path.resolve(process.cwd(), 'json-components-registry.json') + +async function cleanupRegistry() { + console.log('🧹 Cleaning up registry...\n') + + // Read registry + const content = fs.readFileSync(REGISTRY_FILE, 'utf-8') + const registry = JSON.parse(content) + + let cleanedCount = 0 + const cleanedComponents: string[] = [] + + // Remove obsolete fields from all components + if (registry.components) { + for (const component of registry.components) { + let modified = false + + if (component.wrapperRequired !== undefined) { + delete component.wrapperRequired + modified = true + } + + if (component.wrapperComponent !== undefined) { + delete component.wrapperComponent + modified = true + } + + if (modified) { + cleanedCount++ + cleanedComponents.push(component.type || component.name || 'Unknown') + } + } + } + + // Write back to file with proper formatting + fs.writeFileSync(REGISTRY_FILE, JSON.stringify(registry, null, 2) + '\n') + + console.log(`✅ Cleaned ${cleanedCount} components\n`) + + if (cleanedComponents.length > 0) { + console.log('📋 Cleaned components:') + cleanedComponents.slice(0, 10).forEach(name => { + console.log(` • ${name}`) + }) + if (cleanedComponents.length > 10) { + console.log(` ... and ${cleanedComponents.length - 10} more`) + } + } + + console.log('\n✨ Registry cleanup complete!') +} + +cleanupRegistry().catch(error => { + console.error('❌ Cleanup failed:', error) + process.exit(1) +}) diff --git a/scripts/fix-index-files.ts b/scripts/fix-index-files.ts new file mode 100644 index 0000000..28b69a8 --- /dev/null +++ b/scripts/fix-index-files.ts @@ -0,0 +1,41 @@ +#!/usr/bin/env tsx +/** + * Fix index.ts files to only export existing TSX files + */ + +import fs from 'fs' +import path from 'path' +import { globSync } from 'fs' + +const ROOT_DIR = path.resolve(process.cwd()) +const COMPONENTS_DIR = path.join(ROOT_DIR, 'src/components') + +const categories = ['atoms', 'molecules', 'organisms'] + +for (const category of categories) { + const categoryDir = path.join(COMPONENTS_DIR, category) + const indexPath = path.join(categoryDir, 'index.ts') + + if (!fs.existsSync(indexPath)) continue + + // Find all TSX files in this category + const tsxFiles = globSync(path.join(categoryDir, '*.tsx')) + const basenames = tsxFiles.map(f => path.basename(f, '.tsx')) + + console.log(`\n📁 ${category}/`) + console.log(` Found ${basenames.length} TSX files`) + + // Generate new exports + const exports = basenames + .sort() + .map(name => `export { ${name} } from './${name}'`) + .join('\n') + + // Write new index file + const content = `// Auto-generated - only exports existing TSX files\n${exports}\n` + fs.writeFileSync(indexPath, content) + + console.log(` ✅ Updated ${category}/index.ts`) +} + +console.log('\n✨ All index files updated!') diff --git a/src/components/DataBindingDesigner.tsx b/src/components/DataBindingDesigner.tsx index b2fa87a..c77d650 100644 --- a/src/components/DataBindingDesigner.tsx +++ b/src/components/DataBindingDesigner.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { DataSourceManager } from '@/components/organisms/DataSourceManager' -import { ComponentBindingDialog } from '@/components/molecules/ComponentBindingDialog' +import { ComponentBindingDialog } from '@/lib/json-ui/json-components' import { DataSource, UIComponent } from '@/types/json-ui' import { DataBindingHeader } from '@/components/data-binding-designer/DataBindingHeader' import { ComponentBindingsCard } from '@/components/data-binding-designer/ComponentBindingsCard' diff --git a/src/components/atoms/Accordion.tsx b/src/components/atoms/Accordion.tsx deleted file mode 100644 index fe4a4c7..0000000 --- a/src/components/atoms/Accordion.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useState } from 'react' -import { CaretDown } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface AccordionItem { - id: string - title: string - content: React.ReactNode - disabled?: boolean -} - -interface AccordionProps { - items: AccordionItem[] - type?: 'single' | 'multiple' - defaultOpen?: string[] - className?: string -} - -export function Accordion({ items, type = 'single', defaultOpen = [], className }: AccordionProps) { - const [openItems, setOpenItems] = useState(defaultOpen) - - const toggleItem = (id: string) => { - if (type === 'single') { - setOpenItems(openItems.includes(id) ? [] : [id]) - } else { - setOpenItems( - openItems.includes(id) - ? openItems.filter((item) => item !== id) - : [...openItems, id] - ) - } - } - - return ( -
- {items.map((item) => { - const isOpen = openItems.includes(item.id) - - return ( -
- - {isOpen && ( -
- {item.content} -
- )} -
- ) - })} -
- ) -} diff --git a/src/components/atoms/ActionButton.tsx b/src/components/atoms/ActionButton.tsx deleted file mode 100644 index c870cac..0000000 --- a/src/components/atoms/ActionButton.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { ReactNode } from 'react' -import { Button } from '@/components/ui/button' -import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from '@/components/ui/tooltip' - -export interface ActionButtonProps { - icon?: ReactNode - label: string - onClick: () => void - variant?: 'default' | 'outline' | 'ghost' | 'destructive' - size?: 'default' | 'sm' | 'lg' | 'icon' - tooltip?: string - disabled?: boolean - className?: string -} - -export function ActionButton({ - icon, - label, - onClick, - variant = 'default', - size = 'default', - tooltip, - disabled, - className, -}: ActionButtonProps) { - const button = ( - - ) - - if (tooltip) { - return ( - - - {button} - {tooltip} - - - ) - } - - return button -} diff --git a/src/components/atoms/ActionCard.tsx b/src/components/atoms/ActionCard.tsx deleted file mode 100644 index cdd9bc2..0000000 --- a/src/components/atoms/ActionCard.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { cn } from '@/lib/utils' -import { Card, CardContent } from '@/components/ui/card' -import { CaretRight } from '@phosphor-icons/react' - -interface ActionCardProps { - icon?: React.ReactNode - title: string - description?: string - onClick?: () => void - className?: string - disabled?: boolean -} - -export function ActionCard({ icon, title, description, onClick, className, disabled }: ActionCardProps) { - return ( - - -
- {icon && ( -
- {icon} -
- )} -
-
{title}
- {description && ( -
{description}
- )} -
- -
-
-
- ) -} diff --git a/src/components/atoms/ActionIcon.tsx b/src/components/atoms/ActionIcon.tsx deleted file mode 100644 index ea64248..0000000 --- a/src/components/atoms/ActionIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Plus, Pencil, Trash, Copy, Download, Upload } from '@phosphor-icons/react' - -interface ActionIconProps { - action: 'add' | 'edit' | 'delete' | 'copy' | 'download' | 'upload' - size?: number - weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone' - className?: string -} - -export function ActionIcon({ action, size = 16, weight = 'regular', className = '' }: ActionIconProps) { - const iconMap = { - add: Plus, - edit: Pencil, - delete: Trash, - copy: Copy, - download: Download, - upload: Upload, - } - - const IconComponent = iconMap[action] - return -} diff --git a/src/components/atoms/Alert.tsx b/src/components/atoms/Alert.tsx deleted file mode 100644 index f456881..0000000 --- a/src/components/atoms/Alert.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { ReactNode } from 'react' -import { Info, Warning, CheckCircle, XCircle } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface AlertProps { - variant?: 'info' | 'warning' | 'success' | 'error' - title?: string - children: ReactNode - className?: string -} - -const variantConfig = { - info: { - icon: Info, - classes: 'bg-blue-50 border-blue-200 text-blue-900', - }, - warning: { - icon: Warning, - classes: 'bg-yellow-50 border-yellow-200 text-yellow-900', - }, - success: { - icon: CheckCircle, - classes: 'bg-green-50 border-green-200 text-green-900', - }, - error: { - icon: XCircle, - classes: 'bg-red-50 border-red-200 text-red-900', - }, -} - -export function Alert({ variant = 'info', title, children, className }: AlertProps) { - const config = variantConfig[variant] - const Icon = config.icon - - return ( -
- -
- {title &&
{title}
} -
{children}
-
-
- ) -} diff --git a/src/components/atoms/AppLogo.tsx b/src/components/atoms/AppLogo.tsx deleted file mode 100644 index 7977dc4..0000000 --- a/src/components/atoms/AppLogo.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Code } from '@phosphor-icons/react' - -export function AppLogo() { - return ( -
- -
- ) -} diff --git a/src/components/atoms/Avatar.tsx b/src/components/atoms/Avatar.tsx deleted file mode 100644 index fd5083a..0000000 --- a/src/components/atoms/Avatar.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { cn } from '@/lib/utils' - -interface AvatarProps { - src?: string - alt?: string - fallback?: string - size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' - className?: string -} - -const sizeClasses = { - xs: 'w-6 h-6 text-xs', - sm: 'w-8 h-8 text-sm', - md: 'w-10 h-10 text-base', - lg: 'w-12 h-12 text-lg', - xl: 'w-16 h-16 text-xl', -} - -export function Avatar({ src, alt, fallback, size = 'md', className }: AvatarProps) { - const initials = fallback || alt?.slice(0, 2).toUpperCase() || '?' - - return ( -
- {src ? ( - {alt} - ) : ( - {initials} - )} -
- ) -} diff --git a/src/components/atoms/AvatarGroup.tsx b/src/components/atoms/AvatarGroup.tsx deleted file mode 100644 index da7b7ed..0000000 --- a/src/components/atoms/AvatarGroup.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { cn } from '@/lib/utils' - -interface AvatarGroupProps { - avatars: { - src?: string - alt: string - fallback: string - }[] - max?: number - size?: 'xs' | 'sm' | 'md' | 'lg' - className?: string -} - -const sizeClasses = { - xs: 'h-6 w-6 text-xs', - sm: 'h-8 w-8 text-xs', - md: 'h-10 w-10 text-sm', - lg: 'h-12 w-12 text-base', -} - -export function AvatarGroup({ - avatars, - max = 5, - size = 'md', - className, -}: AvatarGroupProps) { - const displayAvatars = avatars.slice(0, max) - const remainingCount = Math.max(avatars.length - max, 0) - - return ( -
- {displayAvatars.map((avatar, index) => ( -
- {avatar.src ? ( - {avatar.alt} - ) : ( - {avatar.fallback} - )} -
- ))} - {remainingCount > 0 && ( -
- +{remainingCount} -
- )} -
- ) -} diff --git a/src/components/atoms/Badge.tsx b/src/components/atoms/Badge.tsx deleted file mode 100644 index 0ac64be..0000000 --- a/src/components/atoms/Badge.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Badge as ShadcnBadge } from '@/components/ui/badge' -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface BadgeProps { - children: ReactNode - variant?: 'default' | 'secondary' | 'destructive' | 'outline' - size?: 'sm' | 'md' | 'lg' - icon?: ReactNode - className?: string -} - -const sizeClasses = { - sm: 'text-xs px-2 py-0.5', - md: 'text-sm px-2.5 py-0.5', - lg: 'text-base px-3 py-1', -} - -export function Badge({ - children, - variant = 'default', - size = 'md', - icon, - className, -}: BadgeProps) { - return ( - - {icon && {icon}} - {children} - - ) -} diff --git a/src/components/atoms/BindingIndicator.tsx b/src/components/atoms/BindingIndicator.tsx deleted file mode 100644 index 045a76a..0000000 --- a/src/components/atoms/BindingIndicator.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Link } from '@phosphor-icons/react' -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' - -interface BindingIndicatorProps { - sourceId: string - path?: string - className?: string -} - -export function BindingIndicator({ sourceId, path, className = '' }: BindingIndicatorProps) { - const bindingText = path ? `${sourceId}.${path}` : sourceId - - return ( - - - -
- - {bindingText} -
-
- -

Bound to: {bindingText}

-
-
-
- ) -} diff --git a/src/components/atoms/Breadcrumb.tsx b/src/components/atoms/Breadcrumb.tsx deleted file mode 100644 index 5134007..0000000 --- a/src/components/atoms/Breadcrumb.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { CaretRight } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface BreadcrumbItem { - label: string - href?: string - onClick?: () => void -} - -interface BreadcrumbNavProps { - items?: BreadcrumbItem[] - className?: string -} - -export function BreadcrumbNav({ items = [], className }: BreadcrumbNavProps) { - return ( - - ) -} - -export const Breadcrumb = BreadcrumbNav diff --git a/src/components/atoms/Button.tsx b/src/components/atoms/Button.tsx deleted file mode 100644 index ed0ce5b..0000000 --- a/src/components/atoms/Button.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Button as ShadcnButton, ButtonProps as ShadcnButtonProps } from '@/components/ui/button' -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -export interface ButtonProps extends ShadcnButtonProps { - children: ReactNode - leftIcon?: ReactNode - rightIcon?: ReactNode - loading?: boolean - fullWidth?: boolean -} - -export function Button({ - children, - leftIcon, - rightIcon, - loading, - fullWidth, - disabled, - className, - ...props -}: ButtonProps) { - return ( - - {loading ? ( -
-
- {children} -
- ) : ( -
- {leftIcon && {leftIcon}} - {children} - {rightIcon && {rightIcon}} -
- )} - - ) -} diff --git a/src/components/atoms/ButtonGroup.tsx b/src/components/atoms/ButtonGroup.tsx deleted file mode 100644 index 1141b89..0000000 --- a/src/components/atoms/ButtonGroup.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface ButtonGroupProps { - children: ReactNode - orientation?: 'horizontal' | 'vertical' - className?: string -} - -export function ButtonGroup({ - children, - orientation = 'horizontal', - className, -}: ButtonGroupProps) { - return ( -
button]:rounded-none', - '[&>button:first-child]:rounded-l-md', - '[&>button:last-child]:rounded-r-md', - orientation === 'vertical' && '[&>button:first-child]:rounded-t-md [&>button:first-child]:rounded-l-none', - orientation === 'vertical' && '[&>button:last-child]:rounded-b-md [&>button:last-child]:rounded-r-none', - '[&>button:not(:last-child)]:border-r-0', - orientation === 'vertical' && '[&>button:not(:last-child)]:border-b-0 [&>button:not(:last-child)]:border-r', - className - )} - > - {children} -
- ) -} diff --git a/src/components/atoms/Calendar.tsx b/src/components/atoms/Calendar.tsx deleted file mode 100644 index 68c6a86..0000000 --- a/src/components/atoms/Calendar.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Calendar as ShadcnCalendar } from '@/components/ui/calendar' -import { cn } from '@/lib/utils' - -interface CalendarProps { - selected?: Date - onSelect?: (date: Date | undefined) => void - mode?: 'single' | 'multiple' | 'range' - disabled?: Date | ((date: Date) => boolean) - className?: string -} - -export function Calendar({ - selected, - onSelect, - mode = 'single', - disabled, - className, -}: CalendarProps) { - return ( - - ) -} diff --git a/src/components/atoms/Card.tsx b/src/components/atoms/Card.tsx deleted file mode 100644 index 21f2ca7..0000000 --- a/src/components/atoms/Card.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { cn } from '@/lib/utils' - -interface CardProps { - children: React.ReactNode - variant?: 'default' | 'bordered' | 'elevated' | 'flat' - padding?: 'none' | 'sm' | 'md' | 'lg' - hover?: boolean - className?: string - onClick?: () => void -} - -export function Card({ - children, - variant = 'default', - padding = 'md', - hover = false, - className, - onClick -}: CardProps) { - const variantStyles = { - default: 'bg-card border border-border', - bordered: 'bg-background border-2 border-border', - elevated: 'bg-card shadow-lg border border-border', - flat: 'bg-muted', - } - - const paddingStyles = { - none: 'p-0', - sm: 'p-3', - md: 'p-6', - lg: 'p-8', - } - - return ( -
- {children} -
- ) -} diff --git a/src/components/atoms/Checkbox.tsx b/src/components/atoms/Checkbox.tsx deleted file mode 100644 index e5cf5dd..0000000 --- a/src/components/atoms/Checkbox.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Check, Minus } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface CheckboxProps { - checked: boolean - onChange: (checked: boolean) => void - label?: string - indeterminate?: boolean - disabled?: boolean - size?: 'sm' | 'md' | 'lg' - className?: string -} - -export function Checkbox({ - checked, - onChange, - label, - indeterminate = false, - disabled = false, - size = 'md', - className -}: CheckboxProps) { - const sizeStyles = { - sm: 'w-4 h-4', - md: 'w-5 h-5', - lg: 'w-6 h-6', - } - - const iconSize = { - sm: 12, - md: 16, - lg: 20, - } - - return ( - - ) -} diff --git a/src/components/atoms/Chip.tsx b/src/components/atoms/Chip.tsx deleted file mode 100644 index fb36da5..0000000 --- a/src/components/atoms/Chip.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { ReactNode } from 'react' -import { X } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface ChipProps { - children: ReactNode - variant?: 'default' | 'primary' | 'accent' | 'muted' - size?: 'sm' | 'md' - onRemove?: () => void - className?: string -} - -const variantClasses = { - default: 'bg-secondary text-secondary-foreground', - primary: 'bg-primary text-primary-foreground', - accent: 'bg-accent text-accent-foreground', - muted: 'bg-muted text-muted-foreground', -} - -const sizeClasses = { - sm: 'px-2 py-0.5 text-xs', - md: 'px-3 py-1 text-sm', -} - -export function Chip({ - children, - variant = 'default', - size = 'md', - onRemove, - className -}: ChipProps) { - return ( - - {children} - {onRemove && ( - - )} - - ) -} diff --git a/src/components/atoms/CircularProgress.tsx b/src/components/atoms/CircularProgress.tsx deleted file mode 100644 index 412f937..0000000 --- a/src/components/atoms/CircularProgress.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Progress } from '@/components/ui/progress' -import { cn } from '@/lib/utils' - -interface CircularProgressProps { - value: number - max?: number - size?: 'sm' | 'md' | 'lg' | 'xl' - showLabel?: boolean - strokeWidth?: number - className?: string -} - -const sizeClasses = { - sm: { dimension: 48, stroke: 4, fontSize: 'text-xs' }, - md: { dimension: 64, stroke: 5, fontSize: 'text-sm' }, - lg: { dimension: 96, stroke: 6, fontSize: 'text-base' }, - xl: { dimension: 128, stroke: 8, fontSize: 'text-lg' }, -} - -export function CircularProgress({ - value, - max = 100, - size = 'md', - showLabel = true, - strokeWidth, - className, -}: CircularProgressProps) { - const { dimension, stroke, fontSize } = sizeClasses[size] - const actualStroke = strokeWidth || stroke - const percentage = Math.min((value / max) * 100, 100) - const radius = (dimension - actualStroke) / 2 - const circumference = radius * 2 * Math.PI - const offset = circumference - (percentage / 100) * circumference - - return ( -
- - - - - {showLabel && ( - - {Math.round(percentage)}% - - )} -
- ) -} diff --git a/src/components/atoms/Code.tsx b/src/components/atoms/Code.tsx deleted file mode 100644 index 0416b4c..0000000 --- a/src/components/atoms/Code.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface CodeProps { - children: ReactNode - inline?: boolean - className?: string -} - -export function Code({ children, inline = true, className }: CodeProps) { - if (inline) { - return ( - - {children} - - ) - } - - return ( -
-      {children}
-    
- ) -} diff --git a/src/components/atoms/ColorSwatch.tsx b/src/components/atoms/ColorSwatch.tsx deleted file mode 100644 index 28e38cb..0000000 --- a/src/components/atoms/ColorSwatch.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Check } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface ColorSwatchProps { - color: string - selected?: boolean - onClick?: () => void - size?: 'sm' | 'md' | 'lg' - label?: string - className?: string -} - -export function ColorSwatch({ - color, - selected = false, - onClick, - size = 'md', - label, - className -}: ColorSwatchProps) { - const sizeStyles = { - sm: 'w-6 h-6', - md: 'w-8 h-8', - lg: 'w-10 h-10', - } - - return ( -
- - {label && {label}} -
- ) -} diff --git a/src/components/atoms/CommandPalette.tsx b/src/components/atoms/CommandPalette.tsx deleted file mode 100644 index fa68e28..0000000 --- a/src/components/atoms/CommandPalette.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { - Command, - CommandDialog, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from '@/components/ui/command' -import { ReactNode } from 'react' - -interface CommandOption { - value: string - label: string - icon?: ReactNode - onSelect?: () => void -} - -interface CommandPaletteProps { - open: boolean - onOpenChange: (open: boolean) => void - placeholder?: string - emptyMessage?: string - groups: { - heading?: string - items: CommandOption[] - }[] -} - -export function CommandPalette({ - open, - onOpenChange, - placeholder = 'Type a command or search...', - emptyMessage = 'No results found.', - groups, -}: CommandPaletteProps) { - return ( - - - - {emptyMessage} - {groups.map((group, groupIndex) => ( - - {group.items.map((item) => ( - { - item.onSelect?.() - onOpenChange(false) - }} - > - {item.icon && {item.icon}} - {item.label} - - ))} - - ))} - - - ) -} diff --git a/src/components/atoms/CompletionCard.tsx b/src/components/atoms/CompletionCard.tsx deleted file mode 100644 index 98ebed8..0000000 --- a/src/components/atoms/CompletionCard.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' -import { Badge } from '@/components/ui/badge' -import { Progress } from '@/components/ui/progress' -import { CheckCircle } from '@phosphor-icons/react' - -interface CompletionCardProps { - completionScore: number - completionMessage: string - isReadyToExport: boolean -} - -export function CompletionCard({ - completionScore, - completionMessage, - isReadyToExport -}: CompletionCardProps) { - return ( - - - - - Project Completeness - - Overall progress of your application - - -
- {completionScore}% - - {isReadyToExport ? 'Ready to Export' : 'In Progress'} - -
- -

{completionMessage}

-
-
- ) -} diff --git a/src/components/atoms/ComponentPaletteItem.tsx b/src/components/atoms/ComponentPaletteItem.tsx deleted file mode 100644 index 5bc47e1..0000000 --- a/src/components/atoms/ComponentPaletteItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { ComponentDefinition } from '@/lib/component-definition-types' -import { Card } from '@/components/ui/card' -import * as Icons from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface ComponentPaletteItemProps { - component: ComponentDefinition - onDragStart: (component: ComponentDefinition, e: React.DragEvent) => void - className?: string -} - -export function ComponentPaletteItem({ component, onDragStart, className }: ComponentPaletteItemProps) { - const IconComponent = (Icons as any)[component.icon] || Icons.Cube - - return ( - onDragStart(component, e)} - className={cn( - 'p-3 cursor-move hover:bg-accent/50 hover:border-accent transition-all', - 'flex flex-col items-center gap-2 text-center', - 'hover:scale-105 active:scale-95', - className - )} - > - - {component.label} - {component.type} - - ) -} diff --git a/src/components/atoms/ComponentTreeNode.tsx b/src/components/atoms/ComponentTreeNode.tsx deleted file mode 100644 index 1655ea2..0000000 --- a/src/components/atoms/ComponentTreeNode.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { UIComponent } from '@/types/json-ui' -import { getComponentDef } from '@/lib/component-definition-utils' -import { cn } from '@/lib/utils' -import * as Icons from '@phosphor-icons/react' - -interface ComponentTreeNodeProps { - component: UIComponent - isSelected: boolean - isHovered: boolean - isDraggedOver: boolean - dropPosition: 'before' | 'after' | 'inside' | null - onSelect: () => void - onHover: () => void - onHoverEnd: () => void - onDragStart: (e: React.DragEvent) => void - onDragOver: (e: React.DragEvent) => void - onDragLeave: (e: React.DragEvent) => void - onDrop: (e: React.DragEvent) => void - depth?: number - hasChildren?: boolean - isExpanded?: boolean - onToggleExpand?: () => void -} - -export function ComponentTreeNode({ - component, - isSelected, - isHovered, - isDraggedOver, - dropPosition, - onSelect, - onHover, - onHoverEnd, - onDragStart, - onDragOver, - onDragLeave, - onDrop, - depth = 0, - hasChildren = false, - isExpanded = false, - onToggleExpand, -}: ComponentTreeNodeProps) { - const def = getComponentDef(component.type) - const IconComponent = def ? (Icons as any)[def.icon] || Icons.Cube : Icons.Cube - - return ( -
- {isDraggedOver && dropPosition === 'before' && ( -
- )} - -
{ - e.stopPropagation() - onSelect() - }} - onMouseEnter={onHover} - onMouseLeave={onHoverEnd} - style={{ paddingLeft: `${depth * 16}px` }} - className={cn( - 'flex items-center gap-2 px-3 py-2 text-sm cursor-pointer', - 'hover:bg-muted/50 transition-colors', - 'border-l-2 border-transparent', - isSelected && 'bg-accent/20 border-l-accent', - isHovered && !isSelected && 'bg-muted/30', - isDraggedOver && dropPosition === 'inside' && 'bg-primary/10' - )} - > - {hasChildren ? ( - - ) : ( -
- )} - - {def?.label || component.type} - {component.id} -
- - {isDraggedOver && dropPosition === 'after' && ( -
- )} -
- ) -} diff --git a/src/components/atoms/ConfirmButton.tsx b/src/components/atoms/ConfirmButton.tsx deleted file mode 100644 index 0fc0f03..0000000 --- a/src/components/atoms/ConfirmButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Button, ButtonProps } from '@/components/ui/button' -import { cn } from '@/lib/utils' - -interface ConfirmButtonProps extends Omit { - onConfirm: () => void | Promise - confirmText?: string - isLoading?: boolean -} - -export function ConfirmButton({ - onConfirm, - confirmText = 'Are you sure?', - isLoading, - children, - className, - ...props -}: ConfirmButtonProps) { - const handleClick = async () => { - if (window.confirm(confirmText)) { - await onConfirm() - } - } - - return ( - - ) -} diff --git a/src/components/atoms/Container.tsx b/src/components/atoms/Container.tsx deleted file mode 100644 index e913ad5..0000000 --- a/src/components/atoms/Container.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface ContainerProps { - children: ReactNode - size?: 'sm' | 'md' | 'lg' | 'xl' | 'full' - className?: string -} - -const sizeClasses = { - sm: 'max-w-screen-sm', - md: 'max-w-screen-md', - lg: 'max-w-screen-lg', - xl: 'max-w-screen-xl', - full: 'max-w-full', -} - -export function Container({ children, size = 'xl', className }: ContainerProps) { - return ( -
- {children} -
- ) -} diff --git a/src/components/atoms/ContextMenu.tsx b/src/components/atoms/ContextMenu.tsx deleted file mode 100644 index 20eacd4..0000000 --- a/src/components/atoms/ContextMenu.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { - ContextMenu as ShadcnContextMenu, - ContextMenuContent, - ContextMenuItem, - ContextMenuTrigger, - ContextMenuSeparator, - ContextMenuSub, - ContextMenuSubContent, - ContextMenuSubTrigger, -} from '@/components/ui/context-menu' -import { ReactNode } from 'react' - -export interface ContextMenuItemType { - label: string - icon?: ReactNode - shortcut?: string - onSelect?: () => void - disabled?: boolean - separator?: boolean - submenu?: ContextMenuItemType[] -} - -interface ContextMenuProps { - trigger: ReactNode - items: ContextMenuItemType[] -} - -export function ContextMenu({ trigger, items }: ContextMenuProps) { - const renderItems = (menuItems: ContextMenuItemType[]) => { - return menuItems.map((item, index) => { - if (item.separator) { - return - } - - if (item.submenu && item.submenu.length > 0) { - return ( - - - {item.icon && {item.icon}} - {item.label} - - - {renderItems(item.submenu)} - - - ) - } - - return ( - - {item.icon && {item.icon}} - {item.label} - {item.shortcut && ( - - {item.shortcut} - - )} - - ) - }) - } - - return ( - - {trigger} - {renderItems(items)} - - ) -} diff --git a/src/components/atoms/CopyButton.tsx b/src/components/atoms/CopyButton.tsx deleted file mode 100644 index c3b352f..0000000 --- a/src/components/atoms/CopyButton.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Copy, Check } from '@phosphor-icons/react' -import { useState } from 'react' -import { cn } from '@/lib/utils' - -interface CopyButtonProps { - text: string - size?: 'sm' | 'md' | 'lg' - className?: string -} - -export function CopyButton({ text, size = 'md', className }: CopyButtonProps) { - const [copied, setCopied] = useState(false) - - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(text) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } catch (error) { - console.error('Failed to copy:', error) - } - } - - const sizeStyles = { - sm: 'p-1', - md: 'p-2', - lg: 'p-3', - } - - const iconSize = { - sm: 12, - md: 16, - lg: 20, - } - - return ( - - ) -} diff --git a/src/components/atoms/CountBadge.tsx b/src/components/atoms/CountBadge.tsx deleted file mode 100644 index 80a747d..0000000 --- a/src/components/atoms/CountBadge.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Badge } from '@/components/ui/badge' -import { cn } from '@/lib/utils' - -interface CountBadgeProps { - count: number - max?: number - variant?: 'default' | 'secondary' | 'destructive' | 'outline' - className?: string -} - -export function CountBadge({ count, max, variant = 'default', className }: CountBadgeProps) { - const displayValue = max && count > max ? `${max}+` : count.toString() - - if (count === 0) return null - - return ( - - {displayValue} - - ) -} diff --git a/src/components/atoms/DataList.tsx b/src/components/atoms/DataList.tsx deleted file mode 100644 index 109cb41..0000000 --- a/src/components/atoms/DataList.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -export interface DataListProps { - items: any[] - renderItem?: (item: any, index: number) => ReactNode - emptyMessage?: string - className?: string - itemClassName?: string - itemKey?: string -} - -export function DataList({ - items, - renderItem, - emptyMessage = 'No items', - className, - itemClassName, - itemKey, -}: DataListProps) { - if (items.length === 0) { - return ( -
- {emptyMessage} -
- ) - } - - const renderFallbackItem = (item: any) => { - if (itemKey && item && typeof item === 'object') { - const value = item[itemKey] - if (value !== undefined && value !== null) { - return typeof value === 'string' || typeof value === 'number' - ? value - : JSON.stringify(value) - } - } - - if (typeof item === 'string' || typeof item === 'number') { - return item - } - - return JSON.stringify(item) - } - - return ( -
- {items.map((item, index) => ( -
- {renderItem ? renderItem(item, index) : renderFallbackItem(item)} -
- ))} -
- ) -} diff --git a/src/components/atoms/DataSourceBadge.tsx b/src/components/atoms/DataSourceBadge.tsx deleted file mode 100644 index 0837490..0000000 --- a/src/components/atoms/DataSourceBadge.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Badge } from '@/components/ui/badge' -import { DataSourceType } from '@/types/json-ui' -import { Database, File } from '@phosphor-icons/react' - -interface DataSourceBadgeProps { - type: DataSourceType - className?: string -} - -const dataSourceConfig = { - kv: { - icon: Database, - label: 'KV Storage', - className: 'bg-accent/20 text-accent border-accent/30' - }, - static: { - icon: File, - label: 'Static', - className: 'bg-muted text-muted-foreground border-border' - } -} - -export function DataSourceBadge({ type, className = '' }: DataSourceBadgeProps) { - const config = dataSourceConfig[type] - const Icon = config.icon - - return ( - - - {config.label} - - ) -} diff --git a/src/components/atoms/DataTable.tsx b/src/components/atoms/DataTable.tsx deleted file mode 100644 index b9f170a..0000000 --- a/src/components/atoms/DataTable.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@/components/ui/table' -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -export interface Column { - key: string - header: string | ReactNode - cell?: (item: T) => ReactNode - sortable?: boolean - width?: string -} - -interface DataTableProps { - data: T[] - columns: Column[] - onRowClick?: (item: T) => void - emptyMessage?: string - className?: string -} - -export function DataTable>({ - data, - columns, - onRowClick, - emptyMessage = 'No data available', - className, -}: DataTableProps) { - return ( -
- - - - {columns.map((column) => ( - - {column.header} - - ))} - - - - {data.length === 0 ? ( - - - {emptyMessage} - - - ) : ( - data.map((item, rowIndex) => ( - onRowClick?.(item)} - className={cn(onRowClick && 'cursor-pointer')} - > - {columns.map((column) => ( - - {column.cell ? column.cell(item) : item[column.key]} - - ))} - - )) - )} - -
-
- ) -} diff --git a/src/components/atoms/DatePicker.tsx b/src/components/atoms/DatePicker.tsx deleted file mode 100644 index 4dc95a0..0000000 --- a/src/components/atoms/DatePicker.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' -import { Button } from '@/components/ui/button' -import { Calendar } from '@/components/ui/calendar' -import { CalendarBlank } from '@phosphor-icons/react' -import { format } from 'date-fns' -import { cn } from '@/lib/utils' - -interface DatePickerProps { - value?: Date - onChange: (date: Date | undefined) => void - placeholder?: string - disabled?: boolean - className?: string -} - -export function DatePicker({ - value, - onChange, - placeholder = 'Pick a date', - disabled, - className, -}: DatePickerProps) { - return ( - - - - - - - - - ) -} diff --git a/src/components/atoms/DetailRow.tsx b/src/components/atoms/DetailRow.tsx deleted file mode 100644 index 7d46e46..0000000 --- a/src/components/atoms/DetailRow.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Card, CardContent } from '@/components/ui/card' -import { Badge } from '@/components/ui/badge' - -interface DetailRowProps { - icon: React.ReactNode - label: string - value: number -} - -export function DetailRow({ icon, label, value }: DetailRowProps) { - return ( -
-
- {icon} - {label} -
- {value} -
- ) -} diff --git a/src/components/atoms/Divider.tsx b/src/components/atoms/Divider.tsx deleted file mode 100644 index 9f87515..0000000 --- a/src/components/atoms/Divider.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { cn } from '@/lib/utils' - -interface DividerProps { - orientation?: 'horizontal' | 'vertical' - className?: string - decorative?: boolean -} - -export function Divider({ - orientation = 'horizontal', - className, - decorative = true -}: DividerProps) { - return ( -
- ) -} diff --git a/src/components/atoms/Dot.tsx b/src/components/atoms/Dot.tsx deleted file mode 100644 index c64addf..0000000 --- a/src/components/atoms/Dot.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { cn } from '@/lib/utils' - -interface DotProps { - variant?: 'default' | 'primary' | 'accent' | 'success' | 'warning' | 'error' - size?: 'xs' | 'sm' | 'md' | 'lg' - pulse?: boolean - className?: string -} - -const variantClasses = { - default: 'bg-muted-foreground', - primary: 'bg-primary', - accent: 'bg-accent', - success: 'bg-green-500', - warning: 'bg-yellow-500', - error: 'bg-destructive', -} - -const sizeClasses = { - xs: 'w-1.5 h-1.5', - sm: 'w-2 h-2', - md: 'w-3 h-3', - lg: 'w-4 h-4', -} - -export function Dot({ - variant = 'default', - size = 'sm', - pulse = false, - className -}: DotProps) { - return ( - - - {pulse && ( - - )} - - ) -} diff --git a/src/components/atoms/Drawer.tsx b/src/components/atoms/Drawer.tsx deleted file mode 100644 index d4138ad..0000000 --- a/src/components/atoms/Drawer.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { X } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface DrawerProps { - isOpen: boolean - onClose: () => void - title?: string - children: React.ReactNode - position?: 'left' | 'right' | 'top' | 'bottom' - size?: 'sm' | 'md' | 'lg' - showCloseButton?: boolean - className?: string -} - -export function Drawer({ - isOpen, - onClose, - title, - children, - position = 'right', - size = 'md', - showCloseButton = true, - className, -}: DrawerProps) { - if (!isOpen) return null - - const positionStyles = { - left: 'left-0 top-0 h-full', - right: 'right-0 top-0 h-full', - top: 'top-0 left-0 w-full', - bottom: 'bottom-0 left-0 w-full', - } - - const sizeStyles = { - sm: position === 'left' || position === 'right' ? 'w-64' : 'h-64', - md: position === 'left' || position === 'right' ? 'w-96' : 'h-96', - lg: position === 'left' || position === 'right' ? 'w-[600px]' : 'h-[600px]', - } - - const slideAnimation = { - left: 'animate-in slide-in-from-left', - right: 'animate-in slide-in-from-right', - top: 'animate-in slide-in-from-top', - bottom: 'animate-in slide-in-from-bottom', - } - - return ( - <> -
-
- {(title || showCloseButton) && ( -
- {title &&

{title}

} - {showCloseButton && ( - - )} -
- )} -
{children}
-
- - ) -} diff --git a/src/components/atoms/EmptyMessage.tsx b/src/components/atoms/EmptyMessage.tsx deleted file mode 100644 index 66cdaf6..0000000 --- a/src/components/atoms/EmptyMessage.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { cn } from '@/lib/utils' -import { Button } from '@/components/ui/button' - -interface EmptyMessageProps { - icon?: React.ReactNode - title: string - description?: string - action?: { - label: string - onClick: () => void - } - className?: string -} - -export function EmptyMessage({ icon, title, description, action, className }: EmptyMessageProps) { - return ( -
- {icon && ( -
- {icon} -
- )} -

{title}

- {description && ( -

- {description} -

- )} - {action && ( - - )} -
- ) -} diff --git a/src/components/atoms/EmptyState.tsx b/src/components/atoms/EmptyState.tsx deleted file mode 100644 index 60c3365..0000000 --- a/src/components/atoms/EmptyState.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' -import { Button } from '@/components/ui/button' - -export interface EmptyStateProps { - icon?: ReactNode - title: string - description?: string - action?: { - label: string - onClick: () => void - } - children?: ReactNode - className?: string -} - -export function EmptyState({ - icon, - title, - description, - action, - children, - className, -}: EmptyStateProps) { - return ( -
- {icon && ( -
- {icon} -
- )} -
-

{title}

- {description && ( -

- {description} -

- )} -
- {action && ( - - )} - {children} -
- ) -} diff --git a/src/components/atoms/EmptyStateIcon.tsx b/src/components/atoms/EmptyStateIcon.tsx deleted file mode 100644 index 9c2153b..0000000 --- a/src/components/atoms/EmptyStateIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -interface EmptyStateIconProps { - icon: React.ReactNode - variant?: 'default' | 'muted' -} - -export function EmptyStateIcon({ icon, variant = 'muted' }: EmptyStateIconProps) { - const variantClasses = { - default: 'from-primary/20 to-accent/20 text-primary', - muted: 'from-muted to-muted/50 text-muted-foreground', - } - - return ( -
- {icon} -
- ) -} diff --git a/src/components/atoms/ErrorBadge.tsx b/src/components/atoms/ErrorBadge.tsx deleted file mode 100644 index 63cee88..0000000 --- a/src/components/atoms/ErrorBadge.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Badge } from '@/components/ui/badge' - -interface ErrorBadgeProps { - count: number - variant?: 'default' | 'destructive' - size?: 'sm' | 'md' -} - -export function ErrorBadge({ count, variant = 'destructive', size = 'md' }: ErrorBadgeProps) { - if (count === 0) return null - - const sizeClasses = { - sm: 'h-5 w-5 text-[10px]', - md: 'h-6 w-6 text-xs', - } - - return ( - - {count} - - ) -} diff --git a/src/components/atoms/FileIcon.tsx b/src/components/atoms/FileIcon.tsx deleted file mode 100644 index 385b75f..0000000 --- a/src/components/atoms/FileIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { FileCode, FileJs, FilePlus } from '@phosphor-icons/react' - -interface FileIconProps { - type?: 'code' | 'json' | 'plus' - size?: number - weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone' - className?: string -} - -export function FileIcon({ type = 'code', size = 20, weight = 'regular', className = '' }: FileIconProps) { - const iconMap = { - code: FileCode, - json: FileJs, - plus: FilePlus, - } - - const IconComponent = iconMap[type] - return -} diff --git a/src/components/atoms/FileUpload.tsx b/src/components/atoms/FileUpload.tsx deleted file mode 100644 index e942685..0000000 --- a/src/components/atoms/FileUpload.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { useState } from 'react' -import { UploadSimple, X } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface FileUploadProps { - accept?: string - multiple?: boolean - maxSize?: number - onFilesSelected: (files: File[]) => void - disabled?: boolean - className?: string -} - -export function FileUpload({ - accept, - multiple = false, - maxSize, - onFilesSelected, - disabled = false, - className -}: FileUploadProps) { - const [isDragging, setIsDragging] = useState(false) - const [selectedFiles, setSelectedFiles] = useState([]) - - const handleFiles = (files: FileList | null) => { - if (!files) return - - const fileArray = Array.from(files) - const validFiles = fileArray.filter(file => { - if (maxSize && file.size > maxSize) { - return false - } - return true - }) - - setSelectedFiles(validFiles) - onFilesSelected(validFiles) - } - - const handleDrop = (e: React.DragEvent) => { - e.preventDefault() - setIsDragging(false) - if (!disabled) { - handleFiles(e.dataTransfer.files) - } - } - - const handleDragOver = (e: React.DragEvent) => { - e.preventDefault() - if (!disabled) { - setIsDragging(true) - } - } - - const handleDragLeave = () => { - setIsDragging(false) - } - - const removeFile = (index: number) => { - const newFiles = selectedFiles.filter((_, i) => i !== index) - setSelectedFiles(newFiles) - onFilesSelected(newFiles) - } - - return ( -
- - - {selectedFiles.length > 0 && ( -
- {selectedFiles.map((file, index) => ( -
-
-

{file.name}

-

- {(file.size / 1024).toFixed(1)} KB -

-
- -
- ))} -
- )} -
- ) -} diff --git a/src/components/atoms/FilterInput.tsx b/src/components/atoms/FilterInput.tsx deleted file mode 100644 index 305c410..0000000 --- a/src/components/atoms/FilterInput.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Input } from '@/components/ui/input' -import { MagnifyingGlass, X } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' -import { useState } from 'react' - -interface FilterInputProps { - value: string - onChange: (value: string) => void - placeholder?: string - className?: string -} - -export function FilterInput({ - value, - onChange, - placeholder = 'Filter...', - className, -}: FilterInputProps) { - const [isFocused, setIsFocused] = useState(false) - - return ( -
- - onChange(e.target.value)} - placeholder={placeholder} - onFocus={() => setIsFocused(true)} - onBlur={() => setIsFocused(false)} - className="pl-9 pr-9" - /> - {value && ( - - )} -
- ) -} diff --git a/src/components/atoms/Flex.tsx b/src/components/atoms/Flex.tsx deleted file mode 100644 index 7ac4d32..0000000 --- a/src/components/atoms/Flex.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface FlexProps { - children: ReactNode - direction?: 'row' | 'col' | 'row-reverse' | 'col-reverse' - align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline' - justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly' - gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' - wrap?: 'wrap' | 'nowrap' | 'wrap-reverse' - grow?: boolean - shrink?: boolean - className?: string -} - -const directionClasses = { - row: 'flex-row', - col: 'flex-col', - 'row-reverse': 'flex-row-reverse', - 'col-reverse': 'flex-col-reverse', -} - -const alignClasses = { - start: 'items-start', - center: 'items-center', - end: 'items-end', - stretch: 'items-stretch', - baseline: 'items-baseline', -} - -const justifyClasses = { - start: 'justify-start', - center: 'justify-center', - end: 'justify-end', - between: 'justify-between', - around: 'justify-around', - evenly: 'justify-evenly', -} - -const gapClasses = { - none: 'gap-0', - xs: 'gap-1', - sm: 'gap-2', - md: 'gap-4', - lg: 'gap-6', - xl: 'gap-8', -} - -const wrapClasses = { - wrap: 'flex-wrap', - nowrap: 'flex-nowrap', - 'wrap-reverse': 'flex-wrap-reverse', -} - -export function Flex({ - children, - direction = 'row', - align = 'stretch', - justify = 'start', - gap = 'md', - wrap = 'nowrap', - grow = false, - shrink = false, - className, -}: FlexProps) { - return ( -
- {children} -
- ) -} diff --git a/src/components/atoms/Form.tsx b/src/components/atoms/Form.tsx deleted file mode 100644 index 0cf6686..0000000 --- a/src/components/atoms/Form.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { - Form as ShadcnForm, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form' -import { UseFormReturn } from 'react-hook-form' -import { ReactNode } from 'react' - -interface FormProps { - form: UseFormReturn - onSubmit: (values: any) => void | Promise - children: ReactNode - className?: string -} - -export function Form({ form, onSubmit, children, className }: FormProps) { - return ( - -
- {children} -
-
- ) -} - -export { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } diff --git a/src/components/atoms/GlowCard.tsx b/src/components/atoms/GlowCard.tsx deleted file mode 100644 index 888380f..0000000 --- a/src/components/atoms/GlowCard.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Card } from '@/components/ui/card' -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface GlowCardProps { - children: ReactNode - glowColor?: 'primary' | 'accent' | 'success' | 'warning' | 'error' - intensity?: 'low' | 'medium' | 'high' - className?: string - onClick?: () => void -} - -export function GlowCard({ - children, - glowColor = 'primary', - intensity = 'medium', - className, - onClick, -}: GlowCardProps) { - const glowClasses = { - primary: { - low: 'shadow-primary/10', - medium: 'shadow-primary/20 hover:shadow-primary/30', - high: 'shadow-primary/30 hover:shadow-primary/50', - }, - accent: { - low: 'shadow-accent/10', - medium: 'shadow-accent/20 hover:shadow-accent/30', - high: 'shadow-accent/30 hover:shadow-accent/50', - }, - success: { - low: 'shadow-green-500/10', - medium: 'shadow-green-500/20 hover:shadow-green-500/30', - high: 'shadow-green-500/30 hover:shadow-green-500/50', - }, - warning: { - low: 'shadow-yellow-500/10', - medium: 'shadow-yellow-500/20 hover:shadow-yellow-500/30', - high: 'shadow-yellow-500/30 hover:shadow-yellow-500/50', - }, - error: { - low: 'shadow-red-500/10', - medium: 'shadow-red-500/20 hover:shadow-red-500/30', - high: 'shadow-red-500/30 hover:shadow-red-500/50', - }, - } - - return ( - - {children} - - ) -} diff --git a/src/components/atoms/Grid.tsx b/src/components/atoms/Grid.tsx deleted file mode 100644 index e2326d9..0000000 --- a/src/components/atoms/Grid.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { ReactNode } from 'react' - -interface GridProps { - children: ReactNode - cols?: 1 | 2 | 3 | 4 | 6 | 12 - gap?: 1 | 2 | 3 | 4 | 6 | 8 - className?: string -} - -const colsClasses = { - 1: 'grid-cols-1', - 2: 'grid-cols-1 md:grid-cols-2', - 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', - 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4', - 6: 'grid-cols-2 md:grid-cols-3 lg:grid-cols-6', - 12: 'grid-cols-3 md:grid-cols-6 lg:grid-cols-12', -} - -const gapClasses = { - 1: 'gap-1', - 2: 'gap-2', - 3: 'gap-3', - 4: 'gap-4', - 6: 'gap-6', - 8: 'gap-8', -} - -export function Grid({ children, cols = 1, gap = 4, className = '' }: GridProps) { - return ( -
- {children} -
- ) -} diff --git a/src/components/atoms/Heading.tsx b/src/components/atoms/Heading.tsx deleted file mode 100644 index 8f098dd..0000000 --- a/src/components/atoms/Heading.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ReactNode, createElement } from 'react' - -interface HeadingProps { - children: ReactNode - level?: 1 | 2 | 3 | 4 | 5 | 6 - className?: string -} - -const levelClasses = { - 1: 'text-4xl font-bold tracking-tight', - 2: 'text-3xl font-semibold tracking-tight', - 3: 'text-2xl font-semibold tracking-tight', - 4: 'text-xl font-semibold', - 5: 'text-lg font-medium', - 6: 'text-base font-medium', -} - -export function Heading({ children, level = 1, className = '' }: HeadingProps) { - return createElement( - `h${level}`, - { className: `${levelClasses[level]} ${className}` }, - children - ) -} diff --git a/src/components/atoms/HelperText.tsx b/src/components/atoms/HelperText.tsx deleted file mode 100644 index ce0cd33..0000000 --- a/src/components/atoms/HelperText.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface HelperTextProps { - children: ReactNode - variant?: 'default' | 'error' | 'success' - className?: string -} - -const variantClasses = { - default: 'text-muted-foreground', - error: 'text-destructive', - success: 'text-green-600', -} - -export function HelperText({ children, variant = 'default', className }: HelperTextProps) { - return ( -

- {children} -

- ) -} diff --git a/src/components/atoms/HoverCard.tsx b/src/components/atoms/HoverCard.tsx deleted file mode 100644 index 338fbbd..0000000 --- a/src/components/atoms/HoverCard.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { - HoverCard as ShadcnHoverCard, - HoverCardContent, - HoverCardTrigger, -} from '@/components/ui/hover-card' -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface HoverCardProps { - trigger: ReactNode - children: ReactNode - side?: 'top' | 'right' | 'bottom' | 'left' - align?: 'start' | 'center' | 'end' - className?: string -} - -export function HoverCard({ - trigger, - children, - side = 'bottom', - align = 'center', - className, -}: HoverCardProps) { - return ( - - {trigger} - - {children} - - - ) -} diff --git a/src/components/atoms/IconButton.tsx b/src/components/atoms/IconButton.tsx deleted file mode 100644 index f5ab784..0000000 --- a/src/components/atoms/IconButton.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Button } from '@/components/ui/button' -import { forwardRef } from 'react' - -interface IconButtonProps { - icon: React.ReactNode - onClick?: () => void - disabled?: boolean - variant?: 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' - size?: 'default' | 'sm' | 'lg' | 'icon' - title?: string - className?: string -} - -export const IconButton = forwardRef( - ({ icon, onClick, disabled, variant = 'ghost', size = 'icon', title, className }, ref) => { - return ( - - ) - } -) - -IconButton.displayName = 'IconButton' diff --git a/src/components/atoms/IconText.tsx b/src/components/atoms/IconText.tsx deleted file mode 100644 index 6582089..0000000 --- a/src/components/atoms/IconText.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { cn } from '@/lib/utils' - -interface IconTextProps { - icon: React.ReactNode - children: React.ReactNode - gap?: 'sm' | 'md' | 'lg' - align?: 'start' | 'center' | 'end' - className?: string -} - -export function IconText({ - icon, - children, - gap = 'md', - align = 'center', - className -}: IconTextProps) { - const gapStyles = { - sm: 'gap-1', - md: 'gap-2', - lg: 'gap-3', - } - - const alignStyles = { - start: 'items-start', - center: 'items-center', - end: 'items-end', - } - - return ( -
- {icon} - {children} -
- ) -} diff --git a/src/components/atoms/IconWrapper.tsx b/src/components/atoms/IconWrapper.tsx deleted file mode 100644 index 27bcf09..0000000 --- a/src/components/atoms/IconWrapper.tsx +++ /dev/null @@ -1,32 +0,0 @@ -interface IconWrapperProps { - icon: React.ReactNode - size?: 'sm' | 'md' | 'lg' - variant?: 'default' | 'muted' | 'primary' | 'destructive' - className?: string -} - -export function IconWrapper({ - icon, - size = 'md', - variant = 'default', - className = '' -}: IconWrapperProps) { - const sizeClasses = { - sm: 'w-4 h-4', - md: 'w-5 h-5', - lg: 'w-6 h-6', - } - - const variantClasses = { - default: 'text-foreground', - muted: 'text-muted-foreground', - primary: 'text-primary', - destructive: 'text-destructive', - } - - return ( - - {icon} - - ) -} diff --git a/src/components/atoms/Image.tsx b/src/components/atoms/Image.tsx deleted file mode 100644 index 415b3cd..0000000 --- a/src/components/atoms/Image.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useState } from 'react' -import { cn } from '@/lib/utils' - -interface ImageProps { - src: string - alt: string - width?: number | string - height?: number | string - fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down' - fallback?: string - className?: string - onLoad?: () => void - onError?: () => void -} - -export function Image({ - src, - alt, - width, - height, - fit = 'cover', - fallback, - className, - onLoad, - onError -}: ImageProps) { - const [error, setError] = useState(false) - const [loading, setLoading] = useState(true) - - const handleLoad = () => { - setLoading(false) - onLoad?.() - } - - const handleError = () => { - setError(true) - setLoading(false) - onError?.() - } - - const imgSrc = error && fallback ? fallback : src - - return ( -
- {loading && ( -
- )} - {alt} -
- ) -} diff --git a/src/components/atoms/InfoBox.tsx b/src/components/atoms/InfoBox.tsx deleted file mode 100644 index c49e752..0000000 --- a/src/components/atoms/InfoBox.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { cn } from '@/lib/utils' -import { Info, Warning, CheckCircle, XCircle } from '@phosphor-icons/react' - -interface InfoBoxProps { - type?: 'info' | 'warning' | 'success' | 'error' - title?: string - children: React.ReactNode - className?: string -} - -const iconMap = { - info: Info, - warning: Warning, - success: CheckCircle, - error: XCircle, -} - -const variantClasses = { - info: 'bg-blue-500/10 border-blue-500/20 text-blue-700 dark:text-blue-300', - warning: 'bg-yellow-500/10 border-yellow-500/20 text-yellow-700 dark:text-yellow-300', - success: 'bg-green-500/10 border-green-500/20 text-green-700 dark:text-green-300', - error: 'bg-destructive/10 border-destructive/20 text-destructive', -} - -export function InfoBox({ type = 'info', title, children, className }: InfoBoxProps) { - const Icon = iconMap[type] - - return ( -
- -
- {title &&
{title}
} -
{children}
-
-
- ) -} diff --git a/src/components/atoms/InfoPanel.tsx b/src/components/atoms/InfoPanel.tsx deleted file mode 100644 index df64750..0000000 --- a/src/components/atoms/InfoPanel.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface InfoPanelProps { - children: ReactNode - variant?: 'info' | 'warning' | 'success' | 'error' | 'default' - title?: string - icon?: ReactNode - className?: string -} - -const variantClasses = { - default: 'bg-card border-border', - info: 'bg-blue-500/10 border-blue-500/20 text-blue-700 dark:text-blue-300', - warning: 'bg-yellow-500/10 border-yellow-500/20 text-yellow-700 dark:text-yellow-300', - success: 'bg-green-500/10 border-green-500/20 text-green-700 dark:text-green-300', - error: 'bg-red-500/10 border-red-500/20 text-red-700 dark:text-red-300', -} - -export function InfoPanel({ - children, - variant = 'default', - title, - icon, - className, -}: InfoPanelProps) { - return ( -
- {(title || icon) && ( -
- {icon &&
{icon}
} - {title &&
{title}
} -
- )} -
{children}
-
- ) -} diff --git a/src/components/atoms/Input.tsx b/src/components/atoms/Input.tsx deleted file mode 100644 index 7b0f3e8..0000000 --- a/src/components/atoms/Input.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { forwardRef } from 'react' -import { cn } from '@/lib/utils' - -interface InputProps extends React.InputHTMLAttributes { - error?: boolean - helperText?: string - label?: string - leftIcon?: React.ReactNode - rightIcon?: React.ReactNode -} - -export const Input = forwardRef( - ({ error, helperText, label, leftIcon, rightIcon, className, ...props }, ref) => { - return ( -
- {label && ( - - )} -
- {leftIcon && ( -
- {leftIcon} -
- )} - - {rightIcon && ( -
- {rightIcon} -
- )} -
- {helperText && ( -

- {helperText} -

- )} -
- ) - } -) - -Input.displayName = 'Input' diff --git a/src/components/atoms/Kbd.tsx b/src/components/atoms/Kbd.tsx deleted file mode 100644 index 42e1e90..0000000 --- a/src/components/atoms/Kbd.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface KbdProps { - children: ReactNode - className?: string -} - -export function Kbd({ children, className }: KbdProps) { - return ( - - {children} - - ) -} diff --git a/src/components/atoms/KeyValue.tsx b/src/components/atoms/KeyValue.tsx deleted file mode 100644 index d00d644..0000000 --- a/src/components/atoms/KeyValue.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { cn } from '@/lib/utils' - -interface KeyValueProps { - label: string - value: React.ReactNode - orientation?: 'horizontal' | 'vertical' - className?: string - labelClassName?: string - valueClassName?: string -} - -export function KeyValue({ - label, - value, - orientation = 'horizontal', - className, - labelClassName, - valueClassName -}: KeyValueProps) { - return ( -
- - {label} - - - {value} - -
- ) -} diff --git a/src/components/atoms/Label.tsx b/src/components/atoms/Label.tsx deleted file mode 100644 index 97e897c..0000000 --- a/src/components/atoms/Label.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface LabelProps { - children: ReactNode - htmlFor?: string - required?: boolean - className?: string -} - -export function Label({ children, htmlFor, required, className }: LabelProps) { - return ( - - ) -} diff --git a/src/components/atoms/Link.tsx b/src/components/atoms/Link.tsx deleted file mode 100644 index 34a2089..0000000 --- a/src/components/atoms/Link.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' - -interface LinkProps { - href: string - children: ReactNode - variant?: 'default' | 'muted' | 'accent' | 'destructive' - external?: boolean - className?: string - onClick?: (e: React.MouseEvent) => void -} - -const variantClasses = { - default: 'text-foreground hover:text-primary underline-offset-4 hover:underline', - muted: 'text-muted-foreground hover:text-foreground underline-offset-4 hover:underline', - accent: 'text-accent hover:text-accent/80 underline-offset-4 hover:underline', - destructive: 'text-destructive hover:text-destructive/80 underline-offset-4 hover:underline', -} - -export function Link({ - href, - children, - variant = 'default', - external = false, - className, - onClick -}: LinkProps) { - const externalProps = external ? { target: '_blank', rel: 'noopener noreferrer' } : {} - - return ( - - {children} - - ) -} diff --git a/src/components/atoms/List.tsx b/src/components/atoms/List.tsx deleted file mode 100644 index 325a980..0000000 --- a/src/components/atoms/List.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ReactNode } from 'react' - -interface ListProps { - items: T[] - renderItem: (item: T, index: number) => ReactNode - emptyMessage?: string - className?: string - itemClassName?: string -} - -export function List({ - items, - renderItem, - emptyMessage = 'No items to display', - className = '', - itemClassName = '' -}: ListProps) { - if (items.length === 0) { - return ( -
- {emptyMessage} -
- ) - } - - return ( -
- {items.map((item, index) => ( -
- {renderItem(item, index)} -
- ))} -
- ) -} diff --git a/src/components/atoms/ListItem.tsx b/src/components/atoms/ListItem.tsx deleted file mode 100644 index 6042eef..0000000 --- a/src/components/atoms/ListItem.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { cn } from '@/lib/utils' - -interface ListItemProps { - icon?: React.ReactNode - children: React.ReactNode - onClick?: () => void - active?: boolean - className?: string - endContent?: React.ReactNode -} - -export function ListItem({ icon, children, onClick, active, className, endContent }: ListItemProps) { - const isInteractive = !!onClick - - return ( -
- {icon &&
{icon}
} -
{children}
- {endContent &&
{endContent}
} -
- ) -} diff --git a/src/components/atoms/LiveIndicator.tsx b/src/components/atoms/LiveIndicator.tsx deleted file mode 100644 index a6ec0a6..0000000 --- a/src/components/atoms/LiveIndicator.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { cn } from '@/lib/utils' - -interface LiveIndicatorProps { - label?: string - showLabel?: boolean - size?: 'sm' | 'md' | 'lg' - className?: string -} - -export function LiveIndicator({ - label = 'LIVE', - showLabel = true, - size = 'md', - className, -}: LiveIndicatorProps) { - const sizeClasses = { - sm: 'text-xs gap-1.5', - md: 'text-sm gap-2', - lg: 'text-base gap-2.5', - } - - const dotSizeClasses = { - sm: 'w-2 h-2', - md: 'w-2.5 h-2.5', - lg: 'w-3 h-3', - } - - return ( -
- - - - - {showLabel && ( - {label} - )} -
- ) -} diff --git a/src/components/atoms/LoadingSpinner.tsx b/src/components/atoms/LoadingSpinner.tsx deleted file mode 100644 index 7420ca7..0000000 --- a/src/components/atoms/LoadingSpinner.tsx +++ /dev/null @@ -1,20 +0,0 @@ -interface LoadingSpinnerProps { - size?: 'sm' | 'md' | 'lg' - className?: string -} - -export function LoadingSpinner({ size = 'md', className = '' }: LoadingSpinnerProps) { - const sizeClasses = { - sm: 'w-4 h-4 border-2', - md: 'w-6 h-6 border-2', - lg: 'w-8 h-8 border-3', - } - - return ( -
- ) -} diff --git a/src/components/atoms/LoadingState.tsx b/src/components/atoms/LoadingState.tsx deleted file mode 100644 index 87ab907..0000000 --- a/src/components/atoms/LoadingState.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { cn } from '@/lib/utils' - -export interface LoadingStateProps { - message?: string - size?: 'sm' | 'md' | 'lg' - className?: string -} - -export function LoadingState({ - message = 'Loading...', - size = 'md', - className -}: LoadingStateProps) { - const sizeClasses = { - sm: 'w-4 h-4 border-2', - md: 'w-8 h-8 border-3', - lg: 'w-12 h-12 border-4', - } - - return ( -
-
- {message && ( -

{message}

- )} -
- ) -} diff --git a/src/components/atoms/Menu.tsx b/src/components/atoms/Menu.tsx deleted file mode 100644 index 6073835..0000000 --- a/src/components/atoms/Menu.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { useState, useRef, useEffect } from 'react' -import { CaretRight, Check } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface MenuItem { - id: string - label: string - icon?: React.ReactNode - disabled?: boolean - selected?: boolean - divider?: boolean - danger?: boolean - shortcut?: string - onClick?: () => void -} - -interface MenuProps { - trigger: React.ReactNode - items: MenuItem[] - className?: string -} - -export function Menu({ trigger, items, className }: MenuProps) { - const [isOpen, setIsOpen] = useState(false) - const menuRef = useRef(null) - const triggerRef = useRef(null) - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - menuRef.current && - !menuRef.current.contains(event.target as Node) && - triggerRef.current && - !triggerRef.current.contains(event.target as Node) - ) { - setIsOpen(false) - } - } - - document.addEventListener('mousedown', handleClickOutside) - return () => document.removeEventListener('mousedown', handleClickOutside) - }, []) - - const handleItemClick = (item: MenuItem) => { - if (!item.disabled && item.onClick) { - item.onClick() - setIsOpen(false) - } - } - - return ( -
-
setIsOpen(!isOpen)}> - {trigger} -
- {isOpen && ( -
-
- {items.map((item, index) => { - if (item.divider) { - return
- } - - return ( - - ) - })} -
-
- )} -
- ) -} diff --git a/src/components/atoms/MetricCard.tsx b/src/components/atoms/MetricCard.tsx deleted file mode 100644 index a537b49..0000000 --- a/src/components/atoms/MetricCard.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Card, CardContent } from '@/components/ui/card' -import { cn } from '@/lib/utils' -import { ReactNode } from 'react' - -interface MetricCardProps { - label: string - value: string | number - icon?: ReactNode - trend?: { - value: number - direction: 'up' | 'down' - } - className?: string -} - -export function MetricCard({ label, value, icon, trend, className }: MetricCardProps) { - return ( - - -
-
-
{label}
-
{value}
- {trend && ( -
- {trend.direction === 'up' ? '↑' : '↓'} {Math.abs(trend.value)}% -
- )} -
- {icon &&
{icon}
} -
-
-
- ) -} diff --git a/src/components/atoms/MetricDisplay.tsx b/src/components/atoms/MetricDisplay.tsx deleted file mode 100644 index 29549c9..0000000 --- a/src/components/atoms/MetricDisplay.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { cn } from '@/lib/utils' -import { TrendUp, TrendDown } from '@phosphor-icons/react' - -interface MetricDisplayProps { - label: string - value: string | number - trend?: { - value: number - direction: 'up' | 'down' - } - icon?: React.ReactNode - className?: string - variant?: 'default' | 'primary' | 'accent' -} - -export function MetricDisplay({ - label, - value, - trend, - icon, - className, - variant = 'default' -}: MetricDisplayProps) { - const variantClasses = { - default: 'text-foreground', - primary: 'text-primary', - accent: 'text-accent', - } - - return ( -
-
- {icon && {icon}} - {label} -
-
- - {value} - - {trend && ( - - {trend.direction === 'up' ? : } - {Math.abs(trend.value)}% - - )} -
-
- ) -} diff --git a/src/components/atoms/Modal.tsx b/src/components/atoms/Modal.tsx deleted file mode 100644 index 2f2b737..0000000 --- a/src/components/atoms/Modal.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { X } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface ModalProps { - isOpen: boolean - onClose: () => void - title?: string - children: React.ReactNode - size?: 'sm' | 'md' | 'lg' | 'xl' | 'full' - showCloseButton?: boolean - className?: string -} - -export function Modal({ - isOpen, - onClose, - title, - children, - size = 'md', - showCloseButton = true, - className, -}: ModalProps) { - if (!isOpen) return null - - const sizeStyles = { - sm: 'max-w-sm', - md: 'max-w-md', - lg: 'max-w-lg', - xl: 'max-w-xl', - full: 'max-w-full m-4', - } - - return ( -
-
e.stopPropagation()} - > - {(title || showCloseButton) && ( -
- {title &&

{title}

} - {showCloseButton && ( - - )} -
- )} -
{children}
-
-
- ) -} diff --git a/src/components/atoms/Notification.tsx b/src/components/atoms/Notification.tsx deleted file mode 100644 index 452ae42..0000000 --- a/src/components/atoms/Notification.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Info, CheckCircle, Warning, XCircle } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface NotificationProps { - type: 'info' | 'success' | 'warning' | 'error' - title: string - message?: string - onClose?: () => void - className?: string -} - -export function Notification({ type, title, message, onClose, className }: NotificationProps) { - const config = { - info: { - icon: Info, - color: 'text-blue-500', - bg: 'bg-blue-500/10', - border: 'border-blue-500/20', - }, - success: { - icon: CheckCircle, - color: 'text-accent', - bg: 'bg-accent/10', - border: 'border-accent/20', - }, - warning: { - icon: Warning, - color: 'text-yellow-500', - bg: 'bg-yellow-500/10', - border: 'border-yellow-500/20', - }, - error: { - icon: XCircle, - color: 'text-destructive', - bg: 'bg-destructive/10', - border: 'border-destructive/20', - }, - } - - const { icon: Icon, color, bg, border } = config[type] - - return ( -
- -
-

{title}

- {message &&

{message}

} -
- {onClose && ( - - )} -
- ) -} diff --git a/src/components/atoms/NumberInput.tsx b/src/components/atoms/NumberInput.tsx deleted file mode 100644 index e8ed56f..0000000 --- a/src/components/atoms/NumberInput.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { Input } from '@/components/ui/input' -import { Button } from '@/components/ui/button' -import { Minus, Plus } from '@phosphor-icons/react' -import { cn } from '@/lib/utils' - -interface NumberInputProps { - value: number - onChange: (value: number) => void - min?: number - max?: number - step?: number - label?: string - disabled?: boolean - className?: string -} - -export function NumberInput({ - value, - onChange, - min, - max, - step = 1, - label, - disabled, - className, -}: NumberInputProps) { - const handleIncrement = () => { - const newValue = value + step - if (max === undefined || newValue <= max) { - onChange(newValue) - } - } - - const handleDecrement = () => { - const newValue = value - step - if (min === undefined || newValue >= min) { - onChange(newValue) - } - } - - const handleInputChange = (e: React.ChangeEvent) => { - const newValue = parseFloat(e.target.value) - if (!isNaN(newValue)) { - if ((min === undefined || newValue >= min) && (max === undefined || newValue <= max)) { - onChange(newValue) - } - } - } - - return ( -
- {label && ( - - )} -
- - - -
-
- ) -} diff --git a/src/components/atoms/PageHeader.tsx b/src/components/atoms/PageHeader.tsx deleted file mode 100644 index cc53c6f..0000000 --- a/src/components/atoms/PageHeader.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { cn } from '@/lib/utils' - -interface BasicPageHeaderProps { - title: string - description?: string - actions?: React.ReactNode - className?: string -} - -export function BasicPageHeader({ title, description, actions, className }: BasicPageHeaderProps) { - return ( -
-
-

{title}

- {description && ( -

{description}

- )} -
- {actions && ( -
{actions}
- )} -
- ) -} diff --git a/src/components/atoms/PanelHeader.tsx b/src/components/atoms/PanelHeader.tsx deleted file mode 100644 index 5b0090a..0000000 --- a/src/components/atoms/PanelHeader.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { ReactNode } from 'react' -import { cn } from '@/lib/utils' -import { Separator } from '@/components/ui/separator' - -interface PanelHeaderProps { - title: string - subtitle?: string | ReactNode - icon?: ReactNode - actions?: ReactNode - className?: string - showSeparator?: boolean -} - -export function PanelHeader({ - title, - subtitle, - icon, - actions, - className, - showSeparator = true, -}: PanelHeaderProps) { - return ( -
-
-
- {icon && ( -
- {icon} -
- )} -
-

- {title} -

- {subtitle && ( - typeof subtitle === 'string' ? ( -

- {subtitle} -

- ) : ( -
- {subtitle} -
- ) - )} -
-
- {actions && ( -
- {actions} -
- )} -
- {showSeparator && } -
- ) -} diff --git a/src/components/atoms/PasswordInput.tsx b/src/components/atoms/PasswordInput.tsx deleted file mode 100644 index 1737104..0000000 --- a/src/components/atoms/PasswordInput.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Eye, EyeSlash } from '@phosphor-icons/react' -import { useState } from 'react' -import { Input } from './Input' - -interface PasswordInputProps { - value: string - onChange: (value: string) => void - label?: string - error?: boolean - helperText?: string - placeholder?: string - disabled?: boolean - className?: string -} - -export function PasswordInput({ - value, - onChange, - label, - error, - helperText, - placeholder = 'Enter password', - disabled, - className, -}: PasswordInputProps) { - const [showPassword, setShowPassword] = useState(false) - - return ( - onChange(e.target.value)} - label={label} - error={error} - helperText={helperText} - placeholder={placeholder} - disabled={disabled} - className={className} - rightIcon={ - - } - /> - ) -} diff --git a/src/components/atoms/Popover.tsx b/src/components/atoms/Popover.tsx deleted file mode 100644 index 4a08980..0000000 --- a/src/components/atoms/Popover.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useState, useRef, useEffect } from 'react' -import { cn } from '@/lib/utils' - -interface PopoverProps { - trigger: React.ReactNode - content: React.ReactNode - placement?: 'top' | 'bottom' | 'left' | 'right' - className?: string -} - -export function Popover({ trigger, content, placement = 'bottom', className }: PopoverProps) { - const [isOpen, setIsOpen] = useState(false) - const popoverRef = useRef(null) - const triggerRef = useRef(null) - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - popoverRef.current && - !popoverRef.current.contains(event.target as Node) && - triggerRef.current && - !triggerRef.current.contains(event.target as Node) - ) { - setIsOpen(false) - } - } - - document.addEventListener('mousedown', handleClickOutside) - return () => document.removeEventListener('mousedown', handleClickOutside) - }, []) - - const placementStyles = { - top: 'bottom-full mb-2 left-1/2 -translate-x-1/2', - bottom: 'top-full mt-2 left-1/2 -translate-x-1/2', - left: 'right-full mr-2 top-1/2 -translate-y-1/2', - right: 'left-full ml-2 top-1/2 -translate-y-1/2', - } - - return ( -
-
setIsOpen(!isOpen)}> - {trigger} -
- {isOpen && ( -
- {content} -
- )} -
- ) -} diff --git a/src/components/atoms/ProgressBar.tsx b/src/components/atoms/ProgressBar.tsx deleted file mode 100644 index 680a4ec..0000000 --- a/src/components/atoms/ProgressBar.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { cn } from '@/lib/utils' - -interface ProgressBarProps { - value: number - max?: number - size?: 'sm' | 'md' | 'lg' - variant?: 'default' | 'accent' | 'destructive' - showLabel?: boolean - className?: string -} - -const sizeClasses = { - sm: 'h-1', - md: 'h-2', - lg: 'h-3', -} - -const variantClasses = { - default: 'bg-primary', - accent: 'bg-accent', - destructive: 'bg-destructive', -} - -export function ProgressBar({ - value, - max = 100, - size = 'md', - variant = 'default', - showLabel = false, - className -}: ProgressBarProps) { - const percentage = Math.min(Math.max((value / max) * 100, 0), 100) - - return ( -
-
-
-
- {showLabel && ( - - {Math.round(percentage)}% - - )} -
- ) -} diff --git a/src/components/atoms/PropertyEditorField.tsx b/src/components/atoms/PropertyEditorField.tsx deleted file mode 100644 index 7948fce..0000000 --- a/src/components/atoms/PropertyEditorField.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' -import { Switch } from '@/components/ui/switch' -import { Textarea } from '@/components/ui/textarea' - -interface PropertyEditorFieldProps { - label: string - name: string - value: any - type?: 'text' | 'number' | 'boolean' | 'select' | 'textarea' - options?: Array<{ label: string; value: string }> - onChange: (name: string, value: any) => void -} - -export function PropertyEditorField({ - label, - name, - value, - type = 'text', - options, - onChange, -}: PropertyEditorFieldProps) { - const renderField = () => { - switch (type) { - case 'boolean': - return ( - onChange(name, checked)} - /> - ) - - case 'select': - return ( - - ) - - case 'number': - return ( - onChange(name, Number(e.target.value))} - /> - ) - - case 'textarea': - return ( -