ai-design-system 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +307 -0
- package/components/ai-elements/actions.tsx +65 -0
- package/components/ai-elements/artifact.tsx +147 -0
- package/components/ai-elements/branch.tsx +212 -0
- package/components/ai-elements/canvas.tsx +24 -0
- package/components/ai-elements/chain-of-thought.tsx +228 -0
- package/components/ai-elements/code-block.tsx +179 -0
- package/components/ai-elements/confirmation.tsx +169 -0
- package/components/ai-elements/connection.tsx +28 -0
- package/components/ai-elements/context.tsx +408 -0
- package/components/ai-elements/controls.tsx +18 -0
- package/components/ai-elements/conversation.tsx +97 -0
- package/components/ai-elements/edge.tsx +140 -0
- package/components/ai-elements/image.tsx +24 -0
- package/components/ai-elements/inline-citation.tsx +287 -0
- package/components/ai-elements/loader.tsx +96 -0
- package/components/ai-elements/message.tsx +80 -0
- package/components/ai-elements/node.tsx +71 -0
- package/components/ai-elements/open-in-chat.tsx +363 -0
- package/components/ai-elements/panel.tsx +15 -0
- package/components/ai-elements/plan.tsx +142 -0
- package/components/ai-elements/prompt-input.tsx +1352 -0
- package/components/ai-elements/queue.tsx +274 -0
- package/components/ai-elements/reasoning.tsx +178 -0
- package/components/ai-elements/response.tsx +22 -0
- package/components/ai-elements/shimmer.tsx +64 -0
- package/components/ai-elements/sources.tsx +77 -0
- package/components/ai-elements/suggestion.tsx +56 -0
- package/components/ai-elements/task.tsx +87 -0
- package/components/ai-elements/tool.tsx +179 -0
- package/components/ai-elements/toolbar.tsx +16 -0
- package/components/ai-elements/web-preview.tsx +263 -0
- package/components/blocks/AIConversation/AIConversation.stories.tsx +164 -0
- package/components/blocks/AIConversation/AIConversation.tsx +186 -0
- package/components/blocks/AIConversation/index.ts +8 -0
- package/components/blocks/AppSidebar/AppSidebar.stories.tsx +63 -0
- package/components/blocks/AppSidebar/AppSidebar.tsx +87 -0
- package/components/blocks/AppSidebar/index.ts +2 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.stories.tsx +341 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.tsx +255 -0
- package/components/blocks/DocumentEditorWithComments/index.ts +9 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.stories.tsx +207 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.tsx +143 -0
- package/components/blocks/FileChangeQueue/index.ts +7 -0
- package/components/blocks/LayoutProvider/LayoutProvider.tsx +34 -0
- package/components/blocks/LayoutProvider/index.ts +1 -0
- package/components/blocks/index.ts +2 -0
- package/components/composites/AgentIndicator/AgentIndicator.stories.tsx +154 -0
- package/components/composites/AgentIndicator/AgentIndicator.tsx +102 -0
- package/components/composites/AgentIndicator/index.ts +8 -0
- package/components/composites/AppHeader/AppHeader.stories.tsx +46 -0
- package/components/composites/AppHeader/AppHeader.tsx +24 -0
- package/components/composites/AppHeader/index.ts +2 -0
- package/components/composites/CommentBox/CommentBox.stories.tsx +192 -0
- package/components/composites/CommentBox/CommentBox.tsx +364 -0
- package/components/composites/CommentBox/index.ts +8 -0
- package/components/composites/Confirmation/Confirmation.stories.tsx +151 -0
- package/components/composites/Confirmation/Confirmation.tsx +93 -0
- package/components/composites/Confirmation/index.ts +7 -0
- package/components/composites/DataTable/DataTable.stories.tsx +35 -0
- package/components/composites/DataTable/DataTable.tsx +95 -0
- package/components/composites/DataTable/index.ts +2 -0
- package/components/composites/DocumentEditor/DocumentEditor.css +106 -0
- package/components/composites/DocumentEditor/DocumentEditor.stories.tsx +927 -0
- package/components/composites/DocumentEditor/DocumentEditor.tsx +279 -0
- package/components/composites/DocumentEditor/index.ts +8 -0
- package/components/composites/FileQueue/FileQueue.stories.tsx +175 -0
- package/components/composites/FileQueue/FileQueue.tsx +161 -0
- package/components/composites/FileQueue/FileStatusBadge.tsx +74 -0
- package/components/composites/FileQueue/index.ts +24 -0
- package/components/composites/InteractiveChart/InteractiveChart.stories.tsx +49 -0
- package/components/composites/InteractiveChart/InteractiveChart.tsx +69 -0
- package/components/composites/InteractiveChart/index.ts +2 -0
- package/components/composites/ModeToggle/ModeToggle.stories.tsx +212 -0
- package/components/composites/ModeToggle/ModeToggle.tsx +100 -0
- package/components/composites/ModeToggle/index.ts +7 -0
- package/components/composites/NavUser/NavUser.stories.tsx +50 -0
- package/components/composites/NavUser/NavUser.tsx +60 -0
- package/components/composites/NavUser/index.ts +2 -0
- package/components/composites/NavigationList/NavigationList.stories.tsx +46 -0
- package/components/composites/NavigationList/NavigationList.tsx +46 -0
- package/components/composites/NavigationList/index.ts +2 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.stories.tsx +188 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +72 -0
- package/components/composites/OrchestratorMessage/index.ts +8 -0
- package/components/composites/PageContainer/PageContainer.stories.tsx +41 -0
- package/components/composites/PageContainer/PageContainer.tsx +24 -0
- package/components/composites/PageContainer/index.ts +2 -0
- package/components/composites/PromptInput/PromptInput.stories.tsx +200 -0
- package/components/composites/PromptInput/PromptInput.tsx +129 -0
- package/components/composites/PromptInput/index.ts +8 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.stories.tsx +286 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.tsx +107 -0
- package/components/composites/SpecialistMessage/index.ts +8 -0
- package/components/composites/StatsCard/StatsCard.stories.tsx +76 -0
- package/components/composites/StatsCard/StatsCard.tsx +81 -0
- package/components/composites/StatsCard/index.ts +2 -0
- package/components/composites/TablePagination/TablePagination.stories.tsx +38 -0
- package/components/composites/TablePagination/TablePagination.tsx +119 -0
- package/components/composites/TablePagination/index.ts +2 -0
- package/components/composites/TableToolbar/TableToolbar.stories.tsx +60 -0
- package/components/composites/TableToolbar/TableToolbar.tsx +66 -0
- package/components/composites/TableToolbar/index.ts +2 -0
- package/components/composites/ThemeSelector/ThemeSelector.stories.tsx +48 -0
- package/components/composites/ThemeSelector/ThemeSelector.tsx +79 -0
- package/components/composites/ThemeSelector/index.ts +2 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.stories.tsx +49 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.tsx +108 -0
- package/components/composites/ToolCallDisplay/index.ts +8 -0
- package/components/composites/UserMessage/UserMessage.stories.tsx +59 -0
- package/components/composites/UserMessage/UserMessage.tsx +52 -0
- package/components/composites/UserMessage/index.ts +8 -0
- package/components/composites/index.ts +90 -0
- package/components/features/AIDocEditor/AIDocEditor.behaviors.stories.tsx +451 -0
- package/components/features/AIDocEditor/AIDocEditor.mocks.ts +96 -0
- package/components/features/AIDocEditor/AIDocEditor.stories.tsx +140 -0
- package/components/features/AIDocEditor/AIDocEditor.tsx +130 -0
- package/components/features/AIDocEditor/index.ts +8 -0
- package/components/features/AIDocEditor/useAIDocEditor.d.ts +97 -0
- package/components/features/AIDocEditor/useAIDocEditor.mock.ts +83 -0
- package/components/features/PageLayout/PageLayout.behaviors.stories.tsx +119 -0
- package/components/features/PageLayout/PageLayout.mocks.ts +27 -0
- package/components/features/PageLayout/PageLayout.stories.tsx +142 -0
- package/components/features/PageLayout/PageLayout.tsx +94 -0
- package/components/features/PageLayout/index.ts +4 -0
- package/components/features/PageLayout/usePageLayout.d.ts +24 -0
- package/components/features/PageLayout/usePageLayout.mock.ts +19 -0
- package/components/features/RefinementPanel/README.md +189 -0
- package/components/features/RefinementPanel/RefinementPanel.behaviors.stories.tsx +475 -0
- package/components/features/RefinementPanel/RefinementPanel.mocks.ts +131 -0
- package/components/features/RefinementPanel/RefinementPanel.stories.tsx +141 -0
- package/components/features/RefinementPanel/RefinementPanel.tsx +160 -0
- package/components/features/RefinementPanel/index.ts +25 -0
- package/components/features/RefinementPanel/useRefinementPanel.d.ts +74 -0
- package/components/features/RefinementPanel/useRefinementPanel.mock.ts +121 -0
- package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +379 -0
- package/components/features/SpecNavigator/SpecNavigator.mocks.ts +131 -0
- package/components/features/SpecNavigator/SpecNavigator.stories.tsx +122 -0
- package/components/features/SpecNavigator/SpecNavigator.tsx +43 -0
- package/components/features/SpecNavigator/index.ts +2 -0
- package/components/features/SpecNavigator/useSpecNavigator.d.ts +122 -0
- package/components/features/SpecNavigator/useSpecNavigator.mock.ts +93 -0
- package/components/features/index.ts +18 -0
- package/components/index.ts +14 -0
- package/components/primitives/Accordion/Accordion.stories.tsx +87 -0
- package/components/primitives/Accordion/Accordion.tsx +66 -0
- package/components/primitives/Accordion/index.ts +13 -0
- package/components/primitives/Alert/Alert.stories.tsx +422 -0
- package/components/primitives/Alert/Alert.tsx +61 -0
- package/components/primitives/Alert/index.ts +8 -0
- package/components/primitives/AlertDialog/AlertDialog.stories.tsx +367 -0
- package/components/primitives/AlertDialog/AlertDialog.tsx +182 -0
- package/components/primitives/AlertDialog/index.ts +25 -0
- package/components/primitives/Avatar/Avatar.stories.tsx +321 -0
- package/components/primitives/Avatar/Avatar.tsx +63 -0
- package/components/primitives/Avatar/index.ts +8 -0
- package/components/primitives/Badge/Badge.stories.tsx +74 -0
- package/components/primitives/Badge/Badge.tsx +49 -0
- package/components/primitives/Badge/index.ts +2 -0
- package/components/primitives/Button/Button.stories.tsx +445 -0
- package/components/primitives/Button/Button.tsx +89 -0
- package/components/primitives/Button/index.ts +7 -0
- package/components/primitives/Card/Card.stories.tsx +831 -0
- package/components/primitives/Card/Card.tsx +242 -0
- package/components/primitives/Card/index.ts +30 -0
- package/components/primitives/Carousel/Carousel.stories.tsx +32 -0
- package/components/primitives/Carousel/Carousel.tsx +63 -0
- package/components/primitives/Carousel/index.ts +13 -0
- package/components/primitives/Chart/Chart.stories.tsx +346 -0
- package/components/primitives/Chart/Chart.tsx +117 -0
- package/components/primitives/Chart/index.ts +20 -0
- package/components/primitives/Checkbox/Checkbox.stories.tsx +87 -0
- package/components/primitives/Checkbox/Checkbox.tsx +38 -0
- package/components/primitives/Checkbox/index.ts +2 -0
- package/components/primitives/Collapsible/Collapsible.stories.tsx +38 -0
- package/components/primitives/Collapsible/Collapsible.tsx +39 -0
- package/components/primitives/Collapsible/index.ts +8 -0
- package/components/primitives/Command/Command.stories.tsx +150 -0
- package/components/primitives/Command/Command.tsx +147 -0
- package/components/primitives/Command/index.ts +20 -0
- package/components/primitives/Dialog/Dialog.stories.tsx +390 -0
- package/components/primitives/Dialog/Dialog.tsx +140 -0
- package/components/primitives/Dialog/index.ts +22 -0
- package/components/primitives/Drawer/Drawer.stories.tsx +327 -0
- package/components/primitives/Drawer/Drawer.tsx +208 -0
- package/components/primitives/Drawer/index.ts +27 -0
- package/components/primitives/DropdownMenu/DropdownMenu.stories.tsx +150 -0
- package/components/primitives/DropdownMenu/DropdownMenu.tsx +73 -0
- package/components/primitives/DropdownMenu/index.ts +1 -0
- package/components/primitives/HoverCard/HoverCard.stories.tsx +26 -0
- package/components/primitives/HoverCard/HoverCard.tsx +39 -0
- package/components/primitives/HoverCard/index.ts +8 -0
- package/components/primitives/Icon/Icon.stories.tsx +281 -0
- package/components/primitives/Icon/Icon.tsx +87 -0
- package/components/primitives/Icon/index.ts +8 -0
- package/components/primitives/Input/Input.stories.tsx +370 -0
- package/components/primitives/Input/Input.tsx +88 -0
- package/components/primitives/Input/index.ts +7 -0
- package/components/primitives/InputGroup/InputGroup.stories.tsx +40 -0
- package/components/primitives/InputGroup/InputGroup.tsx +72 -0
- package/components/primitives/InputGroup/index.ts +14 -0
- package/components/primitives/Label/Label.stories.tsx +227 -0
- package/components/primitives/Label/Label.tsx +53 -0
- package/components/primitives/Label/index.ts +7 -0
- package/components/primitives/Popover/Popover.stories.tsx +42 -0
- package/components/primitives/Popover/Popover.tsx +107 -0
- package/components/primitives/Popover/index.ts +2 -0
- package/components/primitives/Progress/Progress.stories.tsx +340 -0
- package/components/primitives/Progress/Progress.tsx +31 -0
- package/components/primitives/Progress/index.ts +1 -0
- package/components/primitives/ScrollArea/ScrollArea.stories.tsx +26 -0
- package/components/primitives/ScrollArea/ScrollArea.tsx +28 -0
- package/components/primitives/ScrollArea/index.ts +6 -0
- package/components/primitives/Select/Select.stories.tsx +288 -0
- package/components/primitives/Select/Select.tsx +162 -0
- package/components/primitives/Select/index.ts +22 -0
- package/components/primitives/Separator/Separator.stories.tsx +264 -0
- package/components/primitives/Separator/Separator.tsx +48 -0
- package/components/primitives/Separator/index.ts +7 -0
- package/components/primitives/Sidebar/Sidebar.stories.tsx +358 -0
- package/components/primitives/Sidebar/Sidebar.tsx +317 -0
- package/components/primitives/Sidebar/index.ts +41 -0
- package/components/primitives/Table/Table.stories.tsx +389 -0
- package/components/primitives/Table/Table.tsx +191 -0
- package/components/primitives/Table/index.ts +26 -0
- package/components/primitives/Tabs/Tabs.stories.tsx +129 -0
- package/components/primitives/Tabs/Tabs.tsx +70 -0
- package/components/primitives/Tabs/index.ts +13 -0
- package/components/primitives/Textarea/Textarea.stories.tsx +358 -0
- package/components/primitives/Textarea/Textarea.tsx +91 -0
- package/components/primitives/Textarea/index.ts +7 -0
- package/components/primitives/ToggleGroup/ToggleGroup.stories.tsx +87 -0
- package/components/primitives/ToggleGroup/ToggleGroup.tsx +52 -0
- package/components/primitives/ToggleGroup/index.ts +6 -0
- package/components/primitives/Tooltip/Tooltip.stories.tsx +336 -0
- package/components/primitives/Tooltip/Tooltip.tsx +78 -0
- package/components/primitives/Tooltip/index.ts +10 -0
- package/components/primitives/index.ts +34 -0
- package/components/ui/accordion.tsx +66 -0
- package/components/ui/alert-dialog.tsx +157 -0
- package/components/ui/alert.tsx +66 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/card.tsx +117 -0
- package/components/ui/carousel.tsx +241 -0
- package/components/ui/chart.tsx +334 -0
- package/components/ui/checkbox.tsx +32 -0
- package/components/ui/collapsible.tsx +33 -0
- package/components/ui/command.tsx +184 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/drawer.tsx +118 -0
- package/components/ui/dropdown-menu.tsx +257 -0
- package/components/ui/hover-card.tsx +44 -0
- package/components/ui/input-group.tsx +170 -0
- package/components/ui/input.tsx +48 -0
- package/components/ui/label.tsx +26 -0
- package/components/ui/popover.tsx +33 -0
- package/components/ui/progress.tsx +31 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/select.tsx +187 -0
- package/components/ui/separator.tsx +31 -0
- package/components/ui/sidebar.tsx +577 -0
- package/components/ui/table.tsx +120 -0
- package/components/ui/tabs.tsx +66 -0
- package/components/ui/textarea.tsx +46 -0
- package/components/ui/toggle-group.tsx +83 -0
- package/components/ui/toggle.tsx +47 -0
- package/components/ui/tooltip.tsx +61 -0
- package/dist/index.cjs +7389 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +75 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +7160 -0
- package/dist/index.js.map +1 -0
- package/hooks/useAIDocReviewer.d.ts +0 -0
- package/lib/utils.ts +6 -0
- package/package.json +140 -0
- package/tokens/color/base.json +14 -0
- package/tokens/color/dark.json +40 -0
- package/tokens/color/green.json +21 -0
- package/tokens/color/light.json +52 -0
- package/tokens/color/neutral.json +20 -0
- package/tokens/color/violet.json +21 -0
- package/tokens/spacing.json +22 -0
- package/utils/ai-editor/format-date.ts +41 -0
- package/utils/ai-editor/index.ts +22 -0
- package/utils/ai-editor/type-guards.ts +72 -0
- package/utils/ai-editor/validation.ts +130 -0
- package/utils/editor-annotations.ts +122 -0
|
File without changes
|
package/lib/utils.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ai-design-system",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "AI-powered design system with React components, built with Tailwind CSS and Radix UI",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./styles": "./dist/styles.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"components",
|
|
21
|
+
"lib",
|
|
22
|
+
"hooks",
|
|
23
|
+
"utils",
|
|
24
|
+
"tokens",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/bizmatters/ai-design-system.git"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"react",
|
|
36
|
+
"components",
|
|
37
|
+
"design-system",
|
|
38
|
+
"ui",
|
|
39
|
+
"tailwind",
|
|
40
|
+
"radix-ui",
|
|
41
|
+
"ai",
|
|
42
|
+
"typescript"
|
|
43
|
+
],
|
|
44
|
+
"author": "Bizmatters",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
48
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
49
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
50
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
51
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
52
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
53
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
54
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
55
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
56
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
57
|
+
"@radix-ui/react-progress": "^1.1.8",
|
|
58
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
59
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
60
|
+
"@radix-ui/react-separator": "^1.1.8",
|
|
61
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
62
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
63
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
64
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
65
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
66
|
+
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
|
67
|
+
"@tanstack/react-table": "^8.21.3",
|
|
68
|
+
"@tiptap/core": "^3.10.7",
|
|
69
|
+
"@tiptap/extension-highlight": "^3.10.7",
|
|
70
|
+
"@tiptap/markdown": "^3.10.7",
|
|
71
|
+
"@tiptap/react": "^3.10.7",
|
|
72
|
+
"@tiptap/starter-kit": "^3.10.7",
|
|
73
|
+
"@xyflow/react": "^12.9.2",
|
|
74
|
+
"ai": "^5.0.87",
|
|
75
|
+
"class-variance-authority": "^0.7.1",
|
|
76
|
+
"clsx": "^2.1.1",
|
|
77
|
+
"cmdk": "^1.1.1",
|
|
78
|
+
"date-fns": "^4.1.0",
|
|
79
|
+
"embla-carousel-react": "^8.6.0",
|
|
80
|
+
"lucide-react": "^0.552.0",
|
|
81
|
+
"motion": "^12.23.24",
|
|
82
|
+
"nanoid": "^5.1.6",
|
|
83
|
+
"next": "16.0.1",
|
|
84
|
+
"react": "19.2.0",
|
|
85
|
+
"react-dom": "19.2.0",
|
|
86
|
+
"recharts": "^3.4.1",
|
|
87
|
+
"shiki": "^3.14.0",
|
|
88
|
+
"streamdown": "^1.4.0",
|
|
89
|
+
"tailwind-merge": "^3.3.1",
|
|
90
|
+
"tokenlens": "^1.3.1",
|
|
91
|
+
"use-stick-to-bottom": "^1.1.1",
|
|
92
|
+
"vaul": "^1.1.2"
|
|
93
|
+
},
|
|
94
|
+
"devDependencies": {
|
|
95
|
+
"@chromatic-com/storybook": "^4.1.2",
|
|
96
|
+
"@storybook/addon-a11y": "^10.0.4",
|
|
97
|
+
"@storybook/addon-docs": "^10.0.4",
|
|
98
|
+
"@storybook/addon-onboarding": "^10.0.4",
|
|
99
|
+
"@storybook/addon-vitest": "^10.0.4",
|
|
100
|
+
"@storybook/nextjs-vite": "^10.0.4",
|
|
101
|
+
"@storybook/test": "^8.6.14",
|
|
102
|
+
"@tailwindcss/postcss": "^4.1.16",
|
|
103
|
+
"@types/hast": "^3.0.4",
|
|
104
|
+
"@types/node": "^20",
|
|
105
|
+
"@types/react": "^19",
|
|
106
|
+
"@types/react-dom": "^19",
|
|
107
|
+
"@vitest/browser-playwright": "^4.0.7",
|
|
108
|
+
"@vitest/coverage-v8": "^4.0.7",
|
|
109
|
+
"eslint": "^9",
|
|
110
|
+
"eslint-config-next": "16.0.1",
|
|
111
|
+
"eslint-plugin-storybook": "^10.0.4",
|
|
112
|
+
"hast": "^1.0.0",
|
|
113
|
+
"ignore-loader": "^0.1.2",
|
|
114
|
+
"playwright": "^1.56.1",
|
|
115
|
+
"storybook": "^10.0.4",
|
|
116
|
+
"style-dictionary": "^5.1.1",
|
|
117
|
+
"tailwindcss": "^4.1.16",
|
|
118
|
+
"tsup": "^8.3.5",
|
|
119
|
+
"tw-animate-css": "^1.4.0",
|
|
120
|
+
"typescript": "^5",
|
|
121
|
+
"vitest": "^4.0.7"
|
|
122
|
+
},
|
|
123
|
+
"peerDependencies": {
|
|
124
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
125
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
126
|
+
"next": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
127
|
+
},
|
|
128
|
+
"scripts": {
|
|
129
|
+
"dev": "pnpm tokens:build && next dev",
|
|
130
|
+
"build": "pnpm tokens:build && pnpm prebuild && next build",
|
|
131
|
+
"build:lib": "pnpm tokens:build && tsup",
|
|
132
|
+
"prebuild": "bash scripts/run-all-validations.sh",
|
|
133
|
+
"start": "next start",
|
|
134
|
+
"lint": "eslint",
|
|
135
|
+
"tokens:build": "node build-tokens.js",
|
|
136
|
+
"tokens:watch": "style-dictionary build --watch",
|
|
137
|
+
"storybook": "storybook dev -p 6006",
|
|
138
|
+
"build-storybook": "storybook build"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"theme": {
|
|
4
|
+
"background": { "$value": "oklch(0.145 0 0)", "$type": "color" },
|
|
5
|
+
"foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
6
|
+
"card": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
7
|
+
"card-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
8
|
+
"popover": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
9
|
+
"popover-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
10
|
+
"secondary": { "$value": "oklch(0.269 0 0)", "$type": "color" },
|
|
11
|
+
"secondary-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
12
|
+
"muted": { "$value": "oklch(0.269 0 0)", "$type": "color" },
|
|
13
|
+
"muted-foreground": { "$value": "oklch(0.708 0 0)", "$type": "color" },
|
|
14
|
+
"accent": { "$value": "oklch(0.269 0 0)", "$type": "color" },
|
|
15
|
+
"accent-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
16
|
+
"destructive": { "$value": "oklch(0.704 0.191 22.216)", "$type": "color" },
|
|
17
|
+
"border": { "$value": "oklch(1 0 0 / 10%)", "$type": "color" },
|
|
18
|
+
"input": { "$value": "oklch(1 0 0 / 15%)", "$type": "color" }
|
|
19
|
+
},
|
|
20
|
+
"sidebar": {
|
|
21
|
+
"background": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
22
|
+
"foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
23
|
+
"primary-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
24
|
+
"accent": { "$value": "oklch(0.269 0 0)", "$type": "color" },
|
|
25
|
+
"accent-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
26
|
+
"border": { "$value": "oklch(1 0 0 / 10%)", "$type": "color" }
|
|
27
|
+
},
|
|
28
|
+
"annotation": {
|
|
29
|
+
"comment": { "$value": "oklch(0.35 0.12 95)", "$type": "color" },
|
|
30
|
+
"comment-foreground": { "$value": "oklch(0.85 0.12 95)", "$type": "color" },
|
|
31
|
+
"comment-border": { "$value": "oklch(0.55 0.15 95)", "$type": "color" },
|
|
32
|
+
"addition": { "$value": "oklch(0.30 0.12 145)", "$type": "color" },
|
|
33
|
+
"addition-foreground": { "$value": "oklch(0.75 0.12 145)", "$type": "color" },
|
|
34
|
+
"addition-border": { "$value": "oklch(0.50 0.15 145)", "$type": "color" },
|
|
35
|
+
"deletion": { "$value": "oklch(0.35 0.12 25)", "$type": "color" },
|
|
36
|
+
"deletion-foreground": { "$value": "oklch(0.75 0.15 25)", "$type": "color" },
|
|
37
|
+
"deletion-border": { "$value": "oklch(0.50 0.17 25)", "$type": "color" }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"theme": {
|
|
4
|
+
"primary": { "$value": "oklch(0.648 0.2 131.684)", "$type": "color" },
|
|
5
|
+
"primary-foreground": { "$value": "oklch(0.986 0.031 120.757)", "$type": "color" },
|
|
6
|
+
"ring": { "$value": "oklch(0.405 0.101 131.063)", "$type": "color" }
|
|
7
|
+
},
|
|
8
|
+
"chart": {
|
|
9
|
+
"1": { "$value": "oklch(0.871 0.15 154.449)", "$type": "color" },
|
|
10
|
+
"2": { "$value": "oklch(0.723 0.219 149.579)", "$type": "color" },
|
|
11
|
+
"3": { "$value": "oklch(0.627 0.194 149.214)", "$type": "color" },
|
|
12
|
+
"4": { "$value": "oklch(0.527 0.154 150.069)", "$type": "color" },
|
|
13
|
+
"5": { "$value": "oklch(0.448 0.119 151.328)", "$type": "color" }
|
|
14
|
+
},
|
|
15
|
+
"sidebar": {
|
|
16
|
+
"primary": { "$value": "oklch(0.768 0.233 130.85)", "$type": "color" },
|
|
17
|
+
"primary-foreground": { "$value": "oklch(0.986 0.031 120.757)", "$type": "color" },
|
|
18
|
+
"ring": { "$value": "oklch(0.405 0.101 131.063)", "$type": "color" }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"theme": {
|
|
4
|
+
"background": { "$value": "{color.base.white}", "$type": "color" },
|
|
5
|
+
"foreground": { "$value": "{color.base.black}", "$type": "color" },
|
|
6
|
+
"card": { "$value": "{color.base.white}", "$type": "color" },
|
|
7
|
+
"card-foreground": { "$value": "{color.base.black}", "$type": "color" },
|
|
8
|
+
"popover": { "$value": "{color.base.white}", "$type": "color" },
|
|
9
|
+
"popover-foreground": { "$value": "{color.base.black}", "$type": "color" },
|
|
10
|
+
"primary": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
11
|
+
"primary-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
12
|
+
"secondary": { "$value": "oklch(0.97 0 0)", "$type": "color" },
|
|
13
|
+
"secondary-foreground": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
14
|
+
"muted": { "$value": "oklch(0.97 0 0)", "$type": "color" },
|
|
15
|
+
"muted-foreground": { "$value": "oklch(0.556 0 0)", "$type": "color" },
|
|
16
|
+
"accent": { "$value": "oklch(0.97 0 0)", "$type": "color" },
|
|
17
|
+
"accent-foreground": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
18
|
+
"destructive": { "$value": "oklch(0.577 0.245 27.325)", "$type": "color" },
|
|
19
|
+
"border": { "$value": "oklch(0.922 0 0)", "$type": "color" },
|
|
20
|
+
"input": { "$value": "oklch(0.922 0 0)", "$type": "color" },
|
|
21
|
+
"ring": { "$value": "oklch(0.708 0 0)", "$type": "color" }
|
|
22
|
+
},
|
|
23
|
+
"chart": {
|
|
24
|
+
"1": { "$value": "oklch(0.646 0.222 41.116)", "$type": "color" },
|
|
25
|
+
"2": { "$value": "oklch(0.6 0.118 184.704)", "$type": "color" },
|
|
26
|
+
"3": { "$value": "oklch(0.398 0.07 227.392)", "$type": "color" },
|
|
27
|
+
"4": { "$value": "oklch(0.828 0.189 84.429)", "$type": "color" },
|
|
28
|
+
"5": { "$value": "oklch(0.769 0.188 70.08)", "$type": "color" }
|
|
29
|
+
},
|
|
30
|
+
"sidebar": {
|
|
31
|
+
"background": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
32
|
+
"foreground": { "$value": "{color.base.black}", "$type": "color" },
|
|
33
|
+
"primary": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
34
|
+
"primary-foreground": { "$value": "oklch(0.985 0 0)", "$type": "color" },
|
|
35
|
+
"accent": { "$value": "oklch(0.97 0 0)", "$type": "color" },
|
|
36
|
+
"accent-foreground": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
37
|
+
"border": { "$value": "oklch(0.922 0 0)", "$type": "color" },
|
|
38
|
+
"ring": { "$value": "oklch(0.708 0 0)", "$type": "color" }
|
|
39
|
+
},
|
|
40
|
+
"annotation": {
|
|
41
|
+
"comment": { "$value": "oklch(0.95 0.15 95)", "$type": "color" },
|
|
42
|
+
"comment-foreground": { "$value": "oklch(0.45 0.15 95)", "$type": "color" },
|
|
43
|
+
"comment-border": { "$value": "oklch(0.65 0.18 95)", "$type": "color" },
|
|
44
|
+
"addition": { "$value": "oklch(0.85 0.15 145)", "$type": "color" },
|
|
45
|
+
"addition-foreground": { "$value": "oklch(0.35 0.15 145)", "$type": "color" },
|
|
46
|
+
"addition-border": { "$value": "oklch(0.55 0.18 145)", "$type": "color" },
|
|
47
|
+
"deletion": { "$value": "oklch(0.88 0.15 25)", "$type": "color" },
|
|
48
|
+
"deletion-foreground": { "$value": "oklch(0.45 0.18 25)", "$type": "color" },
|
|
49
|
+
"deletion-border": { "$value": "oklch(0.58 0.20 25)", "$type": "color" }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"theme": {
|
|
4
|
+
"primary": { "$value": "oklch(0.922 0 0)", "$type": "color" },
|
|
5
|
+
"primary-foreground": { "$value": "oklch(0.205 0 0)", "$type": "color" },
|
|
6
|
+
"ring": { "$value": "oklch(0.556 0 0)", "$type": "color" }
|
|
7
|
+
},
|
|
8
|
+
"chart": {
|
|
9
|
+
"1": { "$value": "oklch(0.488 0.243 264.376)", "$type": "color" },
|
|
10
|
+
"2": { "$value": "oklch(0.696 0.17 162.48)", "$type": "color" },
|
|
11
|
+
"3": { "$value": "oklch(0.769 0.188 70.08)", "$type": "color" },
|
|
12
|
+
"4": { "$value": "oklch(0.627 0.265 303.9)", "$type": "color" },
|
|
13
|
+
"5": { "$value": "oklch(0.645 0.246 16.439)", "$type": "color" }
|
|
14
|
+
},
|
|
15
|
+
"sidebar": {
|
|
16
|
+
"primary": { "$value": "oklch(0.488 0.243 264.376)", "$type": "color" },
|
|
17
|
+
"ring": { "$value": "oklch(0.556 0 0)", "$type": "color" }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"theme": {
|
|
4
|
+
"primary": { "$value": "oklch(0.606 0.25 292.717)", "$type": "color" },
|
|
5
|
+
"primary-foreground": { "$value": "oklch(0.969 0.016 293.756)", "$type": "color" },
|
|
6
|
+
"ring": { "$value": "oklch(0.38 0.189 293.745)", "$type": "color" }
|
|
7
|
+
},
|
|
8
|
+
"chart": {
|
|
9
|
+
"1": { "$value": "oklch(0.811 0.111 293.571)", "$type": "color" },
|
|
10
|
+
"2": { "$value": "oklch(0.606 0.25 292.717)", "$type": "color" },
|
|
11
|
+
"3": { "$value": "oklch(0.541 0.281 293.009)", "$type": "color" },
|
|
12
|
+
"4": { "$value": "oklch(0.491 0.27 292.581)", "$type": "color" },
|
|
13
|
+
"5": { "$value": "oklch(0.432 0.232 292.759)", "$type": "color" }
|
|
14
|
+
},
|
|
15
|
+
"sidebar": {
|
|
16
|
+
"primary": { "$value": "oklch(0.606 0.25 292.717)", "$type": "color" },
|
|
17
|
+
"primary-foreground": { "$value": "oklch(0.969 0.016 293.756)", "$type": "color" },
|
|
18
|
+
"ring": { "$value": "oklch(0.38 0.189 293.745)", "$type": "color" }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"spacing": {
|
|
3
|
+
"radius": {
|
|
4
|
+
"$type": "dimension",
|
|
5
|
+
"base": { "$value": "0.625rem" },
|
|
6
|
+
"sm": { "$value": "{spacing.radius.base} - 4px" },
|
|
7
|
+
"md": { "$value": "{spacing.radius.base} - 2px" },
|
|
8
|
+
"lg": { "$value": "{spacing.radius.base}" },
|
|
9
|
+
"xl": { "$value": "{spacing.radius.base} + 4px" }
|
|
10
|
+
},
|
|
11
|
+
"sidebar": {
|
|
12
|
+
"$type": "dimension",
|
|
13
|
+
"width": { "$value": "16rem" },
|
|
14
|
+
"width-mobile": { "$value": "18rem" },
|
|
15
|
+
"width-icon": { "$value": "3rem" }
|
|
16
|
+
},
|
|
17
|
+
"header": {
|
|
18
|
+
"$type": "dimension",
|
|
19
|
+
"height": { "$value": "3.5rem" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format Comment Date Utility
|
|
3
|
+
*
|
|
4
|
+
* Formats timestamps as relative time for comment display
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { formatDistanceToNow } from 'date-fns'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Formats a timestamp as relative time
|
|
11
|
+
*
|
|
12
|
+
* @param date - Date object or Unix timestamp (number) to format
|
|
13
|
+
* @returns Formatted string like "5m", "2h", "3d", "2w", "3mo", "1y"
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* formatCommentDate(new Date(Date.now() - 5 * 60 * 1000)) // "5m"
|
|
18
|
+
* formatCommentDate(Date.now() - 2 * 60 * 60 * 1000) // "2h"
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function formatCommentDate(date: Date | number): string {
|
|
22
|
+
const now = Date.now()
|
|
23
|
+
const timestamp = typeof date === 'number' ? date : date.getTime()
|
|
24
|
+
const diffMs = now - timestamp
|
|
25
|
+
|
|
26
|
+
const seconds = Math.floor(diffMs / 1000)
|
|
27
|
+
const minutes = Math.floor(seconds / 60)
|
|
28
|
+
const hours = Math.floor(minutes / 60)
|
|
29
|
+
const days = Math.floor(hours / 24)
|
|
30
|
+
const weeks = Math.floor(days / 7)
|
|
31
|
+
const months = Math.floor(days / 30)
|
|
32
|
+
const years = Math.floor(days / 365)
|
|
33
|
+
|
|
34
|
+
if (seconds < 60) return 'just now'
|
|
35
|
+
if (minutes < 60) return `${minutes}m`
|
|
36
|
+
if (hours < 24) return `${hours}h`
|
|
37
|
+
if (days < 7) return `${days}d`
|
|
38
|
+
if (weeks < 4) return `${weeks}w`
|
|
39
|
+
if (months < 12) return `${months}mo`
|
|
40
|
+
return `${years}y`
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Editor Utilities
|
|
3
|
+
*
|
|
4
|
+
* Central export point for all AI Editor utility functions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Type guards
|
|
8
|
+
export {
|
|
9
|
+
isCommentAnnotation,
|
|
10
|
+
isSuggestionAnnotation,
|
|
11
|
+
isBlockAdditionAnnotation,
|
|
12
|
+
} from './type-guards'
|
|
13
|
+
|
|
14
|
+
// Validation utilities
|
|
15
|
+
export {
|
|
16
|
+
validateRange,
|
|
17
|
+
validateAnnotation,
|
|
18
|
+
validateAnnotations,
|
|
19
|
+
} from './validation'
|
|
20
|
+
|
|
21
|
+
// Date formatting
|
|
22
|
+
export { formatCommentDate } from './format-date'
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type Guards for AI Editor Annotations
|
|
3
|
+
*
|
|
4
|
+
* Provides runtime type checking for discriminated union types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
Annotation,
|
|
9
|
+
CommentAnnotation,
|
|
10
|
+
SuggestionAnnotation,
|
|
11
|
+
BlockAdditionAnnotation,
|
|
12
|
+
} from '../../types/ai-editor'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Type guard to check if annotation is a CommentAnnotation
|
|
16
|
+
*
|
|
17
|
+
* @param annotation - Annotation to check
|
|
18
|
+
* @returns True if annotation is a CommentAnnotation
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* if (isCommentAnnotation(annotation)) {
|
|
23
|
+
* // TypeScript knows annotation.data.thread exists
|
|
24
|
+
* console.log(annotation.data.thread.length)
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function isCommentAnnotation(
|
|
29
|
+
annotation: Annotation
|
|
30
|
+
): annotation is CommentAnnotation {
|
|
31
|
+
return annotation.type === 'comment'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Type guard to check if annotation is a SuggestionAnnotation
|
|
36
|
+
*
|
|
37
|
+
* @param annotation - Annotation to check
|
|
38
|
+
* @returns True if annotation is a SuggestionAnnotation
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* if (isSuggestionAnnotation(annotation)) {
|
|
43
|
+
* // TypeScript knows annotation.data.action exists
|
|
44
|
+
* console.log(annotation.data.action)
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function isSuggestionAnnotation(
|
|
49
|
+
annotation: Annotation
|
|
50
|
+
): annotation is SuggestionAnnotation {
|
|
51
|
+
return annotation.type === 'suggestion'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Type guard to check if annotation is a BlockAdditionAnnotation
|
|
56
|
+
*
|
|
57
|
+
* @param annotation - Annotation to check
|
|
58
|
+
* @returns True if annotation is a BlockAdditionAnnotation
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* if (isBlockAdditionAnnotation(annotation)) {
|
|
63
|
+
* // TypeScript knows annotation.data.content exists
|
|
64
|
+
* console.log(annotation.data.content)
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function isBlockAdditionAnnotation(
|
|
69
|
+
annotation: Annotation
|
|
70
|
+
): annotation is BlockAdditionAnnotation {
|
|
71
|
+
return annotation.type === 'block-addition'
|
|
72
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Utilities for AI Editor
|
|
3
|
+
*
|
|
4
|
+
* Provides runtime validation for annotations and ranges
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Annotation, Range } from '../../types/ai-editor'
|
|
8
|
+
import {
|
|
9
|
+
isCommentAnnotation,
|
|
10
|
+
isSuggestionAnnotation,
|
|
11
|
+
isBlockAdditionAnnotation,
|
|
12
|
+
} from './type-guards'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Validates a range object
|
|
16
|
+
*
|
|
17
|
+
* @param range - Range to validate
|
|
18
|
+
* @param documentLength - Total length of the document
|
|
19
|
+
* @returns True if range is valid
|
|
20
|
+
*/
|
|
21
|
+
export function validateRange(range: Range, documentLength: number): boolean {
|
|
22
|
+
// Check range bounds
|
|
23
|
+
if (range.from < 0 || range.to > documentLength) {
|
|
24
|
+
console.error('Range out of bounds:', range, 'Document length:', documentLength)
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check range order
|
|
29
|
+
if (range.from >= range.to) {
|
|
30
|
+
console.error('Invalid range: from must be less than to:', range)
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Validates an annotation object
|
|
39
|
+
*
|
|
40
|
+
* @param annotation - Annotation to validate
|
|
41
|
+
* @param documentLength - Total length of the document
|
|
42
|
+
* @returns True if annotation is valid
|
|
43
|
+
*/
|
|
44
|
+
export function validateAnnotation(
|
|
45
|
+
annotation: Annotation,
|
|
46
|
+
documentLength: number
|
|
47
|
+
): boolean {
|
|
48
|
+
// Validate range
|
|
49
|
+
if (!validateRange(annotation.range, documentLength)) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Validate type-specific data
|
|
54
|
+
if (isCommentAnnotation(annotation)) {
|
|
55
|
+
if (!annotation.data.thread || annotation.data.thread.length === 0) {
|
|
56
|
+
console.error('Comment annotation must have at least one comment:', annotation)
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
} else if (isSuggestionAnnotation(annotation)) {
|
|
60
|
+
if (!annotation.data.reason) {
|
|
61
|
+
console.error('Suggestion annotation must have a reason:', annotation)
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Validate action-specific requirements
|
|
66
|
+
if (annotation.data.action === 'modify') {
|
|
67
|
+
if (!annotation.data.oldText || !annotation.data.newText) {
|
|
68
|
+
console.error(
|
|
69
|
+
'Modify suggestion must have both oldText and newText:',
|
|
70
|
+
annotation
|
|
71
|
+
)
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
} else if (annotation.data.action === 'delete') {
|
|
75
|
+
if (!annotation.data.oldText) {
|
|
76
|
+
console.error('Delete suggestion must have oldText:', annotation)
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
} else if (annotation.data.action === 'insert') {
|
|
80
|
+
if (!annotation.data.newText) {
|
|
81
|
+
console.error('Insert suggestion must have newText:', annotation)
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} else if (isBlockAdditionAnnotation(annotation)) {
|
|
86
|
+
if (!annotation.data.content || !annotation.data.reason) {
|
|
87
|
+
console.error('Block addition must have content and reason:', annotation)
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return true
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validates an array of annotations
|
|
97
|
+
*
|
|
98
|
+
* @param annotations - Array of annotations to validate
|
|
99
|
+
* @param documentLength - Total length of the document
|
|
100
|
+
* @returns Object with validation results
|
|
101
|
+
*/
|
|
102
|
+
export function validateAnnotations(
|
|
103
|
+
annotations: Annotation[],
|
|
104
|
+
documentLength: number
|
|
105
|
+
): {
|
|
106
|
+
valid: boolean
|
|
107
|
+
errors: string[]
|
|
108
|
+
validAnnotations: Annotation[]
|
|
109
|
+
invalidAnnotations: Annotation[]
|
|
110
|
+
} {
|
|
111
|
+
const errors: string[] = []
|
|
112
|
+
const validAnnotations: Annotation[] = []
|
|
113
|
+
const invalidAnnotations: Annotation[] = []
|
|
114
|
+
|
|
115
|
+
for (const annotation of annotations) {
|
|
116
|
+
if (validateAnnotation(annotation, documentLength)) {
|
|
117
|
+
validAnnotations.push(annotation)
|
|
118
|
+
} else {
|
|
119
|
+
invalidAnnotations.push(annotation)
|
|
120
|
+
errors.push(`Invalid annotation: ${annotation.id}`)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
valid: errors.length === 0,
|
|
126
|
+
errors,
|
|
127
|
+
validAnnotations,
|
|
128
|
+
invalidAnnotations,
|
|
129
|
+
}
|
|
130
|
+
}
|