@moldable-ai/ui 0.2.1 → 0.2.3
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/dist/components/chat/chat-message.d.ts +4 -0
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +64 -10
- package/dist/components/chat/chat-panel.d.ts +20 -1
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +20 -5
- package/dist/components/chat/index.d.ts +4 -1
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +4 -1
- package/dist/components/chat/tool-approval-context.d.ts +21 -0
- package/dist/components/chat/tool-approval-context.d.ts.map +1 -0
- package/dist/components/chat/tool-approval-context.js +19 -0
- package/dist/components/chat/tool-approval.d.ts +85 -0
- package/dist/components/chat/tool-approval.d.ts.map +1 -0
- package/dist/components/chat/tool-approval.js +80 -0
- package/dist/components/chat/tool-handlers.d.ts +21 -0
- package/dist/components/chat/tool-handlers.d.ts.map +1 -1
- package/dist/components/chat/tool-handlers.js +147 -35
- package/dist/components/chat/tool-progress-context.d.ts +27 -0
- package/dist/components/chat/tool-progress-context.d.ts.map +1 -0
- package/dist/components/chat/tool-progress-context.js +26 -0
- package/dist/components/ui/button.d.ts +3 -2
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +6 -5
- package/dist/components/ui/card.d.ts +7 -8
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +14 -23
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/collapsible.d.ts +3 -3
- package/dist/components/ui/collapsible.d.ts.map +1 -1
- package/dist/components/ui/collapsible.js +3 -11
- package/dist/components/ui/command.d.ts +15 -15
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js +24 -29
- package/dist/components/ui/dialog.d.ts +17 -13
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog.js +19 -32
- package/dist/components/ui/dropdown-menu.js +6 -6
- package/dist/components/ui/input.d.ts +2 -1
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/input.js +5 -4
- package/dist/components/ui/label.d.ts +1 -1
- package/dist/components/ui/label.d.ts.map +1 -1
- package/dist/components/ui/label.js +3 -3
- package/dist/components/ui/scroll-area.d.ts +2 -2
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +7 -9
- package/dist/components/ui/select.d.ts +11 -13
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/select.js +23 -35
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/switch.js +4 -4
- package/dist/components/ui/textarea.d.ts +2 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea.js +5 -4
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/commands.d.ts +37 -0
- package/dist/lib/commands.d.ts.map +1 -1
- package/dist/lib/commands.js +85 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import * as
|
|
3
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
4
|
+
import * as React from 'react';
|
|
4
5
|
import { cn } from '../../lib/utils';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
6
|
+
const Switch = React.forwardRef(({ className, ...props }, ref) => (_jsx(SwitchPrimitives.Root, { className: cn('focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-input peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', className), ...props, ref: ref, children: _jsx(SwitchPrimitives.Thumb, { className: cn('bg-background pointer-events-none block h-4 w-4 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0') }) })));
|
|
7
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
8
8
|
export { Switch };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
2
|
+
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
3
|
+
declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
3
4
|
export { Textarea };
|
|
4
5
|
//# sourceMappingURL=textarea.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/components/ui/textarea.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/components/ui/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAE7E,QAAA,MAAM,QAAQ,2FAab,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
'use client';
|
|
2
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
-
|
|
5
|
-
return (_jsx("textarea", {
|
|
6
|
-
}
|
|
4
|
+
const Textarea = React.forwardRef(({ className, ...props }, ref) => {
|
|
5
|
+
return (_jsx("textarea", { className: cn('border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', className), ref: ref, ...props }));
|
|
6
|
+
});
|
|
7
|
+
Textarea.displayName = 'Textarea';
|
|
7
8
|
export { Textarea };
|
|
@@ -12,6 +12,6 @@ function TooltipTrigger({ ...props }) {
|
|
|
12
12
|
return _jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
13
13
|
}
|
|
14
14
|
function TooltipContent({ className, sideOffset = 0, children, ...props }) {
|
|
15
|
-
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { "data-slot": "tooltip-content", sideOffset: sideOffset, className: cn('
|
|
15
|
+
return (_jsx(TooltipPrimitive.Portal, { children: _jsxs(TooltipPrimitive.Content, { "data-slot": "tooltip-content", sideOffset: sideOffset, className: cn('origin-(--radix-tooltip-content-transform-origin) animate-in bg-foreground text-background fade-in-0 zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 z-50 w-fit text-balance rounded-md px-3 py-1.5 text-xs', className), ...props, children: [children, _jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px]" })] }) }));
|
|
16
16
|
}
|
|
17
17
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { cn } from './lib/utils';
|
|
2
2
|
export { ThemeProvider, useTheme, themeScript, type Theme } from './lib/theme';
|
|
3
3
|
export { WorkspaceProvider, useWorkspace, WORKSPACE_HEADER, } from './lib/workspace';
|
|
4
|
-
export { useMoldableCommands, useMoldableCommand, isInMoldable, sendToMoldable, type AppCommand, type CommandAction, type CommandsResponse, type CommandMessage, } from './lib/commands';
|
|
4
|
+
export { useMoldableCommands, useMoldableCommand, isInMoldable, sendToMoldable, downloadFile, type AppCommand, type CommandAction, type CommandsResponse, type CommandMessage, type DownloadFileOptions, } from './lib/commands';
|
|
5
5
|
export * from './components/ui';
|
|
6
6
|
export { useIsMobile } from './hooks/use-mobile';
|
|
7
7
|
export { Markdown } from './components/markdown';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAGhC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AAG9E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAGhC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AAG9E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAA;AAGvB,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAGzD,cAAc,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { ThemeProvider, useTheme, themeScript } from './lib/theme';
|
|
|
5
5
|
// Export workspace
|
|
6
6
|
export { WorkspaceProvider, useWorkspace, WORKSPACE_HEADER, } from './lib/workspace';
|
|
7
7
|
// Export commands
|
|
8
|
-
export { useMoldableCommands, useMoldableCommand, isInMoldable, sendToMoldable, } from './lib/commands';
|
|
8
|
+
export { useMoldableCommands, useMoldableCommand, isInMoldable, sendToMoldable, downloadFile, } from './lib/commands';
|
|
9
9
|
// Export UI components
|
|
10
10
|
export * from './components/ui';
|
|
11
11
|
// Export hooks
|
package/dist/lib/commands.d.ts
CHANGED
|
@@ -71,4 +71,41 @@ export declare function sendToMoldable(message: {
|
|
|
71
71
|
type: string;
|
|
72
72
|
[key: string]: unknown;
|
|
73
73
|
}): void;
|
|
74
|
+
/**
|
|
75
|
+
* Options for downloading a file
|
|
76
|
+
*/
|
|
77
|
+
export interface DownloadFileOptions {
|
|
78
|
+
/** Suggested filename for the save dialog */
|
|
79
|
+
filename: string;
|
|
80
|
+
/** File content - either a string or base64-encoded data */
|
|
81
|
+
data: string;
|
|
82
|
+
/** MIME type of the file (e.g., 'text/csv', 'application/json') */
|
|
83
|
+
mimeType: string;
|
|
84
|
+
/** If true, data is base64-encoded binary; if false, data is plain text */
|
|
85
|
+
isBase64?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Trigger a file download via Moldable's native save dialog.
|
|
89
|
+
* Works inside Moldable's iframe environment where browser downloads don't work.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* // Export CSV
|
|
94
|
+
* downloadFile({
|
|
95
|
+
* filename: 'data.csv',
|
|
96
|
+
* data: 'name,value\nfoo,1\nbar,2',
|
|
97
|
+
* mimeType: 'text/csv',
|
|
98
|
+
* })
|
|
99
|
+
*
|
|
100
|
+
* // Export JSON
|
|
101
|
+
* downloadFile({
|
|
102
|
+
* filename: 'data.json',
|
|
103
|
+
* data: JSON.stringify({ items: [...] }, null, 2),
|
|
104
|
+
* mimeType: 'application/json',
|
|
105
|
+
* })
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @returns Promise that resolves when the save dialog completes (or rejects on error)
|
|
109
|
+
*/
|
|
110
|
+
export declare function downloadFile(options: DownloadFileOptions): Promise<void>;
|
|
74
111
|
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/lib/commands.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,MAAM,EAAE,aAAa,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,UAAU,EAAE,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,QAwBtD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,QAgBrC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAGtC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,QAMA"}
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/lib/commands.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,MAAM,EAAE,aAAa,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,UAAU,EAAE,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,QAwBtD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,QAgBrC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAGtC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,QAMA;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DxE"}
|
package/dist/lib/commands.js
CHANGED
|
@@ -71,3 +71,88 @@ export function sendToMoldable(message) {
|
|
|
71
71
|
}
|
|
72
72
|
window.parent.postMessage(message, '*');
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Trigger a file download via Moldable's native save dialog.
|
|
76
|
+
* Works inside Moldable's iframe environment where browser downloads don't work.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```tsx
|
|
80
|
+
* // Export CSV
|
|
81
|
+
* downloadFile({
|
|
82
|
+
* filename: 'data.csv',
|
|
83
|
+
* data: 'name,value\nfoo,1\nbar,2',
|
|
84
|
+
* mimeType: 'text/csv',
|
|
85
|
+
* })
|
|
86
|
+
*
|
|
87
|
+
* // Export JSON
|
|
88
|
+
* downloadFile({
|
|
89
|
+
* filename: 'data.json',
|
|
90
|
+
* data: JSON.stringify({ items: [...] }, null, 2),
|
|
91
|
+
* mimeType: 'application/json',
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @returns Promise that resolves when the save dialog completes (or rejects on error)
|
|
96
|
+
*/
|
|
97
|
+
export function downloadFile(options) {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
if (!isInMoldable()) {
|
|
100
|
+
// Fallback for browser: use traditional blob download
|
|
101
|
+
try {
|
|
102
|
+
const blob = options.isBase64
|
|
103
|
+
? new Blob([Uint8Array.from(atob(options.data), (c) => c.charCodeAt(0))], {
|
|
104
|
+
type: options.mimeType,
|
|
105
|
+
})
|
|
106
|
+
: new Blob([options.data], { type: options.mimeType });
|
|
107
|
+
const url = URL.createObjectURL(blob);
|
|
108
|
+
const a = document.createElement('a');
|
|
109
|
+
a.href = url;
|
|
110
|
+
a.download = options.filename;
|
|
111
|
+
document.body.appendChild(a);
|
|
112
|
+
a.click();
|
|
113
|
+
document.body.removeChild(a);
|
|
114
|
+
URL.revokeObjectURL(url);
|
|
115
|
+
resolve();
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
reject(err);
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Generate a unique ID for this download request
|
|
123
|
+
const requestId = `download-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
124
|
+
// Listen for the response
|
|
125
|
+
const handleResponse = (event) => {
|
|
126
|
+
if (event.data?.type !== 'moldable:save-file-result')
|
|
127
|
+
return;
|
|
128
|
+
if (event.data?.requestId !== requestId)
|
|
129
|
+
return;
|
|
130
|
+
window.removeEventListener('message', handleResponse);
|
|
131
|
+
if (event.data.success) {
|
|
132
|
+
resolve();
|
|
133
|
+
}
|
|
134
|
+
else if (event.data.cancelled) {
|
|
135
|
+
// User cancelled - not an error, just resolve
|
|
136
|
+
resolve();
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
reject(new Error(event.data.error || 'Download failed'));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
window.addEventListener('message', handleResponse);
|
|
143
|
+
// Send the download request to Moldable
|
|
144
|
+
sendToMoldable({
|
|
145
|
+
type: 'moldable:save-file',
|
|
146
|
+
requestId,
|
|
147
|
+
filename: options.filename,
|
|
148
|
+
data: options.data,
|
|
149
|
+
mimeType: options.mimeType,
|
|
150
|
+
isBase64: options.isBase64 ?? false,
|
|
151
|
+
});
|
|
152
|
+
// Timeout after 5 minutes (user might take time in save dialog)
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
window.removeEventListener('message', handleResponse);
|
|
155
|
+
reject(new Error('Download timed out'));
|
|
156
|
+
}, 5 * 60 * 1000);
|
|
157
|
+
});
|
|
158
|
+
}
|