@decido/shell 1.0.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 (208) hide show
  1. package/.turbo/turbo-build.log +13 -0
  2. package/package.json +65 -0
  3. package/src/AgentPlayer.tsx +105 -0
  4. package/src/DecidoPlayer.tsx +117 -0
  5. package/src/bridge/BridgeAgent.ts +443 -0
  6. package/src/components/DecidoIcon.tsx +56 -0
  7. package/src/components/JsonTreeEditor.tsx +117 -0
  8. package/src/components/PanelSplitter.tsx +71 -0
  9. package/src/components/PluginErrorBoundary.tsx +69 -0
  10. package/src/components/SafeLiquidUI.tsx +114 -0
  11. package/src/components/TransientLayer.tsx +92 -0
  12. package/src/components/agent/AgentChat.tsx +134 -0
  13. package/src/components/chat-extensions/IntentCatalogPanel.tsx +81 -0
  14. package/src/components/chat-extensions/chatSlashCommands.ts +101 -0
  15. package/src/components/controls/CreatorInputBar.tsx +144 -0
  16. package/src/components/controls/OSToolbar.tsx +90 -0
  17. package/src/components/controls/TimelineTape.tsx +43 -0
  18. package/src/components/debug/ActionTimelineTab.tsx +111 -0
  19. package/src/components/debug/CSSInspectorTab.tsx +436 -0
  20. package/src/components/debug/ExportTab.tsx +192 -0
  21. package/src/components/debug/FlowHealthTab.tsx +86 -0
  22. package/src/components/debug/LogsTab.tsx +110 -0
  23. package/src/components/debug/MorphStackTab.tsx +241 -0
  24. package/src/components/debug/NetworkTab.tsx +173 -0
  25. package/src/components/debug/PerformanceTab.tsx +171 -0
  26. package/src/components/debug/ProfilesTab.tsx +238 -0
  27. package/src/components/debug/ReplayTab.tsx +70 -0
  28. package/src/components/debug/StoresTab.tsx +255 -0
  29. package/src/components/debug/TopologyTab.tsx +59 -0
  30. package/src/components/debug/debugConfig.tsx +66 -0
  31. package/src/components/playground/DebugPanel.tsx +112 -0
  32. package/src/components/playground/HeaderCenterControls.tsx +92 -0
  33. package/src/components/playground/KeyframeListItem.tsx +70 -0
  34. package/src/components/playground/PlaygroundAppSidebar.tsx +171 -0
  35. package/src/components/playground/PlaygroundBottomControls.tsx +132 -0
  36. package/src/components/playground/PlaygroundCanvas.tsx +87 -0
  37. package/src/components/playground/PlaygroundChat.tsx +236 -0
  38. package/src/components/playground/PlaygroundErrorBoundary.tsx +63 -0
  39. package/src/components/playground/PlaygroundFloatingInput.tsx +352 -0
  40. package/src/components/playground/PlaygroundHeader.tsx +222 -0
  41. package/src/components/playground/PlaygroundSidebar.tsx +136 -0
  42. package/src/components/playground/PlaygroundTerminal.tsx +44 -0
  43. package/src/components/playground/SuggestionCards.tsx +29 -0
  44. package/src/components/playground/demos/ClinicaAINode.tsx +221 -0
  45. package/src/components/playground/demos/FinanceAINode.tsx +226 -0
  46. package/src/components/playground/demos/KiaAcademyNode.tsx +250 -0
  47. package/src/components/playground/demos/KiaBotNode.tsx +207 -0
  48. package/src/components/playground/demos/KiaCampaignNode.tsx +191 -0
  49. package/src/components/playground/demos/KiaComplianceNode.tsx +140 -0
  50. package/src/components/playground/demos/KiaCustomerJourneyNode.tsx +220 -0
  51. package/src/components/playground/demos/KiaCyberNode.tsx +203 -0
  52. package/src/components/playground/demos/KiaDashboardNode.tsx +399 -0
  53. package/src/components/playground/demos/KiaEmbudoOverviewNode.tsx +168 -0
  54. package/src/components/playground/demos/KiaExecutiveNode.tsx +169 -0
  55. package/src/components/playground/demos/KiaGamificationNode.tsx +229 -0
  56. package/src/components/playground/demos/KiaIntelligenceHubNode.tsx +165 -0
  57. package/src/components/playground/demos/KiaInventoryNode.tsx +183 -0
  58. package/src/components/playground/demos/KiaLeadScoringNode.tsx +226 -0
  59. package/src/components/playground/demos/KiaLiveSimulationNode.tsx +177 -0
  60. package/src/components/playground/demos/KiaMultiDealerNode.tsx +223 -0
  61. package/src/components/playground/demos/KiaNPSVoiceNode.tsx +214 -0
  62. package/src/components/playground/demos/KiaOmnichannelNode.tsx +162 -0
  63. package/src/components/playground/demos/KiaPBIBudgetNode.tsx +152 -0
  64. package/src/components/playground/demos/KiaPBIConversionNode.tsx +206 -0
  65. package/src/components/playground/demos/KiaPBIFunnelNode.tsx +184 -0
  66. package/src/components/playground/demos/KiaPBIOwnershipNode.tsx +113 -0
  67. package/src/components/playground/demos/KiaPBIPartnerNode.tsx +143 -0
  68. package/src/components/playground/demos/KiaPBIPreciosNode.tsx +120 -0
  69. package/src/components/playground/demos/KiaPBIRuntNode.tsx +205 -0
  70. package/src/components/playground/demos/KiaPartnerScoreNode.tsx +206 -0
  71. package/src/components/playground/demos/KiaPredictiveNode.tsx +226 -0
  72. package/src/components/playground/demos/KiaShowroomNode.tsx +194 -0
  73. package/src/components/playground/demos/KiaStoreNode.tsx +215 -0
  74. package/src/components/playground/demos/KiaSustainabilityNode.tsx +173 -0
  75. package/src/components/playground/demos/KiaUsedVehiclesNode.tsx +163 -0
  76. package/src/components/playground/demos/KiaWorkshopNode.tsx +221 -0
  77. package/src/components/playground/demos/SmartCityNode.tsx +205 -0
  78. package/src/components/playground/demos/kia_campaign_manifest.json +112 -0
  79. package/src/components/playground/input-parts/AIModelSelector.tsx +156 -0
  80. package/src/components/playground/input-parts/InputActions.tsx +80 -0
  81. package/src/components/playground/input-parts/InputToolbar.tsx +245 -0
  82. package/src/components/playground/input-parts/ResourceLibraryPanel.tsx +287 -0
  83. package/src/components/playground/sidebarDsdIO.ts +82 -0
  84. package/src/components/settings/SettingsPanel.tsx +267 -0
  85. package/src/components/shell/AppHeader.tsx +9 -0
  86. package/src/components/shell/AppShell.tsx +139 -0
  87. package/src/components/shell/ArtifactBar.tsx +97 -0
  88. package/src/components/shell/BootScreen.tsx +19 -0
  89. package/src/components/shell/CenterComposite.tsx +87 -0
  90. package/src/components/shell/CodeEditorPanel.tsx +88 -0
  91. package/src/components/shell/GlobalOverlays.tsx +228 -0
  92. package/src/components/shell/LayoutConfigurator.tsx +209 -0
  93. package/src/components/shell/LayoutGrid.tsx +178 -0
  94. package/src/components/shell/MorphShell.tsx +368 -0
  95. package/src/components/shell/PluginViewer.tsx +147 -0
  96. package/src/components/shell/ShellNexusPreview.tsx +458 -0
  97. package/src/components/shell/SlotRenderer.tsx +115 -0
  98. package/src/components/shell/TabBar.tsx +94 -0
  99. package/src/components/shell/TemplateLibrary.tsx +195 -0
  100. package/src/components/shell/layoutConstants.ts +35 -0
  101. package/src/components/shell/morphStageMeta.ts +15 -0
  102. package/src/components/shell/shells/BuiltInShells.tsx +443 -0
  103. package/src/components/shell/shells/DatawayChatShell.tsx +42 -0
  104. package/src/components/shell/shells/TokenPreview.tsx +339 -0
  105. package/src/components/shell/shells/bootShells.ts +31 -0
  106. package/src/components/shells/CreatorShell.tsx +37 -0
  107. package/src/components/shells/DecidoShell.tsx +447 -0
  108. package/src/components/shells/ExperimentalChatShell.tsx +245 -0
  109. package/src/components/shells/UserCanvas.tsx +44 -0
  110. package/src/components/studio/BlueprintManagerPanel.tsx +137 -0
  111. package/src/components/studio/DependencyTreePanel.tsx +192 -0
  112. package/src/components/studio/NodePalette.tsx +92 -0
  113. package/src/components/studio/NodePropertiesPanel.tsx +81 -0
  114. package/src/components/studio/ReactFlowEditor.tsx +242 -0
  115. package/src/components/studio/TimelineEditor.tsx +122 -0
  116. package/src/components/studio/TimelineKeyframeCard.tsx +99 -0
  117. package/src/components/studio/VariablePanel.tsx +181 -0
  118. package/src/components/studio/blueprint/BlueprintCard.tsx +82 -0
  119. package/src/components/studio/editor/CanvasContextMenu.tsx +107 -0
  120. package/src/components/studio/editor/EditorToolbar.tsx +80 -0
  121. package/src/components/studio/editor/StageContentRenderer.tsx +134 -0
  122. package/src/components/studio/editor/TrackPropertyEditors.tsx +133 -0
  123. package/src/components/studio/editor/TreeNodeItem.tsx +91 -0
  124. package/src/components/studio/editor/edgeStyles.ts +43 -0
  125. package/src/components/studio/editor/editorKeyHandler.ts +95 -0
  126. package/src/components/studio/editor/nodeTypeRegistry.ts +137 -0
  127. package/src/components/studio/editor/paletteCatalog.tsx +84 -0
  128. package/src/components/studio/nodes/shell/InteractionNodes.tsx +82 -0
  129. package/src/components/studio/nodes/shell/LayoutControlNodes.tsx +69 -0
  130. package/src/components/studio/nodes/shell/RegisterActionNode.tsx +20 -0
  131. package/src/components/studio/nodes/shell/RegisterButtonNode.tsx +22 -0
  132. package/src/components/studio/nodes/shell/RegisterPanelNode.tsx +19 -0
  133. package/src/components/studio/nodes/shell/RegisterSidebarNode.tsx +19 -0
  134. package/src/components/studio/nodes/shell/RegisterStatusBarNode.tsx +22 -0
  135. package/src/components/studio/nodes/shell/RegisterTabNode.tsx +21 -0
  136. package/src/components/studio/nodes/shell/RegisterTopBarNode.tsx +22 -0
  137. package/src/components/studio/nodes/shell/ShellConfigNode.tsx +51 -0
  138. package/src/components/studio/nodes/shell/ShellNodeBase.tsx +100 -0
  139. package/src/components/studio/nodes/shell/ThemeNodes.tsx +51 -0
  140. package/src/components/studio/nodes/shell/index.ts +12 -0
  141. package/src/components/widgets/BroadcastWidget.tsx +93 -0
  142. package/src/components/widgets/MarketplaceWidget.tsx +298 -0
  143. package/src/components/widgets/McpToolsWidget.tsx +231 -0
  144. package/src/components/widgets/OpsDashboard.tsx +59 -0
  145. package/src/components/widgets/QuickActionsWidget.tsx +60 -0
  146. package/src/components/widgets/UsageWidget.tsx +112 -0
  147. package/src/components/widgets/WidgetRenderer.tsx +892 -0
  148. package/src/components/widgets/WidgetSlotPanel.tsx +213 -0
  149. package/src/config/IconRegistry.ts +126 -0
  150. package/src/contexts/NetworkProvider.tsx +162 -0
  151. package/src/core/AIDirector.ts +71 -0
  152. package/src/core/EventBus.ts +37 -0
  153. package/src/core/PluginContext.tsx +141 -0
  154. package/src/hooks/listeners/useUIStateListener.ts +59 -0
  155. package/src/hooks/listeners/useWhatsAppListener.ts +110 -0
  156. package/src/hooks/morphBridge.ts +82 -0
  157. package/src/hooks/useAIModelSelector.ts +144 -0
  158. package/src/hooks/useAgentStream.ts +220 -0
  159. package/src/hooks/useAutoUpdater.ts +89 -0
  160. package/src/hooks/useBootSequence.ts +20 -0
  161. package/src/hooks/useExportDSD.ts +53 -0
  162. package/src/hooks/useFullscreen.ts +35 -0
  163. package/src/hooks/useGeminiStream.ts +282 -0
  164. package/src/hooks/useIntentLens.ts +224 -0
  165. package/src/hooks/useKeyboardShortcuts.ts +69 -0
  166. package/src/hooks/useLoggerBridge.ts +32 -0
  167. package/src/hooks/useMcpClient.ts +112 -0
  168. package/src/hooks/useNexusaiDeploy.ts +118 -0
  169. package/src/hooks/usePlaybackEngine.ts +21 -0
  170. package/src/hooks/usePlaygroundCommander.ts +475 -0
  171. package/src/hooks/usePluginEngine.ts +165 -0
  172. package/src/hooks/useScreenRecorder.ts +73 -0
  173. package/src/hooks/useShellKeyboard.ts +40 -0
  174. package/src/hooks/useShellShortcuts.ts +118 -0
  175. package/src/hooks/useSoundEffects.ts +35 -0
  176. package/src/hooks/useStudioConfig.ts +72 -0
  177. package/src/hooks/useSystemBoot.ts +84 -0
  178. package/src/hooks/useSystemTelemetry.ts +62 -0
  179. package/src/index.ts +97 -0
  180. package/src/lib/debugLogger.ts +80 -0
  181. package/src/lib/networkInterceptor.ts +100 -0
  182. package/src/mocks/decido.tsx +41 -0
  183. package/src/plugins/pluginAPI.ts +190 -0
  184. package/src/store/McpStore.ts +69 -0
  185. package/src/store/UpdaterStore.ts +60 -0
  186. package/src/store/engine.ts +392 -0
  187. package/src/store/index.ts +4 -0
  188. package/src/store/layoutPresets.ts +66 -0
  189. package/src/store/playgroundTypes.ts +98 -0
  190. package/src/store/useActionTimelineStore.ts +48 -0
  191. package/src/store/useDebugPanelStore.ts +98 -0
  192. package/src/store/useDebugProfileStore.ts +130 -0
  193. package/src/store/useLayoutStore.ts +205 -0
  194. package/src/store/useMorphInstanceStore.ts +289 -0
  195. package/src/store/useMorphologyStore.ts +103 -0
  196. package/src/store/usePlaygroundStore.ts +236 -0
  197. package/src/store/useShellRegistry.ts +123 -0
  198. package/src/store/useSuggestionsStore.ts +57 -0
  199. package/src/store/useThemeStore.ts +399 -0
  200. package/src/store/useUIComponentStore.ts +179 -0
  201. package/src/types/DecidoStoryDefinition.ts +43 -0
  202. package/src/utils/ai/ai-architect.ts +92 -0
  203. package/src/utils/ai/ai-code.ts +187 -0
  204. package/src/utils/ai/ai-core.ts +50 -0
  205. package/src/utils/ai/ai-media.ts +292 -0
  206. package/src/utils/layoutGraph.ts +67 -0
  207. package/tsconfig.json +17 -0
  208. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,112 @@
1
+ import { useEffect } from 'react';
2
+ import { useEngineStore } from '@decido/engine';
3
+ import { usePlaygroundStore } from '../store/usePlaygroundStore';
4
+ import { useNetwork, useNetworkEvent } from '../contexts/NetworkProvider';
5
+
6
+ export const useMcpClient = () => {
7
+ const { isConnected, isNativeOS, emitEvent } = useNetwork();
8
+ const lastEvent = useEngineStore((state: any) => state.lastEvent);
9
+ const addLog = usePlaygroundStore((state: any) => state.addLog);
10
+
11
+ // 1. Escuchar peticiones del Motor Interno para enviarlas a la red Real / Rust
12
+ useEffect(() => {
13
+ if (lastEvent?.type === 'MCP_EXECUTION_REQUESTED') {
14
+ const { intent, tool, context, parameters } = lastEvent.payload || {};
15
+ const targetNodeId = lastEvent.targetNodeId;
16
+ const command = intent || tool;
17
+
18
+ // Si estamos en Tauri (isNativeOS) O conectados por WebSocket
19
+ if (isNativeOS || isConnected) {
20
+ addLog(`🦀 [OS Kernel] Solicitando ejecución nativa: ${command}`, 'system');
21
+
22
+ // 🚀 RUTA NUEVA HTTP AL DAEMON (Bypass de WebSockets/IPC para herramientas nativas)
23
+ fetch('http://localhost:3101/api/explorer/execute_tool', {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' },
26
+ body: JSON.stringify({
27
+ tool_name: command,
28
+ args: context || parameters
29
+ })
30
+ })
31
+ .then(res => res.json())
32
+ .then(data => {
33
+ if (data.success || data.result) {
34
+ addLog(`✅ [Daemon REST] Herramienta completada: ${command}`, 'success');
35
+ useEngineStore.getState().dispatchEvent({
36
+ type: 'NODE_COMPLETED',
37
+ targetNodeId: targetNodeId,
38
+ routeHandle: 'success',
39
+ variables: {
40
+ result: data.result,
41
+ ...data
42
+ }
43
+ });
44
+ } else {
45
+ throw new Error(data.error || 'Server error');
46
+ }
47
+ })
48
+ .catch(err => {
49
+ addLog(`❌ [Daemon REST] Error en la herramienta ${command}: ${err.message}`, 'error');
50
+
51
+ // Fallback para herramientas simuladas si falla el daemon
52
+ useEngineStore.getState().dispatchEvent({
53
+ type: 'NODE_COMPLETED',
54
+ targetNodeId: targetNodeId,
55
+ routeHandle: 'error',
56
+ variables: {
57
+ error: err.message,
58
+ mcp_error: err.message
59
+ }
60
+ });
61
+ });
62
+ return;
63
+ } else {
64
+ // MOCK (Isolation Mode) para cuando el Dev prueba en navegador sin backend
65
+ addLog(`[Local Mock] Simulando callback resolutivo para: ${command}`, 'system');
66
+ const timer = setTimeout(() => {
67
+ useEngineStore.getState().dispatchEvent({
68
+ type: 'NODE_COMPLETED',
69
+ targetNodeId: targetNodeId,
70
+ routeHandle: 'success',
71
+ variables: {
72
+ mockValue: Math.floor(Math.random() * 100),
73
+ mocked_intent: command
74
+ }
75
+ });
76
+ }, 1500);
77
+ return () => clearTimeout(timer);
78
+ }
79
+ }
80
+ },[lastEvent, isConnected, isNativeOS, emitEvent, addLog]);
81
+
82
+ // 2. Escuchar respuestas del Kernel en Rust y devolverlas al Motor TypeScript
83
+ useNetworkEvent('mcp:response', (payload: any) => {
84
+ const { targetNodeId, status, data, error } = payload;
85
+
86
+ if (!targetNodeId) {
87
+ addLog(`⚠️ [OS Kernel] Respuesta huérfana (sin targetNodeId): ${status}`, 'error');
88
+ return;
89
+ }
90
+
91
+ addLog(`✅ [OS Kernel] Respuesta recibida para nodo ${targetNodeId}: ${status}`, status === 'success' ? 'success' : 'error');
92
+
93
+ // Determinar la rama lógica para que el grafo avance
94
+ const routeHandle = status === 'success' ? 'success' : 'error';
95
+
96
+ useEngineStore.getState().dispatchEvent({
97
+ type: 'NODE_COMPLETED',
98
+ targetNodeId: targetNodeId,
99
+ routeHandle: routeHandle,
100
+ variables: {
101
+ ...data,
102
+ mcp_error: error
103
+ }
104
+ });
105
+ });
106
+ };
107
+
108
+ // Componente utilitario para montar el cliente invisiblemente en el árbol de React
109
+ export const McpLifecycleManager = () => {
110
+ useMcpClient();
111
+ return null;
112
+ };
@@ -0,0 +1,118 @@
1
+ /**
2
+ * useNexusaiDeploy — Hook for deploying web previews.
3
+ *
4
+ * Dual strategy:
5
+ * 1. If NexusAI API key is configured → deploy via SDK (real URL)
6
+ * 2. Fallback → generate a local Blob URL for immediate preview/sharing
7
+ */
8
+ import { useState, useCallback } from 'react';
9
+ import { useMorphInstanceStore } from '../store/useMorphInstanceStore';
10
+
11
+ export interface DeployState {
12
+ status: 'idle' | 'deploying' | 'success' | 'error';
13
+ url: string | null;
14
+ error: string | null;
15
+ progress: number;
16
+ }
17
+
18
+ function buildStandaloneHTML(html: string, css: string, js: string): string {
19
+ return `<!DOCTYPE html>
20
+ <html lang="es">
21
+ <head>
22
+ <meta charset="UTF-8">
23
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
24
+ <title>Decido Preview</title>
25
+ <script src="https://cdn.tailwindcss.com"><\/script>
26
+ <style>
27
+ *, *::before, *::after { box-sizing: border-box; }
28
+ body {
29
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
30
+ margin: 0;
31
+ background: #fff;
32
+ min-height: 100vh;
33
+ }
34
+ ${css}
35
+ </style>
36
+ </head>
37
+ <body>
38
+ ${html}
39
+ <script>try { ${js} } catch(e) { console.error(e); }<\/script>
40
+ </body>
41
+ </html>`;
42
+ }
43
+
44
+ export function useNexusaiDeploy() {
45
+ const [state, setState] = useState<DeployState>({
46
+ status: 'idle',
47
+ url: null,
48
+ error: null,
49
+ progress: 0,
50
+ });
51
+
52
+ const deploy = useCallback(async () => {
53
+ const activeInst = useMorphInstanceStore.getState().getActiveInstance();
54
+ if (!activeInst?.data?.html) {
55
+ setState({ status: 'error', url: null, error: 'No hay contenido para desplegar', progress: 0 });
56
+ return;
57
+ }
58
+
59
+ const { html, css, javascript } = activeInst.data;
60
+ setState({ status: 'deploying', url: null, error: null, progress: 10 });
61
+
62
+ const nexusKey = localStorage.getItem('nexusai_api_key');
63
+
64
+ if (nexusKey) {
65
+ // Strategy 1: Deploy via NexusAI SDK
66
+ try {
67
+ setState(s => ({ ...s, progress: 30 }));
68
+
69
+ // Dynamic import via variable — prevents Rollup/Vite from resolving at build time
70
+ const sdkModule = '@nexusai' + '/sdk';
71
+ const { NexusAI } = await import(/* @vite-ignore */ sdkModule);
72
+ const client = new NexusAI({ apiKey: nexusKey });
73
+
74
+ const standaloneCode = buildStandaloneHTML(html, css || '', javascript || '');
75
+ const { jobId } = await client.pipeline.deploy({
76
+ componentName: `preview-${Date.now()}`,
77
+ componentCode: standaloneCode,
78
+ });
79
+
80
+ setState(s => ({ ...s, progress: 60 }));
81
+
82
+ const result = await client.pipeline.waitForDeploy(jobId, {
83
+ timeoutMs: 60_000,
84
+ onProgress: (s: any) => setState(prev => ({ ...prev, progress: 60 + Math.round((s.progress || 0) * 0.4) })),
85
+ });
86
+
87
+ const deployUrl = result.result?.deploymentUrl || result.result?.url || '';
88
+ setState({ status: 'success', url: deployUrl, error: null, progress: 100 });
89
+ } catch (err: any) {
90
+ // Fallback to local blob on SDK error
91
+ const standaloneCode = buildStandaloneHTML(html, css || '', javascript || '');
92
+ const blob = new Blob([standaloneCode], { type: 'text/html' });
93
+ const blobUrl = URL.createObjectURL(blob);
94
+ setState({ status: 'success', url: blobUrl, error: `SDK falló (${err.message}). Preview local generado.`, progress: 100 });
95
+ }
96
+ } else {
97
+ // Strategy 2: Local Blob URL (immediate, no server needed)
98
+ await new Promise(r => setTimeout(r, 500)); // Simulate brief deploy
99
+ setState(s => ({ ...s, progress: 50 }));
100
+
101
+ const standaloneCode = buildStandaloneHTML(html, css || '', javascript || '');
102
+ const blob = new Blob([standaloneCode], { type: 'text/html' });
103
+ const blobUrl = URL.createObjectURL(blob);
104
+
105
+ setState({ status: 'success', url: blobUrl, error: null, progress: 100 });
106
+ }
107
+ }, []);
108
+
109
+ const reset = useCallback(() => {
110
+ setState({ status: 'idle', url: null, error: null, progress: 0 });
111
+ }, []);
112
+
113
+ const copyUrl = useCallback(() => {
114
+ if (state.url) navigator.clipboard.writeText(state.url);
115
+ }, [state.url]);
116
+
117
+ return { ...state, deploy, reset, copyUrl };
118
+ }
@@ -0,0 +1,21 @@
1
+ import { useMemo } from 'react';
2
+ import { usePlaybackSimulator, SimulationTape } from '@decido/engine';
3
+
4
+ /**
5
+ * usePlaybackEngine — Wraps the mock tape + playback simulator.
6
+ *
7
+ * Provides: currentTime, isPlaying, setIsPlaying, playbackSpeed,
8
+ * setPlaybackSpeed, seekTime, resetSimulation.
9
+ *
10
+ * @param prototypeBrand - Current brand key for tape ID
11
+ */
12
+ export function usePlaybackEngine(prototypeBrand: string) {
13
+ const mockTape: SimulationTape = useMemo(() => ({
14
+ id: `tape-${prototypeBrand}`,
15
+ events: [
16
+ { t: 0.1, event: { type: 'SYSTEM_START' }, description: 'Arranque Automático' }
17
+ ]
18
+ }), [prototypeBrand]);
19
+
20
+ return usePlaybackSimulator(mockTape);
21
+ }