@moldable-ai/ui 0.2.6 → 0.2.8
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/LICENSE +75 -71
- package/dist/components/chat/chat-input.d.ts +16 -3
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/chat-input.js +25 -8
- package/dist/components/chat/chat-message.d.ts +11 -0
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +503 -158
- package/dist/components/chat/chat-panel.d.ts +26 -2
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +69 -33
- package/dist/components/chat/conversation-history.d.ts +6 -1
- package/dist/components/chat/conversation-history.d.ts.map +1 -1
- package/dist/components/chat/conversation-history.js +6 -6
- package/dist/components/chat/index.d.ts +2 -2
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/model-selector.d.ts +3 -1
- package/dist/components/chat/model-selector.d.ts.map +1 -1
- package/dist/components/chat/model-selector.js +2 -2
- package/dist/components/chat/reasoning-effort-selector.d.ts +4 -1
- package/dist/components/chat/reasoning-effort-selector.d.ts.map +1 -1
- package/dist/components/chat/reasoning-effort-selector.js +6 -6
- package/dist/components/chat/tool-handlers.d.ts.map +1 -1
- package/dist/components/chat/tool-handlers.js +62 -6
- package/dist/components/markdown.js +2 -2
- package/dist/components/ui/command.d.ts +2 -1
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js +2 -2
- package/dist/components/ui/scroll-area.d.ts +1 -1
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +5 -3
- 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 +57 -0
- package/dist/lib/commands.d.ts.map +1 -1
- package/dist/lib/commands.js +74 -0
- package/package.json +2 -2
- package/src/styles/index.css +1 -1
|
@@ -142,9 +142,9 @@ const components = {
|
|
|
142
142
|
return _jsx(CodeBlock, { code: codeContent, language: language });
|
|
143
143
|
}
|
|
144
144
|
// Inline code - style nicely, remove prose backticks via before:/after:content-none
|
|
145
|
-
return (_jsx("code", { className: "bg-muted text-foreground rounded
|
|
145
|
+
return (_jsx("code", { className: "bg-muted/70 text-foreground rounded px-1 py-0.5 font-mono text-[0.92em] before:content-none after:content-none", ...props, children: children }));
|
|
146
146
|
},
|
|
147
|
-
a: ({ children, href, ...props }) => (_jsx("a", { className: "text-primary break-all font-
|
|
147
|
+
a: ({ children, href, ...props }) => (_jsx("a", { className: "text-primary break-all font-medium hover:underline", href: href ?? '#', target: "_blank", rel: "noreferrer", ...props, children: children })),
|
|
148
148
|
// Process @mentions in text and paragraph nodes
|
|
149
149
|
p: ({ children, ...props }) => {
|
|
150
150
|
const processedChildren = React.Children.map(children, (child) => {
|
|
@@ -2,11 +2,12 @@ import * as React from 'react';
|
|
|
2
2
|
import { Dialog } from './dialog';
|
|
3
3
|
import { Command as CommandPrimitive } from 'cmdk';
|
|
4
4
|
declare function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
-
declare function CommandDialog({ title, description, children, className, showCloseButton, ...props }: React.ComponentProps<typeof Dialog> & {
|
|
5
|
+
declare function CommandDialog({ title, description, children, className, showCloseButton, filter, ...props }: React.ComponentProps<typeof Dialog> & {
|
|
6
6
|
title?: string;
|
|
7
7
|
description?: string;
|
|
8
8
|
className?: string;
|
|
9
9
|
showCloseButton?: boolean;
|
|
10
|
+
filter?: React.ComponentProps<typeof CommandPrimitive>['filter'];
|
|
10
11
|
}): import("react/jsx-runtime").JSX.Element;
|
|
11
12
|
declare function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>): import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
declare function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/components/ui/command.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,MAAM,EAKP,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAElD,iBAAS,OAAO,CAAC,EACf,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,2CAW/C;AAED,iBAAS,aAAa,CAAC,EACrB,KAAyB,EACzB,WAA8C,EAC9C,QAAQ,EACR,SAAS,EACT,eAAsB,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/components/ui/command.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,MAAM,EAKP,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAElD,iBAAS,OAAO,CAAC,EACf,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,2CAW/C;AAED,iBAAS,aAAa,CAAC,EACrB,KAAyB,EACzB,WAA8C,EAC9C,QAAQ,EACR,SAAS,EACT,eAAsB,EACtB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAA;CACjE,2CAoBA;AAED,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,KAAK,CAAC,2CAiBrD;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,2CAWpD;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,KAAK,CAAC,2CAQrD;AAED,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,KAAK,CAAC,2CAWrD;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,2CAQzD;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,2CAWpD;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,2CAW9B;AAED,OAAO,EACL,OAAO,EACP,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,CAAA"}
|
|
@@ -7,8 +7,8 @@ import { Command as CommandPrimitive } from 'cmdk';
|
|
|
7
7
|
function Command({ className, ...props }) {
|
|
8
8
|
return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md', className), ...props }));
|
|
9
9
|
}
|
|
10
|
-
function CommandDialog({ title = 'Command Palette', description = 'Search for a command to run...', children, className, showCloseButton = true, ...props }) {
|
|
11
|
-
return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: description })] }), _jsx(DialogContent, { className: cn('overflow-hidden p-0', className), showCloseButton: showCloseButton, children: _jsx(Command, { className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children: children }) })] }));
|
|
10
|
+
function CommandDialog({ title = 'Command Palette', description = 'Search for a command to run...', children, className, showCloseButton = true, filter, ...props }) {
|
|
11
|
+
return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: description })] }), _jsx(DialogContent, { className: cn('overflow-hidden p-0', className), showCloseButton: showCloseButton, children: _jsx(Command, { filter: filter, className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children: children }) })] }));
|
|
12
12
|
}
|
|
13
13
|
function CommandInput({ className, ...props }) {
|
|
14
14
|
return (_jsxs("div", { "data-slot": "command-input-wrapper", className: "flex h-9 items-center gap-2 border-b px-3", children: [_jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }), _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('placeholder:text-muted-foreground outline-hidden flex h-10 w-full rounded-md bg-transparent py-3 text-sm disabled:cursor-not-allowed disabled:opacity-50', className), ...props })] }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
declare
|
|
3
|
+
declare const ScrollArea: React.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
4
4
|
declare function ScrollBar({ className, orientation, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export { ScrollArea, ScrollBar };
|
|
6
6
|
//# sourceMappingURL=scroll-area.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../../src/components/ui/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,
|
|
1
|
+
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../../src/components/ui/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,mBAAmB,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,QAAA,MAAM,UAAU,+JAqBd,CAAA;AAGF,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,2CAqBtE;AAED,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
4
|
+
import * as React from 'react';
|
|
4
5
|
import { cn } from '../../lib/utils';
|
|
5
|
-
|
|
6
|
-
return (_jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn('relative', className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { "data-slot": "scroll-area-viewport", className: "focus-visible:ring-ring/50 size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px]", children: children }), _jsx(ScrollBar, {}), _jsx(ScrollAreaPrimitive.Corner, {})] }));
|
|
7
|
-
}
|
|
6
|
+
const ScrollArea = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
7
|
+
return (_jsxs(ScrollAreaPrimitive.Root, { ref: ref, "data-slot": "scroll-area", className: cn('relative', className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { "data-slot": "scroll-area-viewport", className: "focus-visible:ring-ring/50 size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px]", children: children }), _jsx(ScrollBar, {}), _jsx(ScrollAreaPrimitive.Corner, {})] }));
|
|
8
|
+
});
|
|
9
|
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
8
10
|
function ScrollBar({ className, orientation = 'vertical', ...props }) {
|
|
9
11
|
return (_jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, { "data-slot": "scroll-area-scrollbar", orientation: orientation, className: cn('flex touch-none select-none p-px transition-colors', orientation === 'vertical' &&
|
|
10
12
|
'h-full w-2.5 border-l border-l-transparent', orientation === 'horizontal' &&
|
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, downloadFile, type AppCommand, type CommandAction, type CommandsResponse, type CommandMessage, type DownloadFileOptions, } from './lib/commands';
|
|
4
|
+
export { useMoldableCommands, useMoldableCommand, useMoldableAppCommands, 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,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"}
|
|
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,sBAAsB,EACtB,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, downloadFile, } from './lib/commands';
|
|
8
|
+
export { useMoldableCommands, useMoldableCommand, useMoldableAppCommands, 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
|
@@ -7,10 +7,22 @@ export type CommandAction = {
|
|
|
7
7
|
} | {
|
|
8
8
|
type: 'message';
|
|
9
9
|
payload: unknown;
|
|
10
|
+
command?: string;
|
|
10
11
|
} | {
|
|
11
12
|
type: 'focus';
|
|
12
13
|
target: string;
|
|
13
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Optional visual marker apps can attach to command labels.
|
|
17
|
+
*/
|
|
18
|
+
export interface AppCommandIndicator {
|
|
19
|
+
/** Shape to render. Defaults to a small dot. */
|
|
20
|
+
type?: 'dot';
|
|
21
|
+
/** Accessible label and hover title for the indicator. */
|
|
22
|
+
label: string;
|
|
23
|
+
/** CSS color value for the indicator. Defaults to the desktop primary color. */
|
|
24
|
+
color?: string;
|
|
25
|
+
}
|
|
14
26
|
/**
|
|
15
27
|
* Command definition that apps expose via /_moldable/commands
|
|
16
28
|
*/
|
|
@@ -21,8 +33,12 @@ export interface AppCommand {
|
|
|
21
33
|
label: string;
|
|
22
34
|
/** Optional keyboard shortcut (single key, shown as hint) */
|
|
23
35
|
shortcut?: string;
|
|
36
|
+
/** Optional supporting text shown below the label */
|
|
37
|
+
description?: string;
|
|
24
38
|
/** Optional icon (emoji or lucide icon name) */
|
|
25
39
|
icon?: string;
|
|
40
|
+
/** Optional app-defined visual marker shown next to the command label */
|
|
41
|
+
indicator?: AppCommandIndicator;
|
|
26
42
|
/** Optional group/category for organizing commands */
|
|
27
43
|
group?: string;
|
|
28
44
|
/** What happens when the command is executed */
|
|
@@ -54,6 +70,14 @@ export interface CommandMessage {
|
|
|
54
70
|
* ```
|
|
55
71
|
*/
|
|
56
72
|
export declare function useMoldableCommands(handlers: Record<string, (payload?: unknown) => void>): void;
|
|
73
|
+
/**
|
|
74
|
+
* Publish the commands that make sense for the app's current view.
|
|
75
|
+
*
|
|
76
|
+
* Apps should call this with a stable, memoized command list. The desktop
|
|
77
|
+
* command menu will prefer these commands over the app's static
|
|
78
|
+
* /api/moldable/commands response while the app is running.
|
|
79
|
+
*/
|
|
80
|
+
export declare function useMoldableAppCommands(appId: string, commands: AppCommand[]): void;
|
|
57
81
|
/**
|
|
58
82
|
* Hook to register a single command handler
|
|
59
83
|
* Useful when you want to register handlers in different components
|
|
@@ -84,6 +108,39 @@ export interface DownloadFileOptions {
|
|
|
84
108
|
/** If true, data is base64-encoded binary; if false, data is plain text */
|
|
85
109
|
isBase64?: boolean;
|
|
86
110
|
}
|
|
111
|
+
export interface MoldableAppCallOptions {
|
|
112
|
+
scopes?: string[];
|
|
113
|
+
timeoutMs?: number;
|
|
114
|
+
requestAccess?: boolean;
|
|
115
|
+
}
|
|
116
|
+
export interface MoldableAppCallMessage {
|
|
117
|
+
type: 'moldable:app-call';
|
|
118
|
+
requestId: string;
|
|
119
|
+
targetAppId: string;
|
|
120
|
+
method: string;
|
|
121
|
+
params?: unknown;
|
|
122
|
+
scopes?: string[];
|
|
123
|
+
requestAccess?: boolean;
|
|
124
|
+
}
|
|
125
|
+
export interface MoldableAppCallResultMessage<T = unknown> {
|
|
126
|
+
type: 'moldable:app-call-result';
|
|
127
|
+
requestId: string;
|
|
128
|
+
ok: boolean;
|
|
129
|
+
result?: T;
|
|
130
|
+
error?: {
|
|
131
|
+
code?: string;
|
|
132
|
+
message?: string;
|
|
133
|
+
detail?: unknown;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Call another Moldable app through the desktop broker.
|
|
138
|
+
*
|
|
139
|
+
* The target app owns its data and provider auth. The desktop broker handles
|
|
140
|
+
* workspace-scoped access grants and forwards the request to the target app's
|
|
141
|
+
* private /api/moldable/rpc endpoint.
|
|
142
|
+
*/
|
|
143
|
+
export declare function callMoldableApp<T = unknown>(targetAppId: string, method: string, params?: unknown, options?: MoldableAppCallOptions): Promise<T>;
|
|
87
144
|
/**
|
|
88
145
|
* Trigger a file download via Moldable's native save dialog.
|
|
89
146
|
* Works inside Moldable's iframe environment where browser downloads don't work.
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/lib/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/commands.js
CHANGED
|
@@ -33,6 +33,24 @@ export function useMoldableCommands(handlers) {
|
|
|
33
33
|
return () => window.removeEventListener('message', handleMessage);
|
|
34
34
|
}, []);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Publish the commands that make sense for the app's current view.
|
|
38
|
+
*
|
|
39
|
+
* Apps should call this with a stable, memoized command list. The desktop
|
|
40
|
+
* command menu will prefer these commands over the app's static
|
|
41
|
+
* /api/moldable/commands response while the app is running.
|
|
42
|
+
*/
|
|
43
|
+
export function useMoldableAppCommands(appId, commands) {
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!isInMoldable())
|
|
46
|
+
return;
|
|
47
|
+
window.parent.postMessage({
|
|
48
|
+
type: 'moldable:set-app-commands',
|
|
49
|
+
appId,
|
|
50
|
+
commands,
|
|
51
|
+
}, '*');
|
|
52
|
+
}, [appId, commands]);
|
|
53
|
+
}
|
|
36
54
|
/**
|
|
37
55
|
* Hook to register a single command handler
|
|
38
56
|
* Useful when you want to register handlers in different components
|
|
@@ -71,6 +89,62 @@ export function sendToMoldable(message) {
|
|
|
71
89
|
}
|
|
72
90
|
window.parent.postMessage(message, '*');
|
|
73
91
|
}
|
|
92
|
+
function makeRequestId(prefix) {
|
|
93
|
+
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
|
|
94
|
+
return `${prefix}-${crypto.randomUUID()}`;
|
|
95
|
+
}
|
|
96
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Call another Moldable app through the desktop broker.
|
|
100
|
+
*
|
|
101
|
+
* The target app owns its data and provider auth. The desktop broker handles
|
|
102
|
+
* workspace-scoped access grants and forwards the request to the target app's
|
|
103
|
+
* private /api/moldable/rpc endpoint.
|
|
104
|
+
*/
|
|
105
|
+
export function callMoldableApp(targetAppId, method, params, options = {}) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
if (!isInMoldable()) {
|
|
108
|
+
reject(new Error('App-to-app calls are only available inside Moldable.'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const requestId = makeRequestId('app-call');
|
|
112
|
+
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
113
|
+
const timeout = window.setTimeout(() => {
|
|
114
|
+
window.removeEventListener('message', handleResponse);
|
|
115
|
+
reject(new Error('App-to-app call timed out.'));
|
|
116
|
+
}, timeoutMs);
|
|
117
|
+
function handleResponse(event) {
|
|
118
|
+
if (event.data?.type !== 'moldable:app-call-result')
|
|
119
|
+
return;
|
|
120
|
+
if (event.data?.requestId !== requestId)
|
|
121
|
+
return;
|
|
122
|
+
window.clearTimeout(timeout);
|
|
123
|
+
window.removeEventListener('message', handleResponse);
|
|
124
|
+
const response = event.data;
|
|
125
|
+
if (response.ok) {
|
|
126
|
+
resolve(response.result);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const error = new Error(response.error?.message ||
|
|
130
|
+
response.error?.code ||
|
|
131
|
+
'App-to-app call failed.');
|
|
132
|
+
error.code = response.error?.code;
|
|
133
|
+
error.detail = response.error?.detail;
|
|
134
|
+
reject(error);
|
|
135
|
+
}
|
|
136
|
+
window.addEventListener('message', handleResponse);
|
|
137
|
+
sendToMoldable({
|
|
138
|
+
type: 'moldable:app-call',
|
|
139
|
+
requestId,
|
|
140
|
+
targetAppId,
|
|
141
|
+
method,
|
|
142
|
+
params,
|
|
143
|
+
scopes: options.scopes ?? [method],
|
|
144
|
+
requestAccess: options.requestAccess ?? true,
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
74
148
|
/**
|
|
75
149
|
* Trigger a file download via Moldable's native save dialog.
|
|
76
150
|
* Works inside Moldable's iframe environment where browser downloads don't work.
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moldable-ai/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Shared UI components for Moldable applications",
|
|
5
5
|
"author": "Desiderata LLC",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/moldable-ai/moldable.git",
|
package/src/styles/index.css
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
@custom-variant dark (&:is(.dark *));
|
|
7
7
|
|
|
8
8
|
/* Ensure Tailwind scans UI component class strings */
|
|
9
|
-
@source "
|
|
9
|
+
@source "../../dist/**/*.{js,jsx,ts,tsx}";
|
|
10
10
|
@source "../components/**/*.{js,jsx,ts,tsx}";
|
|
11
11
|
@source "../lib/**/*.{js,jsx,ts,tsx}";
|
|
12
12
|
@source "../hooks/**/*.{js,jsx,ts,tsx}";
|