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.
- package/README.md +509 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +118 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +25 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +100 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/login.d.ts +52 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +571 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/publish.d.ts +27 -0
- package/dist/cli/publish.d.ts.map +1 -0
- package/dist/cli/publish.js +531 -0
- package/dist/cli/publish.js.map +1 -0
- package/dist/cli/scaffold.d.ts +18 -0
- package/dist/cli/scaffold.d.ts.map +1 -0
- package/dist/cli/scaffold.js +252 -0
- package/dist/cli/scaffold.js.map +1 -0
- package/dist/cli/ui.d.ts +57 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +339 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli/validate.d.ts +28 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +1270 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/compat/legacy-adapter.d.ts +198 -0
- package/dist/compat/legacy-adapter.d.ts.map +1 -0
- package/dist/compat/legacy-adapter.js +318 -0
- package/dist/compat/legacy-adapter.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/client.d.ts +370 -0
- package/dist/runtime/client.d.ts.map +1 -0
- package/dist/runtime/client.js +470 -0
- package/dist/runtime/client.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/types/api.d.ts +564 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +11 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/manifest.d.ts +412 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/manifest.js +42 -0
- package/dist/types/manifest.js.map +1 -0
- package/dist/types/marketplace-categories.d.ts +9 -0
- package/dist/types/marketplace-categories.d.ts.map +1 -0
- package/dist/types/marketplace-categories.js +16 -0
- package/dist/types/marketplace-categories.js.map +1 -0
- package/dist/types/permissions.d.ts +86 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +295 -0
- package/dist/types/permissions.js.map +1 -0
- package/dist/types/theme/index.d.ts +7 -0
- package/dist/types/theme/index.d.ts.map +1 -0
- package/dist/types/theme/index.js +7 -0
- package/dist/types/theme/index.js.map +1 -0
- package/dist/types/theme/schema.d.ts +1205 -0
- package/dist/types/theme/schema.d.ts.map +1 -0
- package/dist/types/theme/schema.js +325 -0
- package/dist/types/theme/schema.js.map +1 -0
- package/dist/types/theme/types.d.ts +648 -0
- package/dist/types/theme/types.d.ts.map +1 -0
- package/dist/types/theme/types.js +8 -0
- package/dist/types/theme/types.js.map +1 -0
- package/package.json +75 -0
- package/templates/extension/README.md +254 -0
- package/templates/extension/icon.png +0 -0
- package/templates/extension/index.html +42 -0
- package/templates/extension/manifest.json +57 -0
- package/templates/extension/package.json +24 -0
- package/templates/extension/src/App.tsx +252 -0
- package/templates/extension/src/components/OnboardingComplete.tsx +190 -0
- package/templates/extension/src/components/OnboardingProgress.tsx +82 -0
- package/templates/extension/src/components/OnboardingWelcome.tsx +166 -0
- package/templates/extension/src/components/StepContainer.tsx +217 -0
- package/templates/extension/src/components/playground/CanvasTab.tsx +24 -0
- package/templates/extension/src/components/playground/ConfigTab.tsx +24 -0
- package/templates/extension/src/components/playground/EventsTab.tsx +24 -0
- package/templates/extension/src/components/playground/InfoTab.tsx +89 -0
- package/templates/extension/src/components/playground/NetworkTab.tsx +24 -0
- package/templates/extension/src/components/playground/PlaygroundContainer.tsx +184 -0
- package/templates/extension/src/components/playground/ResultDisplay.tsx +30 -0
- package/templates/extension/src/components/playground/StorageTab.tsx +24 -0
- package/templates/extension/src/components/playground/UITab.tsx +24 -0
- package/templates/extension/src/components/shared/CanvasControls.tsx +130 -0
- package/templates/extension/src/components/shared/ConfigControls.tsx +154 -0
- package/templates/extension/src/components/shared/EventsControls.tsx +232 -0
- package/templates/extension/src/components/shared/InfoControls.tsx +281 -0
- package/templates/extension/src/components/shared/NetworkControls.tsx +328 -0
- package/templates/extension/src/components/shared/StorageControls.tsx +203 -0
- package/templates/extension/src/components/shared/UIControls.tsx +199 -0
- package/templates/extension/src/components/shared/index.ts +15 -0
- package/templates/extension/src/components/steps/CanvasStep.tsx +67 -0
- package/templates/extension/src/components/steps/ClipboardStep.tsx +167 -0
- package/templates/extension/src/components/steps/ConfigStep.tsx +63 -0
- package/templates/extension/src/components/steps/EventsStep.tsx +69 -0
- package/templates/extension/src/components/steps/InfoStep.tsx +70 -0
- package/templates/extension/src/components/steps/NetworkStep.tsx +70 -0
- package/templates/extension/src/components/steps/StorageStep.tsx +61 -0
- package/templates/extension/src/components/steps/UIStep.tsx +70 -0
- package/templates/extension/src/hooks/useDoe.ts +93 -0
- package/templates/extension/src/hooks/useOnboarding.ts +264 -0
- package/templates/extension/src/hooks/usePointerHandlers.ts +105 -0
- package/templates/extension/src/main.tsx +18 -0
- package/templates/extension/src/styles.ts +265 -0
- package/templates/extension/tsconfig.json +28 -0
- package/templates/extension/vite.config.ts +32 -0
- package/templates/theme/README.md +132 -0
- package/templates/theme/manifest.json +19 -0
- package/templates/theme/package.json +16 -0
- package/templates/theme/styles/.gitkeep +2 -0
- package/templates/theme/themes/theme.json +32 -0
- package/templates/theme/vite-plugin-doe-theme.ts +53 -0
- package/templates/theme/vite.config.ts +10 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StepContainer - Wrapper for onboarding step content
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent layout, navigation, and code toggle functionality.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState, useRef, type ReactNode } from "react";
|
|
7
|
+
import {
|
|
8
|
+
useInteractivePointerDown,
|
|
9
|
+
usePreventCanvasZoom,
|
|
10
|
+
} from "../hooks/usePointerHandlers";
|
|
11
|
+
import {
|
|
12
|
+
spacing,
|
|
13
|
+
colors,
|
|
14
|
+
typography,
|
|
15
|
+
buttonStyles,
|
|
16
|
+
cardStyles,
|
|
17
|
+
codeStyles,
|
|
18
|
+
flexBetween,
|
|
19
|
+
animationStyles,
|
|
20
|
+
} from "../styles";
|
|
21
|
+
|
|
22
|
+
export interface StepContainerProps {
|
|
23
|
+
/** Step title */
|
|
24
|
+
title: string;
|
|
25
|
+
/** Step description */
|
|
26
|
+
description: string;
|
|
27
|
+
/** Step icon (emoji) */
|
|
28
|
+
icon: string;
|
|
29
|
+
/** Current step number (1-based for display) */
|
|
30
|
+
stepNumber: number;
|
|
31
|
+
/** Total number of steps */
|
|
32
|
+
totalSteps: number;
|
|
33
|
+
/** Interactive demo content */
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
/** Code example to show */
|
|
36
|
+
codeExample?: string;
|
|
37
|
+
/** Result/output to display */
|
|
38
|
+
result?: ReactNode;
|
|
39
|
+
/** Navigate to previous step */
|
|
40
|
+
onPrev: () => void;
|
|
41
|
+
/** Navigate to next step (or complete) */
|
|
42
|
+
onNext: () => void;
|
|
43
|
+
/** Whether this is the last step */
|
|
44
|
+
isLastStep?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function StepContainer({
|
|
48
|
+
title,
|
|
49
|
+
description,
|
|
50
|
+
icon,
|
|
51
|
+
stepNumber,
|
|
52
|
+
totalSteps,
|
|
53
|
+
children,
|
|
54
|
+
codeExample,
|
|
55
|
+
result,
|
|
56
|
+
onPrev,
|
|
57
|
+
onNext,
|
|
58
|
+
isLastStep = false,
|
|
59
|
+
}: StepContainerProps): React.ReactElement {
|
|
60
|
+
const [showCode, setShowCode] = useState(false);
|
|
61
|
+
const handlePointerDown = useInteractivePointerDown();
|
|
62
|
+
const scrollRef = useRef<HTMLDivElement>(null);
|
|
63
|
+
usePreventCanvasZoom(scrollRef);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
ref={scrollRef}
|
|
68
|
+
style={{
|
|
69
|
+
display: "flex",
|
|
70
|
+
flexDirection: "column",
|
|
71
|
+
height: "100%",
|
|
72
|
+
overflow: "auto",
|
|
73
|
+
animation: "slideInRight 0.3s ease-out",
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
<style>{animationStyles}</style>
|
|
77
|
+
|
|
78
|
+
{/* Header */}
|
|
79
|
+
<div style={{ marginBottom: spacing.lg }}>
|
|
80
|
+
<div
|
|
81
|
+
style={{
|
|
82
|
+
display: "flex",
|
|
83
|
+
alignItems: "center",
|
|
84
|
+
gap: spacing.sm,
|
|
85
|
+
marginBottom: spacing.xs,
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
<span style={{ fontSize: typography.sizes.xl }}>{icon}</span>
|
|
89
|
+
<h2
|
|
90
|
+
style={{
|
|
91
|
+
fontSize: typography.sizes.xl,
|
|
92
|
+
fontWeight: typography.weights.semibold,
|
|
93
|
+
color: colors.text,
|
|
94
|
+
margin: 0,
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
{title}
|
|
98
|
+
</h2>
|
|
99
|
+
</div>
|
|
100
|
+
<p
|
|
101
|
+
style={{
|
|
102
|
+
fontSize: typography.sizes.base,
|
|
103
|
+
color: colors.textSecondary,
|
|
104
|
+
margin: 0,
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
{description}
|
|
108
|
+
</p>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{/* Demo Area */}
|
|
112
|
+
<div style={{ ...cardStyles.base, marginBottom: spacing.md, flex: 1 }}>
|
|
113
|
+
{children}
|
|
114
|
+
|
|
115
|
+
{/* Result Display */}
|
|
116
|
+
{result && (
|
|
117
|
+
<div
|
|
118
|
+
style={{
|
|
119
|
+
marginTop: spacing.md,
|
|
120
|
+
padding: spacing.sm,
|
|
121
|
+
background: colors.backgroundHover,
|
|
122
|
+
borderRadius: 6,
|
|
123
|
+
fontSize: typography.sizes.sm,
|
|
124
|
+
fontFamily: "monospace",
|
|
125
|
+
color: colors.textSecondary,
|
|
126
|
+
wordBreak: "break-word",
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
{result}
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* Code Toggle */}
|
|
135
|
+
{codeExample && (
|
|
136
|
+
<div style={{ marginBottom: spacing.md }}>
|
|
137
|
+
<button
|
|
138
|
+
onClick={() => setShowCode(!showCode)}
|
|
139
|
+
onPointerDown={handlePointerDown}
|
|
140
|
+
style={{
|
|
141
|
+
...buttonStyles.link,
|
|
142
|
+
display: "flex",
|
|
143
|
+
alignItems: "center",
|
|
144
|
+
gap: spacing.xs,
|
|
145
|
+
padding: 0,
|
|
146
|
+
marginBottom: spacing.sm,
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<span
|
|
150
|
+
style={{
|
|
151
|
+
transform: showCode ? "rotate(90deg)" : "rotate(0deg)",
|
|
152
|
+
transition: "transform 0.15s ease",
|
|
153
|
+
display: "inline-block",
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
▶
|
|
157
|
+
</span>
|
|
158
|
+
{showCode ? "Hide Code" : "Show Code"}
|
|
159
|
+
</button>
|
|
160
|
+
|
|
161
|
+
{showCode && (
|
|
162
|
+
<div
|
|
163
|
+
style={{
|
|
164
|
+
...codeStyles.container,
|
|
165
|
+
animation: "slideInUp 0.2s ease-out",
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
<pre style={{ margin: 0, whiteSpace: "pre-wrap" }}>
|
|
169
|
+
<code style={{ color: codeStyles.plain.color }}>
|
|
170
|
+
{codeExample}
|
|
171
|
+
</code>
|
|
172
|
+
</pre>
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
177
|
+
|
|
178
|
+
{/* Navigation */}
|
|
179
|
+
<div
|
|
180
|
+
style={{
|
|
181
|
+
...flexBetween,
|
|
182
|
+
paddingTop: spacing.md,
|
|
183
|
+
borderTop: `1px solid ${colors.border}`,
|
|
184
|
+
}}
|
|
185
|
+
>
|
|
186
|
+
<button
|
|
187
|
+
onClick={onPrev}
|
|
188
|
+
onPointerDown={handlePointerDown}
|
|
189
|
+
style={{
|
|
190
|
+
...buttonStyles.secondary,
|
|
191
|
+
opacity: stepNumber === 1 ? 0.5 : 1,
|
|
192
|
+
}}
|
|
193
|
+
disabled={stepNumber === 1}
|
|
194
|
+
>
|
|
195
|
+
← Back
|
|
196
|
+
</button>
|
|
197
|
+
|
|
198
|
+
<span
|
|
199
|
+
style={{
|
|
200
|
+
fontSize: typography.sizes.sm,
|
|
201
|
+
color: colors.textMuted,
|
|
202
|
+
}}
|
|
203
|
+
>
|
|
204
|
+
{stepNumber} / {totalSteps}
|
|
205
|
+
</span>
|
|
206
|
+
|
|
207
|
+
<button
|
|
208
|
+
onClick={onNext}
|
|
209
|
+
onPointerDown={handlePointerDown}
|
|
210
|
+
style={buttonStyles.primary}
|
|
211
|
+
>
|
|
212
|
+
{isLastStep ? "Complete" : "Next →"}
|
|
213
|
+
</button>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CanvasTab - Playground tab for Canvas API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared CanvasControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { CanvasControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface CanvasTabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function CanvasTab({ api }: CanvasTabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<CanvasControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigTab - Playground tab for Config API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared ConfigControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { ConfigControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface ConfigTabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function ConfigTab({ api }: ConfigTabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<ConfigControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventsTab - Playground tab for Events API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared EventsControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { EventsControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface EventsTabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function EventsTab({ api }: EventsTabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<EventsControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InfoTab - Playground tab for Workspace and Theme info
|
|
3
|
+
*
|
|
4
|
+
* Uses shared InfoControls component for DRY code,
|
|
5
|
+
* plus extension-specific info display.
|
|
6
|
+
*/
|
|
7
|
+
import React, { useState } from "react";
|
|
8
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
9
|
+
import { InfoControls } from "../shared";
|
|
10
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
11
|
+
import { spacing, colors, typography, cardStyles } from "../../styles";
|
|
12
|
+
|
|
13
|
+
export interface InfoTabProps {
|
|
14
|
+
api: DOEExtensionAPI;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function InfoTab({ api }: InfoTabProps): React.ReactElement {
|
|
18
|
+
const [result, setResult] = useState<string>("");
|
|
19
|
+
const extensionInfo = api.extension;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div>
|
|
23
|
+
{/* Extension info (specific to playground) */}
|
|
24
|
+
<div style={{ marginBottom: spacing.md }}>
|
|
25
|
+
<div
|
|
26
|
+
style={{
|
|
27
|
+
fontSize: typography.sizes.sm,
|
|
28
|
+
fontWeight: typography.weights.medium,
|
|
29
|
+
color: colors.textSecondary,
|
|
30
|
+
marginBottom: spacing.xs,
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
Extension
|
|
34
|
+
</div>
|
|
35
|
+
<div
|
|
36
|
+
style={{
|
|
37
|
+
...cardStyles.base,
|
|
38
|
+
background: colors.backgroundHover,
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<div style={{ marginBottom: spacing.xs }}>
|
|
42
|
+
<span style={{ fontSize: typography.sizes.sm, color: colors.textSecondary }}>ID: </span>
|
|
43
|
+
<span
|
|
44
|
+
style={{
|
|
45
|
+
fontSize: typography.sizes.sm,
|
|
46
|
+
fontWeight: typography.weights.medium,
|
|
47
|
+
color: colors.text,
|
|
48
|
+
fontFamily: "monospace",
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{extensionInfo.id}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div style={{ marginBottom: spacing.xs }}>
|
|
55
|
+
<span style={{ fontSize: typography.sizes.sm, color: colors.textSecondary }}>
|
|
56
|
+
Version:{" "}
|
|
57
|
+
</span>
|
|
58
|
+
<span
|
|
59
|
+
style={{
|
|
60
|
+
fontSize: typography.sizes.sm,
|
|
61
|
+
fontWeight: typography.weights.medium,
|
|
62
|
+
color: colors.text,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{extensionInfo.version}
|
|
66
|
+
</span>
|
|
67
|
+
</div>
|
|
68
|
+
<div>
|
|
69
|
+
<span style={{ fontSize: typography.sizes.sm, color: colors.textSecondary }}>
|
|
70
|
+
Permissions:{" "}
|
|
71
|
+
</span>
|
|
72
|
+
<span
|
|
73
|
+
style={{
|
|
74
|
+
fontSize: typography.sizes.sm,
|
|
75
|
+
fontWeight: typography.weights.medium,
|
|
76
|
+
color: colors.text,
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
{extensionInfo.permissions?.length || 0} granted
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<InfoControls api={api} onResult={setResult} />
|
|
86
|
+
<ResultDisplay result={result} />
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NetworkTab - Playground tab for Network API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared NetworkControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { NetworkControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface NetworkTabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function NetworkTab({ api }: NetworkTabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<NetworkControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlaygroundContainer - Tabbed playground for exploring SDK APIs
|
|
3
|
+
*
|
|
4
|
+
* Post-onboarding environment for free exploration of all APIs.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState, useRef } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { useInteractivePointerDown, usePreventCanvasZoom } from "../../hooks/usePointerHandlers";
|
|
9
|
+
import { spacing, colors, typography, animationStyles } from "../../styles";
|
|
10
|
+
import { CanvasTab } from "./CanvasTab";
|
|
11
|
+
import { StorageTab } from "./StorageTab";
|
|
12
|
+
import { ConfigTab } from "./ConfigTab";
|
|
13
|
+
import { UITab } from "./UITab";
|
|
14
|
+
import { EventsTab } from "./EventsTab";
|
|
15
|
+
import { NetworkTab } from "./NetworkTab";
|
|
16
|
+
import { InfoTab } from "./InfoTab";
|
|
17
|
+
|
|
18
|
+
export interface PlaygroundContainerProps {
|
|
19
|
+
api: DOEExtensionAPI;
|
|
20
|
+
onRestartOnboarding: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type TabId = "canvas" | "storage" | "config" | "ui" | "events" | "network" | "info";
|
|
24
|
+
|
|
25
|
+
interface Tab {
|
|
26
|
+
id: TabId;
|
|
27
|
+
label: string;
|
|
28
|
+
icon: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const TABS: Tab[] = [
|
|
32
|
+
{ id: "canvas", label: "Canvas", icon: "🎨" },
|
|
33
|
+
{ id: "storage", label: "Storage", icon: "💾" },
|
|
34
|
+
{ id: "config", label: "Config", icon: "⚙️" },
|
|
35
|
+
{ id: "ui", label: "UI", icon: "🔔" },
|
|
36
|
+
{ id: "events", label: "Events", icon: "📡" },
|
|
37
|
+
{ id: "network", label: "Network", icon: "🌐" },
|
|
38
|
+
{ id: "info", label: "Info", icon: "ℹ️" },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export function PlaygroundContainer({
|
|
42
|
+
api,
|
|
43
|
+
onRestartOnboarding,
|
|
44
|
+
}: PlaygroundContainerProps): React.ReactElement {
|
|
45
|
+
const [activeTab, setActiveTab] = useState<TabId>("canvas");
|
|
46
|
+
const handlePointerDown = useInteractivePointerDown();
|
|
47
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
48
|
+
usePreventCanvasZoom(contentRef);
|
|
49
|
+
|
|
50
|
+
const renderTabContent = () => {
|
|
51
|
+
switch (activeTab) {
|
|
52
|
+
case "canvas":
|
|
53
|
+
return <CanvasTab api={api} />;
|
|
54
|
+
case "storage":
|
|
55
|
+
return <StorageTab api={api} />;
|
|
56
|
+
case "config":
|
|
57
|
+
return <ConfigTab api={api} />;
|
|
58
|
+
case "ui":
|
|
59
|
+
return <UITab api={api} />;
|
|
60
|
+
case "events":
|
|
61
|
+
return <EventsTab api={api} />;
|
|
62
|
+
case "network":
|
|
63
|
+
return <NetworkTab api={api} />;
|
|
64
|
+
case "info":
|
|
65
|
+
return <InfoTab api={api} />;
|
|
66
|
+
default:
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div
|
|
73
|
+
style={{
|
|
74
|
+
display: "flex",
|
|
75
|
+
flexDirection: "column",
|
|
76
|
+
height: "100%",
|
|
77
|
+
animation: "fadeIn 0.3s ease-out",
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<style>{animationStyles}</style>
|
|
81
|
+
|
|
82
|
+
{/* Header */}
|
|
83
|
+
<div
|
|
84
|
+
style={{
|
|
85
|
+
display: "flex",
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
justifyContent: "space-between",
|
|
88
|
+
marginBottom: spacing.md,
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<div>
|
|
92
|
+
<h1
|
|
93
|
+
style={{
|
|
94
|
+
fontSize: typography.sizes.lg,
|
|
95
|
+
fontWeight: typography.weights.semibold,
|
|
96
|
+
color: colors.text,
|
|
97
|
+
margin: 0,
|
|
98
|
+
}}
|
|
99
|
+
>
|
|
100
|
+
SDK Playground
|
|
101
|
+
</h1>
|
|
102
|
+
<p
|
|
103
|
+
style={{
|
|
104
|
+
fontSize: typography.sizes.xs,
|
|
105
|
+
color: colors.textMuted,
|
|
106
|
+
margin: 0,
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
Explore APIs freely
|
|
110
|
+
</p>
|
|
111
|
+
</div>
|
|
112
|
+
<button
|
|
113
|
+
onClick={onRestartOnboarding}
|
|
114
|
+
onPointerDown={handlePointerDown}
|
|
115
|
+
style={{
|
|
116
|
+
padding: `${spacing.xs}px ${spacing.sm}px`,
|
|
117
|
+
background: "transparent",
|
|
118
|
+
border: `1px solid ${colors.border}`,
|
|
119
|
+
borderRadius: 6,
|
|
120
|
+
fontSize: typography.sizes.xs,
|
|
121
|
+
color: colors.textSecondary,
|
|
122
|
+
cursor: "pointer",
|
|
123
|
+
transition: "all 0.15s ease",
|
|
124
|
+
}}
|
|
125
|
+
>
|
|
126
|
+
↻ Restart Tour
|
|
127
|
+
</button>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{/* Tab bar */}
|
|
131
|
+
<div
|
|
132
|
+
style={{
|
|
133
|
+
display: "flex",
|
|
134
|
+
gap: spacing.xs,
|
|
135
|
+
marginBottom: spacing.md,
|
|
136
|
+
overflowX: "auto",
|
|
137
|
+
paddingBottom: spacing.xs,
|
|
138
|
+
}}
|
|
139
|
+
onPointerDown={handlePointerDown}
|
|
140
|
+
>
|
|
141
|
+
{TABS.map((tab) => (
|
|
142
|
+
<button
|
|
143
|
+
key={tab.id}
|
|
144
|
+
onClick={() => setActiveTab(tab.id)}
|
|
145
|
+
onPointerDown={handlePointerDown}
|
|
146
|
+
style={{
|
|
147
|
+
display: "flex",
|
|
148
|
+
alignItems: "center",
|
|
149
|
+
gap: spacing.xs,
|
|
150
|
+
padding: `${spacing.sm}px ${spacing.md}px`,
|
|
151
|
+
background: activeTab === tab.id ? colors.primary : "transparent",
|
|
152
|
+
color: activeTab === tab.id ? "white" : colors.textSecondary,
|
|
153
|
+
border: activeTab === tab.id ? "none" : `1px solid ${colors.border}`,
|
|
154
|
+
borderRadius: 8,
|
|
155
|
+
fontSize: typography.sizes.sm,
|
|
156
|
+
fontWeight: typography.weights.medium,
|
|
157
|
+
cursor: "pointer",
|
|
158
|
+
transition: "all 0.15s ease",
|
|
159
|
+
whiteSpace: "nowrap",
|
|
160
|
+
flexShrink: 0,
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
<span>{tab.icon}</span>
|
|
164
|
+
{tab.label}
|
|
165
|
+
</button>
|
|
166
|
+
))}
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
{/* Tab content */}
|
|
170
|
+
<div
|
|
171
|
+
ref={contentRef}
|
|
172
|
+
style={{
|
|
173
|
+
flex: 1,
|
|
174
|
+
overflow: "auto",
|
|
175
|
+
background: colors.backgroundSecondary,
|
|
176
|
+
borderRadius: 12,
|
|
177
|
+
padding: spacing.md,
|
|
178
|
+
}}
|
|
179
|
+
>
|
|
180
|
+
{renderTabContent()}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResultDisplay - Shared result display for playground tabs
|
|
3
|
+
*/
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { spacing, colors, typography } from "../../styles";
|
|
6
|
+
|
|
7
|
+
export interface ResultDisplayProps {
|
|
8
|
+
result: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ResultDisplay({ result }: ResultDisplayProps): React.ReactElement | null {
|
|
12
|
+
if (!result) return null;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
style={{
|
|
17
|
+
marginTop: spacing.md,
|
|
18
|
+
padding: spacing.sm,
|
|
19
|
+
background: colors.backgroundHover,
|
|
20
|
+
borderRadius: 6,
|
|
21
|
+
fontSize: typography.sizes.sm,
|
|
22
|
+
color: colors.textSecondary,
|
|
23
|
+
fontFamily: "monospace",
|
|
24
|
+
whiteSpace: "pre-wrap",
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
{result}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorageTab - Playground tab for Storage API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared StorageControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { StorageControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface StorageTabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function StorageTab({ api }: StorageTabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<StorageControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UITab - Playground tab for UI API exploration
|
|
3
|
+
*
|
|
4
|
+
* Uses shared UIControls component for DRY code.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from "react";
|
|
7
|
+
import type { DOEExtensionAPI } from "doe-sdk/runtime";
|
|
8
|
+
import { UIControls } from "../shared";
|
|
9
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
10
|
+
|
|
11
|
+
export interface UITabProps {
|
|
12
|
+
api: DOEExtensionAPI;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function UITab({ api }: UITabProps): React.ReactElement {
|
|
16
|
+
const [result, setResult] = useState<string>("");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<UIControls api={api} onResult={setResult} />
|
|
21
|
+
<ResultDisplay result={result} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|