doe-sdk 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.
Files changed (127) hide show
  1. package/README.md +509 -0
  2. package/dist/cli/index.d.ts +17 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +118 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/cli/init.d.ts +25 -0
  7. package/dist/cli/init.d.ts.map +1 -0
  8. package/dist/cli/init.js +100 -0
  9. package/dist/cli/init.js.map +1 -0
  10. package/dist/cli/login.d.ts +52 -0
  11. package/dist/cli/login.d.ts.map +1 -0
  12. package/dist/cli/login.js +571 -0
  13. package/dist/cli/login.js.map +1 -0
  14. package/dist/cli/publish.d.ts +27 -0
  15. package/dist/cli/publish.d.ts.map +1 -0
  16. package/dist/cli/publish.js +531 -0
  17. package/dist/cli/publish.js.map +1 -0
  18. package/dist/cli/scaffold.d.ts +18 -0
  19. package/dist/cli/scaffold.d.ts.map +1 -0
  20. package/dist/cli/scaffold.js +252 -0
  21. package/dist/cli/scaffold.js.map +1 -0
  22. package/dist/cli/ui.d.ts +57 -0
  23. package/dist/cli/ui.d.ts.map +1 -0
  24. package/dist/cli/ui.js +339 -0
  25. package/dist/cli/ui.js.map +1 -0
  26. package/dist/cli/validate.d.ts +28 -0
  27. package/dist/cli/validate.d.ts.map +1 -0
  28. package/dist/cli/validate.js +1270 -0
  29. package/dist/cli/validate.js.map +1 -0
  30. package/dist/compat/legacy-adapter.d.ts +198 -0
  31. package/dist/compat/legacy-adapter.d.ts.map +1 -0
  32. package/dist/compat/legacy-adapter.js +318 -0
  33. package/dist/compat/legacy-adapter.js.map +1 -0
  34. package/dist/index.d.ts +14 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +16 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/runtime/client.d.ts +370 -0
  39. package/dist/runtime/client.d.ts.map +1 -0
  40. package/dist/runtime/client.js +470 -0
  41. package/dist/runtime/client.js.map +1 -0
  42. package/dist/runtime/index.d.ts +8 -0
  43. package/dist/runtime/index.d.ts.map +1 -0
  44. package/dist/runtime/index.js +7 -0
  45. package/dist/runtime/index.js.map +1 -0
  46. package/dist/types/api.d.ts +564 -0
  47. package/dist/types/api.d.ts.map +1 -0
  48. package/dist/types/api.js +11 -0
  49. package/dist/types/api.js.map +1 -0
  50. package/dist/types/index.d.ts +12 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/index.js +10 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/types/manifest.d.ts +412 -0
  55. package/dist/types/manifest.d.ts.map +1 -0
  56. package/dist/types/manifest.js +42 -0
  57. package/dist/types/manifest.js.map +1 -0
  58. package/dist/types/marketplace-categories.d.ts +9 -0
  59. package/dist/types/marketplace-categories.d.ts.map +1 -0
  60. package/dist/types/marketplace-categories.js +16 -0
  61. package/dist/types/marketplace-categories.js.map +1 -0
  62. package/dist/types/permissions.d.ts +86 -0
  63. package/dist/types/permissions.d.ts.map +1 -0
  64. package/dist/types/permissions.js +295 -0
  65. package/dist/types/permissions.js.map +1 -0
  66. package/dist/types/theme/index.d.ts +7 -0
  67. package/dist/types/theme/index.d.ts.map +1 -0
  68. package/dist/types/theme/index.js +7 -0
  69. package/dist/types/theme/index.js.map +1 -0
  70. package/dist/types/theme/schema.d.ts +1205 -0
  71. package/dist/types/theme/schema.d.ts.map +1 -0
  72. package/dist/types/theme/schema.js +325 -0
  73. package/dist/types/theme/schema.js.map +1 -0
  74. package/dist/types/theme/types.d.ts +648 -0
  75. package/dist/types/theme/types.d.ts.map +1 -0
  76. package/dist/types/theme/types.js +8 -0
  77. package/dist/types/theme/types.js.map +1 -0
  78. package/package.json +75 -0
  79. package/templates/extension/README.md +254 -0
  80. package/templates/extension/icon.png +0 -0
  81. package/templates/extension/index.html +42 -0
  82. package/templates/extension/manifest.json +57 -0
  83. package/templates/extension/package.json +24 -0
  84. package/templates/extension/src/App.tsx +252 -0
  85. package/templates/extension/src/components/OnboardingComplete.tsx +190 -0
  86. package/templates/extension/src/components/OnboardingProgress.tsx +82 -0
  87. package/templates/extension/src/components/OnboardingWelcome.tsx +166 -0
  88. package/templates/extension/src/components/StepContainer.tsx +217 -0
  89. package/templates/extension/src/components/playground/CanvasTab.tsx +24 -0
  90. package/templates/extension/src/components/playground/ConfigTab.tsx +24 -0
  91. package/templates/extension/src/components/playground/EventsTab.tsx +24 -0
  92. package/templates/extension/src/components/playground/InfoTab.tsx +89 -0
  93. package/templates/extension/src/components/playground/NetworkTab.tsx +24 -0
  94. package/templates/extension/src/components/playground/PlaygroundContainer.tsx +184 -0
  95. package/templates/extension/src/components/playground/ResultDisplay.tsx +30 -0
  96. package/templates/extension/src/components/playground/StorageTab.tsx +24 -0
  97. package/templates/extension/src/components/playground/UITab.tsx +24 -0
  98. package/templates/extension/src/components/shared/CanvasControls.tsx +130 -0
  99. package/templates/extension/src/components/shared/ConfigControls.tsx +154 -0
  100. package/templates/extension/src/components/shared/EventsControls.tsx +232 -0
  101. package/templates/extension/src/components/shared/InfoControls.tsx +281 -0
  102. package/templates/extension/src/components/shared/NetworkControls.tsx +328 -0
  103. package/templates/extension/src/components/shared/StorageControls.tsx +203 -0
  104. package/templates/extension/src/components/shared/UIControls.tsx +199 -0
  105. package/templates/extension/src/components/shared/index.ts +15 -0
  106. package/templates/extension/src/components/steps/CanvasStep.tsx +67 -0
  107. package/templates/extension/src/components/steps/ClipboardStep.tsx +167 -0
  108. package/templates/extension/src/components/steps/ConfigStep.tsx +63 -0
  109. package/templates/extension/src/components/steps/EventsStep.tsx +69 -0
  110. package/templates/extension/src/components/steps/InfoStep.tsx +70 -0
  111. package/templates/extension/src/components/steps/NetworkStep.tsx +70 -0
  112. package/templates/extension/src/components/steps/StorageStep.tsx +61 -0
  113. package/templates/extension/src/components/steps/UIStep.tsx +70 -0
  114. package/templates/extension/src/hooks/useDoe.ts +93 -0
  115. package/templates/extension/src/hooks/useOnboarding.ts +264 -0
  116. package/templates/extension/src/hooks/usePointerHandlers.ts +105 -0
  117. package/templates/extension/src/main.tsx +18 -0
  118. package/templates/extension/src/styles.ts +265 -0
  119. package/templates/extension/tsconfig.json +28 -0
  120. package/templates/extension/vite.config.ts +32 -0
  121. package/templates/theme/README.md +132 -0
  122. package/templates/theme/manifest.json +19 -0
  123. package/templates/theme/package.json +16 -0
  124. package/templates/theme/styles/.gitkeep +2 -0
  125. package/templates/theme/themes/theme.json +32 -0
  126. package/templates/theme/vite-plugin-doe-theme.ts +53 -0
  127. package/templates/theme/vite.config.ts +10 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * useOnboarding - Onboarding State Management Hook
3
+ *
4
+ * Manages onboarding flow state with persistence via DOE storage API.
5
+ * Supports step navigation, progress tracking, and skip functionality.
6
+ */
7
+ import { useState, useCallback, useEffect } from "react";
8
+ import type { DOEExtensionAPI } from "doe-sdk/runtime";
9
+
10
+ // ============================================================================
11
+ // TYPES
12
+ // ============================================================================
13
+
14
+ export type OnboardingScreen = "welcome" | "steps" | "complete" | "playground";
15
+
16
+ export type StepId =
17
+ | "canvas"
18
+ | "storage"
19
+ | "config"
20
+ | "ui"
21
+ | "clipboard"
22
+ | "events"
23
+ | "network"
24
+ | "info";
25
+
26
+ export interface OnboardingState {
27
+ /** Current screen being displayed */
28
+ screen: OnboardingScreen;
29
+ /** Current step index (0-based) when in steps screen */
30
+ currentStep: number;
31
+ /** Completed step IDs */
32
+ completedSteps: StepId[];
33
+ /** Whether onboarding was skipped */
34
+ skipped: boolean;
35
+ /** Whether state has been loaded from storage */
36
+ isLoaded: boolean;
37
+ }
38
+
39
+ export interface UseOnboardingResult {
40
+ state: OnboardingState;
41
+ /** Navigate to a specific screen */
42
+ goToScreen: (screen: OnboardingScreen) => void;
43
+ /** Go to next step */
44
+ nextStep: () => void;
45
+ /** Go to previous step */
46
+ prevStep: () => void;
47
+ /** Mark current step as completed and advance */
48
+ completeStep: () => void;
49
+ /** Skip onboarding and go to playground */
50
+ skip: () => void;
51
+ /** Restart onboarding from welcome */
52
+ restart: () => void;
53
+ /** Total number of steps */
54
+ totalSteps: number;
55
+ /** Whether all steps are completed */
56
+ isComplete: boolean;
57
+ /** Get current step ID */
58
+ currentStepId: StepId;
59
+ }
60
+
61
+ // ============================================================================
62
+ // CONSTANTS
63
+ // ============================================================================
64
+
65
+ const STORAGE_KEY = "onboarding_state";
66
+
67
+ export const STEPS: StepId[] = [
68
+ "canvas",
69
+ "storage",
70
+ "config",
71
+ "ui",
72
+ "clipboard",
73
+ "events",
74
+ "network",
75
+ "info",
76
+ ];
77
+
78
+ export const STEP_INFO: Record<
79
+ StepId,
80
+ { title: string; description: string; icon: string }
81
+ > = {
82
+ canvas: {
83
+ title: "Canvas API",
84
+ description: "Navigate the canvas and query selected shapes",
85
+ icon: "🎨",
86
+ },
87
+ storage: {
88
+ title: "Storage API",
89
+ description: "Persist data locally with key-value storage",
90
+ icon: "💾",
91
+ },
92
+ config: {
93
+ title: "Config API",
94
+ description: "Manage user-configurable settings",
95
+ icon: "⚙️",
96
+ },
97
+ ui: {
98
+ title: "UI API",
99
+ description: "Show notifications and confirmation dialogs",
100
+ icon: "🔔",
101
+ },
102
+ clipboard: {
103
+ title: "Clipboard API",
104
+ description: "Read and write to the system clipboard",
105
+ icon: "📋",
106
+ },
107
+ events: {
108
+ title: "Events API",
109
+ description: "React to selection and canvas changes",
110
+ icon: "📡",
111
+ },
112
+ network: {
113
+ title: "Network API",
114
+ description: "Call external APIs like GitHub, weather services, and more",
115
+ icon: "🌐",
116
+ },
117
+ info: {
118
+ title: "Workspace & Theme",
119
+ description: "Access workspace info and theme tokens",
120
+ icon: "ℹ️",
121
+ },
122
+ };
123
+
124
+ // ============================================================================
125
+ // INITIAL STATE
126
+ // ============================================================================
127
+
128
+ const initialState: OnboardingState = {
129
+ screen: "welcome",
130
+ currentStep: 0,
131
+ completedSteps: [],
132
+ skipped: false,
133
+ isLoaded: false,
134
+ };
135
+
136
+ // ============================================================================
137
+ // HOOK
138
+ // ============================================================================
139
+
140
+ export function useOnboarding(api: DOEExtensionAPI | null): UseOnboardingResult {
141
+ const [state, setState] = useState<OnboardingState>(initialState);
142
+
143
+ // Load state from storage on mount
144
+ useEffect(() => {
145
+ if (!api) return;
146
+
147
+ api.storage.get<OnboardingState>(STORAGE_KEY).then((savedState) => {
148
+ if (savedState && savedState.screen) {
149
+ setState({ ...savedState, isLoaded: true });
150
+ } else {
151
+ setState((s) => ({ ...s, isLoaded: true }));
152
+ }
153
+ });
154
+ }, [api]);
155
+
156
+ // Persist state to storage
157
+ const persistState = useCallback(
158
+ (newState: OnboardingState) => {
159
+ if (!api) return;
160
+ api.storage.set(STORAGE_KEY, newState);
161
+ },
162
+ [api]
163
+ );
164
+
165
+ const goToScreen = useCallback(
166
+ (screen: OnboardingScreen) => {
167
+ setState((prev) => {
168
+ const newState = { ...prev, screen };
169
+ persistState(newState);
170
+ return newState;
171
+ });
172
+ },
173
+ [persistState]
174
+ );
175
+
176
+ const nextStep = useCallback(() => {
177
+ setState((prev) => {
178
+ if (prev.currentStep >= STEPS.length - 1) {
179
+ // Move to complete screen
180
+ const newState = { ...prev, screen: "complete" as OnboardingScreen };
181
+ persistState(newState);
182
+ return newState;
183
+ }
184
+ const newState = { ...prev, currentStep: prev.currentStep + 1 };
185
+ persistState(newState);
186
+ return newState;
187
+ });
188
+ }, [persistState]);
189
+
190
+ const prevStep = useCallback(() => {
191
+ setState((prev) => {
192
+ if (prev.currentStep <= 0) return prev;
193
+ const newState = { ...prev, currentStep: prev.currentStep - 1 };
194
+ persistState(newState);
195
+ return newState;
196
+ });
197
+ }, [persistState]);
198
+
199
+ const completeStep = useCallback(() => {
200
+ setState((prev) => {
201
+ const stepId = STEPS[prev.currentStep];
202
+ const alreadyCompleted = prev.completedSteps.includes(stepId);
203
+ const completedSteps = alreadyCompleted
204
+ ? prev.completedSteps
205
+ : [...prev.completedSteps, stepId];
206
+
207
+ if (prev.currentStep >= STEPS.length - 1) {
208
+ // All steps done
209
+ const newState = {
210
+ ...prev,
211
+ completedSteps,
212
+ screen: "complete" as OnboardingScreen,
213
+ };
214
+ persistState(newState);
215
+ return newState;
216
+ }
217
+
218
+ const newState = {
219
+ ...prev,
220
+ completedSteps,
221
+ currentStep: prev.currentStep + 1,
222
+ };
223
+ persistState(newState);
224
+ return newState;
225
+ });
226
+ }, [persistState]);
227
+
228
+ const skip = useCallback(() => {
229
+ setState((prev) => {
230
+ const newState = {
231
+ ...prev,
232
+ skipped: true,
233
+ screen: "playground" as OnboardingScreen,
234
+ };
235
+ persistState(newState);
236
+ return newState;
237
+ });
238
+ }, [persistState]);
239
+
240
+ const restart = useCallback(() => {
241
+ const newState = {
242
+ ...initialState,
243
+ isLoaded: true,
244
+ };
245
+ persistState(newState);
246
+ setState(newState);
247
+ }, [persistState]);
248
+
249
+ const isComplete = state.completedSteps.length === STEPS.length;
250
+ const currentStepId = STEPS[state.currentStep];
251
+
252
+ return {
253
+ state,
254
+ goToScreen,
255
+ nextStep,
256
+ prevStep,
257
+ completeStep,
258
+ skip,
259
+ restart,
260
+ totalSteps: STEPS.length,
261
+ isComplete,
262
+ currentStepId,
263
+ };
264
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Pointer Handler Hooks for DOE Extensions
3
+ *
4
+ * These hooks help manage pointer events in extension UIs to ensure
5
+ * proper interaction between extension content and the DOE canvas.
6
+ *
7
+ * Extensions use `pointerEvents: "auto"`, which means the extension captures
8
+ * all pointer events. For interactive areas (buttons, inputs, scrollable content),
9
+ * you must use stopPropagation() to prevent those events from triggering
10
+ * canvas drag or other canvas actions.
11
+ */
12
+ import { useCallback, useEffect, type RefObject } from "react";
13
+
14
+ /**
15
+ * Hook for interactive areas that should NOT start a canvas drag.
16
+ * Use on buttons, inputs, scrollable content, dropdown menus, etc.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * function MyExtension() {
21
+ * const handleInteractive = useInteractivePointerDown();
22
+ *
23
+ * return (
24
+ * <div>
25
+ * <button onPointerDown={handleInteractive}>Click me</button>
26
+ * <input onPointerDown={handleInteractive} />
27
+ * <textarea onPointerDown={handleInteractive} />
28
+ * </div>
29
+ * );
30
+ * }
31
+ * ```
32
+ */
33
+ export function useInteractivePointerDown(): (e: React.PointerEvent) => void {
34
+ return useCallback((e: React.PointerEvent) => {
35
+ e.stopPropagation();
36
+ }, []);
37
+ }
38
+
39
+ /**
40
+ * Hook to prevent canvas zoom when scrolling inside extension.
41
+ * Use on scrollable containers to ensure scroll wheel events
42
+ * scroll the content instead of zooming the canvas.
43
+ *
44
+ * @param ref - Reference to the scrollable element
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * function MyExtension() {
49
+ * const scrollRef = useRef<HTMLDivElement>(null);
50
+ * usePreventCanvasZoom(scrollRef);
51
+ *
52
+ * return (
53
+ * <div ref={scrollRef} className="overflow-auto h-64">
54
+ * {/* Long scrollable content *\/}
55
+ * <div className="h-[1000px]">Content...</div>
56
+ * </div>
57
+ * );
58
+ * }
59
+ * ```
60
+ */
61
+ export function usePreventCanvasZoom(ref: RefObject<HTMLElement | null>): void {
62
+ useEffect(() => {
63
+ const el = ref.current;
64
+ if (!el) return;
65
+
66
+ const handleWheel = (e: WheelEvent) => {
67
+ e.stopPropagation();
68
+ };
69
+
70
+ el.addEventListener("wheel", handleWheel, { capture: true, passive: false });
71
+ return () => el.removeEventListener("wheel", handleWheel, { capture: true });
72
+ }, [ref]);
73
+ }
74
+
75
+ /**
76
+ * Combined hook for scrollable interactive areas.
77
+ * Provides both pointer down handler and wheel event blocking.
78
+ *
79
+ * @param ref - Reference to the scrollable element
80
+ * @returns Handler for onPointerDown events
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * function MyExtension() {
85
+ * const scrollRef = useRef<HTMLDivElement>(null);
86
+ * const handleInteractive = useScrollableArea(scrollRef);
87
+ *
88
+ * return (
89
+ * <div
90
+ * ref={scrollRef}
91
+ * className="overflow-auto"
92
+ * onPointerDown={handleInteractive}
93
+ * >
94
+ * Scrollable content...
95
+ * </div>
96
+ * );
97
+ * }
98
+ * ```
99
+ */
100
+ export function useScrollableArea(
101
+ ref: RefObject<HTMLElement | null>
102
+ ): (e: React.PointerEvent) => void {
103
+ usePreventCanvasZoom(ref);
104
+ return useInteractivePointerDown();
105
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * {{displayName}} - React Entry Point
3
+ *
4
+ * Renders React immediately. DOE connection is handled by useDoe hook.
5
+ * This allows the extension to work both standalone (for development)
6
+ * and inside DOE (for production).
7
+ */
8
+ import { createRoot } from "react-dom/client";
9
+ import { App } from "./App";
10
+
11
+ // Mount React immediately
12
+ const container = document.getElementById("root");
13
+ if (!container) {
14
+ throw new Error("Root element not found");
15
+ }
16
+
17
+ const root = createRoot(container);
18
+ root.render(<App />);
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Shared Styles for Extension Template
3
+ *
4
+ * CSS custom properties and reusable style objects for consistent theming.
5
+ * Uses inline styles (consistent with existing template pattern).
6
+ */
7
+ import type { CSSProperties } from "react";
8
+
9
+ // ============================================================================
10
+ // SPACING SCALE (4px base)
11
+ // ============================================================================
12
+ export const spacing = {
13
+ xs: 4,
14
+ sm: 8,
15
+ md: 16,
16
+ lg: 24,
17
+ xl: 32,
18
+ xxl: 48,
19
+ } as const;
20
+
21
+ // ============================================================================
22
+ // COLORS
23
+ // ============================================================================
24
+ export const colors = {
25
+ // Primary
26
+ primary: "#3b82f6",
27
+ primaryHover: "#2563eb",
28
+ primaryLight: "#dbeafe",
29
+
30
+ // Success
31
+ success: "#22c55e",
32
+ successLight: "#dcfce7",
33
+
34
+ // Warning
35
+ warning: "#f59e0b",
36
+ warningLight: "#fef3c7",
37
+
38
+ // Error
39
+ error: "#ef4444",
40
+ errorLight: "#fee2e2",
41
+
42
+ // Neutral
43
+ text: "#111827",
44
+ textSecondary: "#6b7280",
45
+ textMuted: "#9ca3af",
46
+ border: "#e5e7eb",
47
+ borderLight: "#f3f4f6",
48
+ background: "#ffffff",
49
+ backgroundSecondary: "#f9fafb",
50
+ backgroundHover: "#f3f4f6",
51
+ backgroundCode: "#1e293b",
52
+ } as const;
53
+
54
+ // ============================================================================
55
+ // TYPOGRAPHY
56
+ // ============================================================================
57
+ export const typography = {
58
+ fontFamily:
59
+ '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
60
+ sizes: {
61
+ xs: 11,
62
+ sm: 12,
63
+ base: 14,
64
+ lg: 16,
65
+ xl: 20,
66
+ xxl: 24,
67
+ },
68
+ weights: {
69
+ normal: 400,
70
+ medium: 500,
71
+ semibold: 600,
72
+ },
73
+ } as const;
74
+
75
+ // ============================================================================
76
+ // SHARED STYLE OBJECTS
77
+ // ============================================================================
78
+
79
+ export const buttonStyles = {
80
+ primary: {
81
+ padding: `${spacing.sm}px ${spacing.lg}px`,
82
+ background: colors.primary,
83
+ color: "white",
84
+ border: "none",
85
+ borderRadius: 8,
86
+ fontSize: typography.sizes.base,
87
+ fontWeight: typography.weights.medium,
88
+ cursor: "pointer",
89
+ transition: "all 0.15s ease",
90
+ display: "inline-flex",
91
+ alignItems: "center",
92
+ justifyContent: "center",
93
+ gap: spacing.sm,
94
+ } as CSSProperties,
95
+
96
+ secondary: {
97
+ padding: `${spacing.sm}px ${spacing.lg}px`,
98
+ background: "transparent",
99
+ color: colors.textSecondary,
100
+ border: `1px solid ${colors.border}`,
101
+ borderRadius: 8,
102
+ fontSize: typography.sizes.base,
103
+ fontWeight: typography.weights.medium,
104
+ cursor: "pointer",
105
+ transition: "all 0.15s ease",
106
+ display: "inline-flex",
107
+ alignItems: "center",
108
+ justifyContent: "center",
109
+ gap: spacing.sm,
110
+ } as CSSProperties,
111
+
112
+ link: {
113
+ padding: `${spacing.xs}px ${spacing.sm}px`,
114
+ background: "transparent",
115
+ color: colors.textSecondary,
116
+ border: "none",
117
+ fontSize: typography.sizes.sm,
118
+ cursor: "pointer",
119
+ textDecoration: "underline",
120
+ transition: "color 0.15s ease",
121
+ } as CSSProperties,
122
+ };
123
+
124
+ export const inputStyles = {
125
+ base: {
126
+ width: "100%",
127
+ padding: `${spacing.sm}px ${spacing.md}px`,
128
+ border: `1px solid ${colors.border}`,
129
+ borderRadius: 8,
130
+ fontSize: typography.sizes.base,
131
+ outline: "none",
132
+ transition: "border-color 0.15s ease",
133
+ boxSizing: "border-box",
134
+ } as CSSProperties,
135
+ };
136
+
137
+ export const cardStyles = {
138
+ base: {
139
+ background: colors.backgroundSecondary,
140
+ borderRadius: 12,
141
+ padding: spacing.md,
142
+ border: `1px solid ${colors.borderLight}`,
143
+ } as CSSProperties,
144
+
145
+ interactive: {
146
+ background: colors.backgroundSecondary,
147
+ borderRadius: 12,
148
+ padding: spacing.md,
149
+ border: `1px solid ${colors.borderLight}`,
150
+ cursor: "pointer",
151
+ transition: "all 0.15s ease",
152
+ } as CSSProperties,
153
+ };
154
+
155
+ // ============================================================================
156
+ // ANIMATION KEYFRAMES (as CSS string)
157
+ // ============================================================================
158
+ export const animationStyles = `
159
+ @keyframes fadeIn {
160
+ from { opacity: 0; }
161
+ to { opacity: 1; }
162
+ }
163
+
164
+ @keyframes slideInUp {
165
+ from {
166
+ opacity: 0;
167
+ transform: translateY(16px);
168
+ }
169
+ to {
170
+ opacity: 1;
171
+ transform: translateY(0);
172
+ }
173
+ }
174
+
175
+ @keyframes slideInLeft {
176
+ from {
177
+ opacity: 0;
178
+ transform: translateX(-16px);
179
+ }
180
+ to {
181
+ opacity: 1;
182
+ transform: translateX(0);
183
+ }
184
+ }
185
+
186
+ @keyframes slideInRight {
187
+ from {
188
+ opacity: 0;
189
+ transform: translateX(16px);
190
+ }
191
+ to {
192
+ opacity: 1;
193
+ transform: translateX(0);
194
+ }
195
+ }
196
+
197
+ @keyframes pulse {
198
+ 0%, 100% { opacity: 1; }
199
+ 50% { opacity: 0.5; }
200
+ }
201
+
202
+ @keyframes checkmark {
203
+ 0% {
204
+ stroke-dashoffset: 50;
205
+ }
206
+ 100% {
207
+ stroke-dashoffset: 0;
208
+ }
209
+ }
210
+
211
+ @keyframes scaleIn {
212
+ from {
213
+ opacity: 0;
214
+ transform: scale(0.9);
215
+ }
216
+ to {
217
+ opacity: 1;
218
+ transform: scale(1);
219
+ }
220
+ }
221
+ `;
222
+
223
+ // ============================================================================
224
+ // LAYOUT HELPERS
225
+ // ============================================================================
226
+ export const flexCenter: CSSProperties = {
227
+ display: "flex",
228
+ alignItems: "center",
229
+ justifyContent: "center",
230
+ };
231
+
232
+ export const flexBetween: CSSProperties = {
233
+ display: "flex",
234
+ alignItems: "center",
235
+ justifyContent: "space-between",
236
+ };
237
+
238
+ export const flexColumn: CSSProperties = {
239
+ display: "flex",
240
+ flexDirection: "column",
241
+ };
242
+
243
+ // ============================================================================
244
+ // CODE DISPLAY STYLES
245
+ // ============================================================================
246
+ export const codeStyles = {
247
+ container: {
248
+ background: "#1e1e1e",
249
+ borderRadius: 8,
250
+ padding: spacing.md,
251
+ overflow: "auto",
252
+ fontSize: typography.sizes.sm,
253
+ fontFamily: 'Monaco, Menlo, "Ubuntu Mono", Consolas, monospace',
254
+ lineHeight: 1.5,
255
+ } as CSSProperties,
256
+
257
+ keyword: { color: "#569cd6" },
258
+ string: { color: "#ce9178" },
259
+ comment: { color: "#6a9955" },
260
+ function: { color: "#dcdcaa" },
261
+ variable: { color: "#9cdcfe" },
262
+ property: { color: "#4ec9b0" },
263
+ operator: { color: "#d4d4d4" },
264
+ plain: { color: "#d4d4d4" },
265
+ };
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "declaration": false,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src",
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "resolveJsonModule": true,
19
+ "isolatedModules": true,
20
+ "noEmit": true,
21
+ "paths": {
22
+ "doe-sdk": ["../../dist/index.d.ts"],
23
+ "doe-sdk/*": ["../../dist/*"]
24
+ }
25
+ },
26
+ "include": ["src/**/*"],
27
+ "exclude": ["node_modules", "dist"]
28
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Vite Configuration for DOE Extension
3
+ *
4
+ * Builds the extension as a single HTML + JS bundle that can be loaded in DOE.
5
+ */
6
+ import { defineConfig } from "vite";
7
+ import react from "@vitejs/plugin-react";
8
+
9
+ export default defineConfig({
10
+ plugins: [react()],
11
+ base: "./", // Use relative paths for DOE custom protocol
12
+ build: {
13
+ outDir: "dist",
14
+ // Inline all assets for simpler loading
15
+ assetsInlineLimit: 100000,
16
+ rollupOptions: {
17
+ output: {
18
+ // Single JS file
19
+ entryFileNames: "assets/[name].js",
20
+ chunkFileNames: "assets/[name].js",
21
+ assetFileNames: "assets/[name].[ext]",
22
+ },
23
+ },
24
+ target: "esnext",
25
+ minify: true,
26
+ sourcemap: false,
27
+ },
28
+ server: {
29
+ port: 3001,
30
+ strictPort: true,
31
+ },
32
+ });