@wakastellar/ui 3.3.3 → 3.5.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 (140) hide show
  1. package/dist/badge-BbwO7QeZ.js +1 -0
  2. package/dist/badge-BfiocODp.mjs +23 -0
  3. package/dist/charts.cjs.js +1 -1
  4. package/dist/charts.es.js +1 -1
  5. package/dist/chunk-14q5BKub.js +1 -0
  6. package/dist/{chunk-BH6uBOac.mjs → chunk-Cr9pTUWm.mjs} +5 -5
  7. package/dist/cn-DEtaFQsA.js +1 -0
  8. package/dist/cn-DUn6aSIQ.mjs +24 -0
  9. package/dist/doc.cjs.js +2 -2
  10. package/dist/doc.es.js +19 -19
  11. package/dist/editor.cjs.js +48 -0
  12. package/dist/editor.d.ts +1 -0
  13. package/dist/editor.es.js +6551 -0
  14. package/dist/{exceljs.min-DG9M8IZ1.mjs → exceljs.min-DL1XYDll.mjs} +1 -1
  15. package/dist/{exceljs.min-BuefmDRS.js → exceljs.min-qeIfSCbF.js} +1 -1
  16. package/dist/export.cjs.js +1 -1
  17. package/dist/export.es.js +1 -1
  18. package/dist/index.cjs.js +150 -150
  19. package/dist/index.es.js +26782 -27591
  20. package/dist/input-BfaSAGVw.js +1 -0
  21. package/dist/input-DVr_Qkl8.mjs +14 -0
  22. package/dist/rich-text.cjs.js +1 -1
  23. package/dist/rich-text.es.js +1 -1
  24. package/dist/security-CyBpuklN.mjs +122 -0
  25. package/dist/security-bFWwDrlg.js +1 -0
  26. package/dist/separator-NrkltulH.js +1 -0
  27. package/dist/separator-ibN2mycs.mjs +51 -0
  28. package/dist/src/components/editor/blocks/index.d.ts +51 -0
  29. package/dist/src/components/editor/blocks/waka-acceptance-criteria-block.d.ts +60 -0
  30. package/dist/src/components/editor/blocks/waka-ai-assist-block.d.ts +58 -0
  31. package/dist/src/components/editor/blocks/waka-api-endpoint-block.d.ts +63 -0
  32. package/dist/src/components/editor/blocks/waka-code-playground-block.d.ts +61 -0
  33. package/dist/src/components/editor/blocks/waka-comment-thread-block.d.ts +85 -0
  34. package/dist/src/components/editor/blocks/waka-diagram-block.d.ts +52 -0
  35. package/dist/src/components/editor/blocks/waka-embed-block.d.ts +58 -0
  36. package/dist/src/components/editor/blocks/waka-slash-menu-block.d.ts +67 -0
  37. package/dist/src/components/editor/blocks/waka-user-story-block.d.ts +79 -0
  38. package/dist/src/components/editor/blocks/waka-version-diff-block.d.ts +73 -0
  39. package/dist/src/components/editor/index.d.ts +66 -0
  40. package/dist/src/components/editor/waka-ai-writer.d.ts +80 -0
  41. package/dist/src/components/editor/waka-collaborative-editor.d.ts +93 -0
  42. package/dist/src/components/editor/waka-diff-viewer.d.ts +71 -0
  43. package/dist/src/components/editor/waka-dnd-editor.d.ts +64 -0
  44. package/dist/src/components/editor/waka-document-editor.d.ts +92 -0
  45. package/dist/src/components/editor/waka-editor-elements.d.ts +79 -0
  46. package/dist/src/components/editor/waka-editor-leaves.d.ts +39 -0
  47. package/dist/src/components/editor/waka-editor-plugins.d.ts +41 -0
  48. package/dist/src/components/editor/waka-editor-toolbar.d.ts +20 -0
  49. package/dist/src/components/editor/waka-editor.d.ts +59 -0
  50. package/dist/src/components/editor/waka-floating-toolbar.d.ts +47 -0
  51. package/dist/src/components/editor/waka-markdown-editor.d.ts +60 -0
  52. package/dist/src/components/editor/waka-mention-editor.d.ts +125 -0
  53. package/dist/src/components/editor/waka-slash-menu.d.ts +70 -0
  54. package/dist/src/components/editor/waka-spec-editor.d.ts +88 -0
  55. package/dist/src/components/index.d.ts +1 -15
  56. package/dist/src/editor.d.ts +26 -0
  57. package/dist/textarea-CdQWggYG.js +1 -0
  58. package/dist/textarea-DJDXJ3nd.mjs +23 -0
  59. package/dist/types-C2St0wOW.js +1 -0
  60. package/dist/{types-B6GVaSIP.mjs → types-JnqoLyuv.mjs} +214 -211
  61. package/dist/{useDataTableImport-BPvfo--2.mjs → useDataTableImport-BWUFesPi.mjs} +3 -3
  62. package/dist/{useDataTableImport-Cm_pCKnO.js → useDataTableImport-T7ddpN5k.js} +3 -3
  63. package/dist/waka-doc-renderer-CTxC7Trf.js +3 -0
  64. package/dist/{waka-doc-renderer-BkIvas3z.mjs → waka-doc-renderer-Cw-Xnyen.mjs} +264 -281
  65. package/dist/waka-editor-plugins-DR6tpsUC.mjs +135 -0
  66. package/dist/waka-editor-plugins-sGSh9hn2.js +1 -0
  67. package/dist/waka-rich-text-editor-BlIdtknG.js +1 -0
  68. package/dist/waka-rich-text-editor-D1uA3zbB.js +1 -0
  69. package/dist/waka-rich-text-editor-DgSWiXMW.mjs +342 -0
  70. package/dist/waka-rich-text-editor-DndVJuDw.mjs +2 -0
  71. package/package.json +87 -2
  72. package/src/blocks/footer/index.tsx +1 -6
  73. package/src/blocks/login/index.tsx +1 -7
  74. package/src/blocks/profile/index.tsx +3 -5
  75. package/src/components/editor/blocks/index.ts +182 -0
  76. package/src/components/editor/blocks/waka-acceptance-criteria-block.tsx +326 -0
  77. package/src/components/editor/blocks/waka-ai-assist-block.tsx +284 -0
  78. package/src/components/editor/blocks/waka-api-endpoint-block.tsx +382 -0
  79. package/src/components/editor/blocks/waka-code-playground-block.tsx +331 -0
  80. package/src/components/editor/blocks/waka-comment-thread-block.tsx +448 -0
  81. package/src/components/editor/blocks/waka-diagram-block.tsx +293 -0
  82. package/src/components/editor/blocks/waka-embed-block.tsx +416 -0
  83. package/src/components/editor/blocks/waka-slash-menu-block.tsx +432 -0
  84. package/src/components/editor/blocks/waka-user-story-block.tsx +295 -0
  85. package/src/components/editor/blocks/waka-version-diff-block.tsx +426 -0
  86. package/src/components/editor/index.ts +279 -0
  87. package/src/components/editor/waka-ai-writer.tsx +434 -0
  88. package/src/components/editor/waka-collaborative-editor.tsx +426 -0
  89. package/src/components/editor/waka-diff-viewer.tsx +352 -0
  90. package/src/components/editor/waka-dnd-editor.tsx +284 -0
  91. package/src/components/editor/waka-document-editor.tsx +502 -0
  92. package/src/components/editor/waka-editor-elements.tsx +312 -0
  93. package/src/components/editor/waka-editor-leaves.tsx +101 -0
  94. package/src/components/editor/waka-editor-plugins.ts +207 -0
  95. package/src/components/editor/waka-editor-toolbar.tsx +358 -0
  96. package/src/components/editor/waka-editor.tsx +431 -0
  97. package/src/components/editor/waka-floating-toolbar.tsx +268 -0
  98. package/src/components/editor/waka-markdown-editor.tsx +395 -0
  99. package/src/components/editor/waka-mention-editor.tsx +459 -0
  100. package/src/components/editor/waka-slash-menu.tsx +392 -0
  101. package/src/components/editor/waka-spec-editor.tsx +657 -0
  102. package/src/components/index.ts +1 -18
  103. package/dist/chunk-BDDJmn7V.js +0 -1
  104. package/dist/cn-DnPbmOCy.js +0 -1
  105. package/dist/cn-DpLcAzrf.mjs +0 -22
  106. package/dist/separator-BDReXBvI.mjs +0 -59
  107. package/dist/separator-BKjNl9sI.js +0 -1
  108. package/dist/src/components/waka-actor-badge/index.d.ts +0 -8
  109. package/dist/src/components/waka-actors-list/index.d.ts +0 -18
  110. package/dist/src/components/waka-ai-assistant-button/index.d.ts +0 -8
  111. package/dist/src/components/waka-document-flyover/index.d.ts +0 -10
  112. package/dist/src/components/waka-document-preview-popup/index.d.ts +0 -26
  113. package/dist/src/components/waka-hour-balance-badge/index.d.ts +0 -8
  114. package/dist/src/components/waka-hour-consumption-table/index.d.ts +0 -15
  115. package/dist/src/components/waka-hour-pack-dialog/index.d.ts +0 -8
  116. package/dist/src/components/waka-project-stats-header/index.d.ts +0 -15
  117. package/dist/src/components/waka-step-comment-bubble/index.d.ts +0 -13
  118. package/dist/src/components/waka-step-comment-panel/index.d.ts +0 -20
  119. package/dist/src/components/waka-step-permission-matrix/index.d.ts +0 -12
  120. package/dist/src/components/waka-time-entry-dialog/index.d.ts +0 -16
  121. package/dist/src/components/waka-time-tracking-flyover/index.d.ts +0 -11
  122. package/dist/types-BH9cQRqZ.js +0 -1
  123. package/dist/waka-doc-renderer-BZ2-SqyT.js +0 -3
  124. package/dist/waka-rich-text-editor-BJGlQgpq.js +0 -1
  125. package/dist/waka-rich-text-editor-BJzzxeP1.mjs +0 -361
  126. package/dist/waka-rich-text-editor-wnXLwvUo.js +0 -1
  127. package/src/components/waka-actor-badge/index.tsx +0 -34
  128. package/src/components/waka-actors-list/index.tsx +0 -125
  129. package/src/components/waka-ai-assistant-button/index.tsx +0 -31
  130. package/src/components/waka-document-flyover/index.tsx +0 -36
  131. package/src/components/waka-document-preview-popup/index.tsx +0 -103
  132. package/src/components/waka-hour-balance-badge/index.tsx +0 -43
  133. package/src/components/waka-hour-consumption-table/index.tsx +0 -72
  134. package/src/components/waka-hour-pack-dialog/index.tsx +0 -72
  135. package/src/components/waka-project-stats-header/index.tsx +0 -69
  136. package/src/components/waka-step-comment-bubble/index.tsx +0 -71
  137. package/src/components/waka-step-comment-panel/index.tsx +0 -106
  138. package/src/components/waka-step-permission-matrix/index.tsx +0 -65
  139. package/src/components/waka-time-entry-dialog/index.tsx +0 -131
  140. package/src/components/waka-time-tracking-flyover/index.tsx +0 -41
@@ -0,0 +1,331 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../../utils/cn"
5
+ import type { PlateElementProps } from "../waka-editor-elements"
6
+
7
+ // ============================================================================
8
+ // Types
9
+ // ============================================================================
10
+
11
+ export const CODE_PLAYGROUND_BLOCK_TYPE = "code_playground" as const
12
+
13
+ /** Supported programming languages */
14
+ export type PlaygroundLanguage = "javascript" | "typescript" | "python" | "html" | "css" | "json" | "sql" | "bash" | "go" | "rust"
15
+
16
+ /** Execution status */
17
+ export type ExecutionStatus = "idle" | "running" | "success" | "error"
18
+
19
+ /** Slate node for code playground blocks */
20
+ export interface CodePlaygroundElement {
21
+ type: typeof CODE_PLAYGROUND_BLOCK_TYPE
22
+ /** Source code */
23
+ code: string
24
+ /** Programming language */
25
+ language: PlaygroundLanguage
26
+ /** Title / filename */
27
+ title?: string
28
+ /** Last execution output */
29
+ output?: string
30
+ /** Last execution error */
31
+ errorOutput?: string
32
+ /** Execution status */
33
+ executionStatus: ExecutionStatus
34
+ /** Whether to show line numbers */
35
+ showLineNumbers: boolean
36
+ /** Whether the code is read-only */
37
+ readOnly: boolean
38
+ children: Array<{ text: string }>
39
+ }
40
+
41
+ export interface WakaCodePlaygroundBlockProps extends PlateElementProps {
42
+ element?: CodePlaygroundElement & Record<string, unknown>
43
+ /** Callback to execute code. Returns stdout output or throws with stderr. */
44
+ onExecute?: (code: string, language: PlaygroundLanguage) => Promise<string>
45
+ }
46
+
47
+ // ============================================================================
48
+ // Language Config
49
+ // ============================================================================
50
+
51
+ const LANGUAGE_CONFIG: Record<PlaygroundLanguage, { label: string; color: string; extension: string }> = {
52
+ javascript: { label: "JavaScript", color: "text-yellow-500", extension: ".js" },
53
+ typescript: { label: "TypeScript", color: "text-blue-500", extension: ".ts" },
54
+ python: { label: "Python", color: "text-green-500", extension: ".py" },
55
+ html: { label: "HTML", color: "text-orange-500", extension: ".html" },
56
+ css: { label: "CSS", color: "text-pink-500", extension: ".css" },
57
+ json: { label: "JSON", color: "text-gray-400", extension: ".json" },
58
+ sql: { label: "SQL", color: "text-cyan-500", extension: ".sql" },
59
+ bash: { label: "Bash", color: "text-emerald-500", extension: ".sh" },
60
+ go: { label: "Go", color: "text-cyan-600", extension: ".go" },
61
+ rust: { label: "Rust", color: "text-orange-600", extension: ".rs" },
62
+ }
63
+
64
+ // ============================================================================
65
+ // Simple syntax highlighting (keyword-based)
66
+ // ============================================================================
67
+
68
+ const KEYWORD_PATTERNS: Record<string, RegExp> = {
69
+ keyword: /\b(const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|import|export|from|default|class|extends|new|this|typeof|instanceof|try|catch|finally|throw|async|await|yield|in|of|with|as|is|type|interface|enum|namespace|module|declare|readonly|abstract|implements|package|private|protected|public|static|super|void|null|undefined|true|false|NaN|Infinity|def|print|range|len|self|None|True|False|SELECT|FROM|WHERE|INSERT|UPDATE|DELETE|CREATE|TABLE|INDEX|JOIN|ON|AND|OR|NOT|ORDER|BY|GROUP|HAVING|LIMIT|OFFSET|fn|pub|mod|use|struct|impl|trait|mut|ref|match|loop|break|continue|move|dyn|Box|Vec|String|Option|Result|Some|None|Ok|Err|func|go|chan|defer|fallthrough|select|map|make|append|package|import)\b/g,
70
+ string: /(["'`])(?:(?!\1|\\).|\\.)*?\1/g,
71
+ comment: /\/\/.*$|\/\*[\s\S]*?\*\/|#.*$/gm,
72
+ number: /\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/gi,
73
+ }
74
+
75
+ function highlightCode(code: string): React.ReactNode[] {
76
+ // Simple token-based highlighting (not a full parser)
77
+ // For production, integrate with Prism.js or Shiki
78
+ const lines = code.split("\n")
79
+ return lines.map((line, i) => (
80
+ <div key={i} className="table-row">
81
+ <span className="table-cell w-8 text-right pr-3 text-muted-foreground/40 select-none text-[11px]">
82
+ {i + 1}
83
+ </span>
84
+ <span className="table-cell">
85
+ {line || " "}
86
+ </span>
87
+ </div>
88
+ ))
89
+ }
90
+
91
+ // ============================================================================
92
+ // Element Component
93
+ // ============================================================================
94
+
95
+ /**
96
+ * WakaCodePlaygroundBlock - A Plate.js block with an inline code editor and
97
+ * sandboxed execution. Users write code and can run it, seeing output in
98
+ * an integrated console panel.
99
+ *
100
+ * Execution is sandboxed via the `onExecute` callback provided by the
101
+ * consuming application (e.g. using Web Workers, iframes, or server-side eval).
102
+ *
103
+ * Register in Plate editor:
104
+ * ```ts
105
+ * components: {
106
+ * [CODE_PLAYGROUND_BLOCK_TYPE]: (props) => (
107
+ * <WakaCodePlaygroundBlock {...props} onExecute={myExecutor} />
108
+ * ),
109
+ * }
110
+ * ```
111
+ */
112
+ export function WakaCodePlaygroundBlock({
113
+ attributes,
114
+ children,
115
+ element,
116
+ className,
117
+ onExecute,
118
+ }: WakaCodePlaygroundBlockProps) {
119
+ const el = element as CodePlaygroundElement | undefined
120
+ const code = el?.code || ""
121
+ const language = el?.language || "javascript"
122
+ const langConfig = LANGUAGE_CONFIG[language]
123
+ const output = el?.output || ""
124
+ const errorOutput = el?.errorOutput || ""
125
+ const executionStatus = el?.executionStatus || "idle"
126
+ const title = el?.title || `main${langConfig.extension}`
127
+
128
+ const [showOutput, setShowOutput] = React.useState(!!output || !!errorOutput)
129
+ const [localStatus, setLocalStatus] = React.useState(executionStatus)
130
+
131
+ const handleRun = React.useCallback(async () => {
132
+ if (!onExecute) return
133
+ setLocalStatus("running")
134
+ setShowOutput(true)
135
+ try {
136
+ await onExecute(code, language)
137
+ setLocalStatus("success")
138
+ } catch {
139
+ setLocalStatus("error")
140
+ }
141
+ }, [code, language, onExecute])
142
+
143
+ const displayStatus = localStatus !== executionStatus ? localStatus : executionStatus
144
+
145
+ return (
146
+ <div
147
+ {...attributes}
148
+ contentEditable={false}
149
+ className={cn(
150
+ "my-4 rounded-lg overflow-hidden border border-gray-800 dark:border-gray-700 shadow-lg",
151
+ className
152
+ )}
153
+ >
154
+ {/* Title bar (VS Code-like) */}
155
+ <div className="flex items-center justify-between px-3 py-1.5 bg-gray-900 dark:bg-gray-800 border-b border-gray-800 dark:border-gray-700">
156
+ <div className="flex items-center gap-3">
157
+ {/* Traffic lights */}
158
+ <div className="flex items-center gap-1.5" aria-hidden="true">
159
+ <div className="h-3 w-3 rounded-full bg-red-500/80" />
160
+ <div className="h-3 w-3 rounded-full bg-yellow-500/80" />
161
+ <div className="h-3 w-3 rounded-full bg-green-500/80" />
162
+ </div>
163
+
164
+ {/* File name tab */}
165
+ <div className="flex items-center gap-1.5 px-2 py-0.5 rounded bg-gray-800 dark:bg-gray-700">
166
+ <span className={cn("text-[10px] font-bold", langConfig.color)}>
167
+ {langConfig.label}
168
+ </span>
169
+ <span className="text-xs font-mono text-gray-300">{title}</span>
170
+ </div>
171
+ </div>
172
+
173
+ <div className="flex items-center gap-2">
174
+ {/* Status indicator */}
175
+ {displayStatus !== "idle" && (
176
+ <div className="flex items-center gap-1">
177
+ {displayStatus === "running" && (
178
+ <svg className="h-3 w-3 animate-spin text-amber-400" viewBox="0 0 24 24" fill="none">
179
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
180
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
181
+ </svg>
182
+ )}
183
+ {displayStatus === "success" && (
184
+ <svg className="h-3 w-3 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}>
185
+ <path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
186
+ </svg>
187
+ )}
188
+ {displayStatus === "error" && (
189
+ <svg className="h-3 w-3 text-red-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}>
190
+ <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
191
+ </svg>
192
+ )}
193
+ </div>
194
+ )}
195
+
196
+ {/* Run button */}
197
+ {onExecute && (
198
+ <button
199
+ type="button"
200
+ onClick={handleRun}
201
+ disabled={displayStatus === "running" || !code.trim()}
202
+ className={cn(
203
+ "flex items-center gap-1 px-2.5 py-1 rounded text-[10px] font-semibold transition-all",
204
+ displayStatus === "running"
205
+ ? "bg-amber-500/20 text-amber-300 cursor-wait"
206
+ : "bg-emerald-500/20 text-emerald-300 hover:bg-emerald-500/30",
207
+ !code.trim() && "opacity-40 cursor-not-allowed"
208
+ )}
209
+ aria-label="Run code"
210
+ >
211
+ <svg className="h-3 w-3" viewBox="0 0 24 24" fill="currentColor">
212
+ <path d="M8 5v14l11-7z" />
213
+ </svg>
214
+ {displayStatus === "running" ? "Running..." : "Run"}
215
+ </button>
216
+ )}
217
+
218
+ {/* Toggle output */}
219
+ <button
220
+ type="button"
221
+ onClick={() => setShowOutput(!showOutput)}
222
+ className={cn(
223
+ "px-2 py-1 rounded text-[10px] font-medium transition-colors",
224
+ showOutput
225
+ ? "bg-gray-700 text-gray-200"
226
+ : "text-gray-400 hover:text-gray-200"
227
+ )}
228
+ >
229
+ Console
230
+ </button>
231
+ </div>
232
+ </div>
233
+
234
+ {/* Code area */}
235
+ <div className="bg-gray-950 dark:bg-[#0d1117] overflow-x-auto">
236
+ <pre className="p-4 text-[12px] font-mono leading-relaxed text-gray-100 min-h-[80px]">
237
+ <code className="table w-full">
238
+ {highlightCode(code)}
239
+ </code>
240
+ </pre>
241
+ </div>
242
+
243
+ {/* Output console */}
244
+ {showOutput && (output || errorOutput || displayStatus === "running") && (
245
+ <div className="border-t border-gray-800 dark:border-gray-700">
246
+ <div className="flex items-center justify-between px-3 py-1 bg-gray-900 dark:bg-gray-800">
247
+ <span className="text-[10px] font-semibold uppercase tracking-wider text-gray-400">
248
+ Output
249
+ </span>
250
+ {(output || errorOutput) && (
251
+ <button
252
+ type="button"
253
+ className="text-[10px] text-gray-500 hover:text-gray-300 transition-colors"
254
+ aria-label="Clear output"
255
+ >
256
+ Clear
257
+ </button>
258
+ )}
259
+ </div>
260
+ <div className="bg-gray-950 dark:bg-[#0d1117] p-3 max-h-[200px] overflow-y-auto">
261
+ {displayStatus === "running" ? (
262
+ <div className="flex items-center gap-2 text-amber-400 text-xs font-mono">
263
+ <svg className="h-3 w-3 animate-spin" viewBox="0 0 24 24" fill="none">
264
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
265
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
266
+ </svg>
267
+ Executing...
268
+ </div>
269
+ ) : errorOutput ? (
270
+ <pre className="text-[12px] font-mono text-red-400 whitespace-pre-wrap">{errorOutput}</pre>
271
+ ) : output ? (
272
+ <pre className="text-[12px] font-mono text-gray-200 whitespace-pre-wrap">{output}</pre>
273
+ ) : null}
274
+ </div>
275
+ </div>
276
+ )}
277
+
278
+ {/* Hidden Slate children */}
279
+ <div className="hidden">{children}</div>
280
+ </div>
281
+ )
282
+ }
283
+
284
+ WakaCodePlaygroundBlock.displayName = "WakaCodePlaygroundBlock"
285
+
286
+ // ============================================================================
287
+ // Node Factory
288
+ // ============================================================================
289
+
290
+ export function createCodePlaygroundNodes(options?: {
291
+ code?: string
292
+ language?: PlaygroundLanguage
293
+ title?: string
294
+ }): CodePlaygroundElement[] {
295
+ return [
296
+ {
297
+ type: CODE_PLAYGROUND_BLOCK_TYPE,
298
+ code: options?.code || '// Write your code here\nconsole.log("Hello, WakaStart!");',
299
+ language: options?.language || "javascript",
300
+ title: options?.title,
301
+ output: "",
302
+ errorOutput: "",
303
+ executionStatus: "idle",
304
+ showLineNumbers: true,
305
+ readOnly: false,
306
+ children: [{ text: "" }],
307
+ },
308
+ ]
309
+ }
310
+
311
+ export async function createCodePlaygroundPlugin(
312
+ onExecute?: (code: string, language: PlaygroundLanguage) => Promise<string>
313
+ ) {
314
+ try {
315
+ const { createPlatePlugin } = await import("platejs/react")
316
+ return createPlatePlugin({
317
+ key: CODE_PLAYGROUND_BLOCK_TYPE,
318
+ node: {
319
+ isElement: true,
320
+ isVoid: true,
321
+ type: CODE_PLAYGROUND_BLOCK_TYPE,
322
+ component: (props: WakaCodePlaygroundBlockProps) => (
323
+ <WakaCodePlaygroundBlock {...props} onExecute={onExecute} />
324
+ ),
325
+ },
326
+ })
327
+ } catch {
328
+ console.warn("[WakaCodePlaygroundBlock] platejs not installed")
329
+ return null
330
+ }
331
+ }