@moldable-ai/ui 0.2.13 → 0.2.15

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.
@@ -1,17 +1,20 @@
1
1
  import { Component, type ErrorInfo, type ReactNode } from 'react';
2
- type ErrorSource = 'react' | 'window' | 'promise';
2
+ export type AppErrorSource = 'react' | 'window' | 'promise' | 'bootstrap';
3
3
  interface AppErrorBoundaryProps {
4
4
  appName: string;
5
5
  children: ReactNode;
6
+ initialError?: Error | null;
7
+ initialSource?: AppErrorSource;
6
8
  }
7
9
  interface AppErrorBoundaryState {
8
10
  error: Error | null;
9
- source: ErrorSource;
11
+ source: AppErrorSource;
10
12
  componentStack: string | null;
11
13
  }
12
14
  export declare class AppErrorBoundary extends Component<AppErrorBoundaryProps, AppErrorBoundaryState> {
13
15
  state: AppErrorBoundaryState;
14
16
  static getDerivedStateFromError(error: Error): Partial<AppErrorBoundaryState>;
17
+ constructor(props: AppErrorBoundaryProps);
15
18
  componentDidMount(): void;
16
19
  componentWillUnmount(): void;
17
20
  componentDidCatch(error: Error, info: ErrorInfo): void;
@@ -1 +1 @@
1
- {"version":3,"file":"app-error-boundary.d.ts","sourceRoot":"","sources":["../../src/components/app-error-boundary.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGjE,KAAK,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEjD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,UAAU,qBAAqB;IAC7B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAiCD,qBAAa,gBAAiB,SAAQ,SAAS,CAC7C,qBAAqB,EACrB,qBAAqB,CACtB;IACC,KAAK,EAAE,qBAAqB,CAI3B;IAED,MAAM,CAAC,wBAAwB,CAC7B,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,qBAAqB,CAAC;IAIjC,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;IAU5B,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAKtD,OAAO,CAAC,iBAAiB,CAKxB;IAED,OAAO,CAAC,wBAAwB,CAI/B;IAED,OAAO,CAAC,MAAM,CAEb;IAED,OAAO,CAAC,WAAW,CAYlB;IAED,MAAM;CA8CP"}
1
+ {"version":3,"file":"app-error-boundary.d.ts","sourceRoot":"","sources":["../../src/components/app-error-boundary.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGjE,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAA;AAWzE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,CAAA;IACnB,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,CAAA;IAC3B,aAAa,CAAC,EAAE,cAAc,CAAA;CAC/B;AAED,UAAU,qBAAqB;IAC7B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAqDD,qBAAa,gBAAiB,SAAQ,SAAS,CAC7C,qBAAqB,EACrB,qBAAqB,CACtB;IACC,KAAK,EAAE,qBAAqB,CAAA;IAE5B,MAAM,CAAC,wBAAwB,CAC7B,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,qBAAqB,CAAC;gBAIrB,KAAK,EAAE,qBAAqB;IASxC,iBAAiB,IAAI,IAAI;IAgBzB,oBAAoB,IAAI,IAAI;IAU5B,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAWtD,OAAO,CAAC,iBAAiB,CAMxB;IAED,OAAO,CAAC,wBAAwB,CAK/B;IAED,OAAO,CAAC,MAAM,CAEb;IAED,OAAO,CAAC,WAAW,CAYlB;IAED,MAAM;CA8CP"}
@@ -26,20 +26,40 @@ function formatError(error, source, componentStack) {
26
26
  parts.push(`Source: ${source}`);
27
27
  return parts.join('\n\n');
28
28
  }
29
- export class AppErrorBoundary extends Component {
30
- state = {
31
- error: null,
32
- source: 'react',
33
- componentStack: null,
29
+ function reportClientErrorToMoldable(appName, error, source, componentStack) {
30
+ if (typeof window === 'undefined' || window.parent === window)
31
+ return;
32
+ const message = {
33
+ type: 'moldable:app-client-error',
34
+ appName,
35
+ source,
36
+ message: `${error.name}: ${error.message}`,
37
+ stack: error.stack,
38
+ componentStack,
34
39
  };
40
+ window.parent.postMessage(message, '*');
41
+ }
42
+ export class AppErrorBoundary extends Component {
43
+ state;
35
44
  static getDerivedStateFromError(error) {
36
45
  return { error, source: 'react' };
37
46
  }
47
+ constructor(props) {
48
+ super(props);
49
+ this.state = {
50
+ error: props.initialError ?? null,
51
+ source: props.initialSource ?? 'react',
52
+ componentStack: null,
53
+ };
54
+ }
38
55
  componentDidMount() {
39
56
  if (typeof window === 'undefined')
40
57
  return;
41
58
  window.addEventListener('error', this.handleWindowError);
42
59
  window.addEventListener('unhandledrejection', this.handleUnhandledRejection);
60
+ if (this.state.error) {
61
+ reportClientErrorToMoldable(this.props.appName, this.state.error, this.state.source, this.state.componentStack);
62
+ }
43
63
  }
44
64
  componentWillUnmount() {
45
65
  if (typeof window === 'undefined')
@@ -50,16 +70,19 @@ export class AppErrorBoundary extends Component {
50
70
  componentDidCatch(error, info) {
51
71
  console.error(`${this.props.appName} UI crashed:`, error, info);
52
72
  this.setState({ componentStack: info.componentStack ?? null });
73
+ reportClientErrorToMoldable(this.props.appName, error, 'react', info.componentStack ?? null);
53
74
  }
54
75
  handleWindowError = (event) => {
55
76
  const error = event.error instanceof Error ? event.error : new Error(event.message);
56
77
  console.error(`${this.props.appName} uncaught frontend error:`, error);
57
78
  this.setState({ error, source: 'window', componentStack: null });
79
+ reportClientErrorToMoldable(this.props.appName, error, 'window', null);
58
80
  };
59
81
  handleUnhandledRejection = (event) => {
60
82
  const error = toError(event.reason);
61
83
  console.error(`${this.props.appName} unhandled promise rejection:`, error);
62
84
  this.setState({ error, source: 'promise', componentStack: null });
85
+ reportClientErrorToMoldable(this.props.appName, error, 'promise', null);
63
86
  };
64
87
  reload = () => {
65
88
  window.location.reload();
@@ -1,5 +1,5 @@
1
1
  import type { ChangeEvent, FormEvent, ReactNode, RefObject } from 'react';
2
- export type ChatSubmitMode = 'send' | 'queue' | 'manual-steer';
2
+ export type ChatSubmitMode = 'send' | 'queue';
3
3
  export type ChatSlashCommandOption = {
4
4
  id: string;
5
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-input.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAGT,SAAS,EACT,SAAS,EACV,MAAM,OAAO,CAAA;AAKd,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,cAAc,CAAA;AAE9D,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAA;IAC5D,QAAQ,EAAE,CACR,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,EACzC,IAAI,CAAC,EAAE,cAAc,KAClB,IAAI,CAAA;IACT,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAChD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,mBAAmB,CAAC,EAAE,SAAS,CAAA;IAC/B,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACxC,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACjE,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAA+B,EAC/B,QAAQ,EACR,MAAM,EACN,OAAe,EACf,gBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,cAAsB,EACtB,aAAkB,EAClB,oBAAoB,GACrB,EAAE,cAAc,2CAyMhB"}
1
+ {"version":3,"file":"chat-input.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAGT,SAAS,EACT,SAAS,EACV,MAAM,OAAO,CAAA;AAKd,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAA;AAE7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAA;IAC5D,QAAQ,EAAE,CACR,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,GAAG,SAAS,EACzC,IAAI,CAAC,EAAE,cAAc,KAClB,IAAI,CAAA;IACT,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAChD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACxC,uBAAuB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,mBAAmB,CAAC,EAAE,SAAS,CAAA;IAC/B,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACxC,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACjE,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAA+B,EAC/B,QAAQ,EACR,MAAM,EACN,OAAe,EACf,gBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,cAAsB,EACtB,aAAkB,EAClB,oBAAoB,GACrB,EAAE,cAAc,2CA2KhB"}
@@ -1,5 +1,5 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ArrowUp, CornerDownRight, Image as ImageIcon, ListPlus, Square, X, } from 'lucide-react';
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { ArrowUp, Image as ImageIcon, Square, X } from 'lucide-react';
3
3
  import { cn } from '../../lib/utils';
4
4
  import { Button } from '../ui/button';
5
5
  import { Textarea } from '../ui/textarea';
@@ -30,10 +30,8 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
30
30
  onSubmit(undefined, isResponding ? 'queue' : 'send');
31
31
  }
32
32
  };
33
- // During a response, Enter/primary submit queues follow-up text. The explicit
34
- // Steer control is the manual override for injecting it into the active turn.
33
+ // During a response, Enter/primary submit queues follow-up text.
35
34
  const showStopButton = isResponding && !canSubmit;
36
- const showQueueSubmitButton = isResponding && canSubmit;
37
35
  const handleButtonClick = (e) => {
38
36
  // When rendered as stop button (type="button"), always call onStop
39
37
  // Don't re-check conditions - trust the render decision to avoid race conditions
@@ -43,12 +41,6 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
43
41
  }
44
42
  // If type="submit", form handles submission
45
43
  };
46
- const handleSteerClick = (e) => {
47
- e.preventDefault();
48
- if (!canSubmit)
49
- return;
50
- onSubmit(undefined, 'manual-steer');
51
- };
52
44
  return (_jsx("div", { className: cn('isolate w-full p-2'), "data-chat-input-wrapper": true, children: _jsx("div", { className: "mx-auto max-w-5xl", children: _jsx("form", { onSubmit: (e) => {
53
45
  if (submitDisabled && !isResponding) {
54
46
  e.preventDefault();
@@ -58,9 +50,7 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
58
50
  }, children: _jsxs("div", { className: cn('bg-background relative flex w-full flex-col rounded-3xl border', compact && !hasAttachments && 'h-14'), children: [!compact && slashCommands.length > 0 && (_jsx("div", { className: "border-border bg-popover text-popover-foreground absolute bottom-full left-4 right-4 z-20 mb-2 overflow-hidden rounded-lg border shadow-lg", children: slashCommands.map((command) => (_jsxs("button", { type: "button", className: "hover:bg-accent hover:text-accent-foreground flex min-h-12 w-full cursor-pointer items-center gap-3 px-3 py-2.5 text-left transition-colors", onMouseDown: (event) => {
59
51
  event.preventDefault();
60
52
  onSlashCommandSelect?.(command);
61
- }, children: [_jsxs("span", { className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 font-mono text-xs", children: ["/", command.name] }), _jsx("span", { className: "min-w-0 text-xs", children: command.description })] }, command.id))) })), !compact && hasAttachments && (_jsx("div", { className: "flex max-h-32 gap-2 overflow-x-auto px-3 pt-3", children: imageAttachments.map((attachment) => (_jsxs("div", { className: "bg-muted/70 border-border flex max-w-48 shrink-0 items-center gap-2 rounded-xl border p-1.5 pr-2", children: [_jsx("div", { className: "bg-background flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border", children: attachment.previewUrl ? (_jsx("img", { src: attachment.previewUrl, alt: "", className: "size-full object-cover", draggable: false })) : (_jsx(ImageIcon, { className: "text-muted-foreground size-4" })) }), _jsx("span", { className: "min-w-0 truncate text-xs font-medium", title: attachment.path, children: attachment.name }), onRemoveImageAttachment && (_jsx("button", { type: "button", onClick: () => onRemoveImageAttachment(attachment.id), className: "text-muted-foreground hover:bg-accent hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md transition-colors", "aria-label": `Remove ${attachment.name}`, children: _jsx(X, { className: "size-3.5" }) }))] }, attachment.id))) })), _jsx("div", { className: cn('w-full px-5', compact ? 'py-4' : 'pb-2 pt-4'), children: _jsx(Textarea, { ref: inputRef, value: input, placeholder: placeholder, onChange: onInputChange, onKeyDown: handleKeyDown, className: cn('max-h-32 min-h-[24px] resize-none rounded-none border-0 !bg-transparent p-0 text-sm shadow-none focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:!bg-transparent', compact && 'max-h-6 min-h-6') }) }), !compact && (_jsxs("div", { className: "flex min-h-11 items-center justify-between gap-3 px-3 pb-3", children: [_jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-start gap-1", children: footerStartControls }), _jsx("div", { className: "min-w-0 flex-1" }), _jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-end gap-0.5", children: footerControls }), isResponding && canSubmit && (_jsxs(Button, { type: "button", variant: "secondary", size: "sm", className: "h-8 cursor-pointer gap-1.5 rounded-full px-2.5 text-xs", onClick: handleSteerClick, children: [_jsx(CornerDownRight, { className: "size-3.5" }), _jsx("span", { children: "Steer" })] })), _jsxs(Button, { type: showStopButton ? 'button' : 'submit', size: showQueueSubmitButton ? 'sm' : 'icon', className: cn('bg-primary text-primary-foreground h-8 cursor-pointer rounded-full hover:opacity-70 disabled:opacity-30', showQueueSubmitButton
62
- ? 'gap-1.5 px-2.5 text-xs'
63
- : 'size-8'), disabled: !canSubmit && !isResponding, onClick: handleButtonClick, children: [showStopButton ? (_jsx(Square, { className: "fill-primary-foreground size-4 animate-pulse" })) : showQueueSubmitButton ? (_jsxs(_Fragment, { children: [_jsx(ListPlus, { className: "size-3.5" }), _jsx("span", { children: "Queue" })] })) : (_jsx(ArrowUp, { className: "size-4" })), _jsx("span", { className: "sr-only", children: showStopButton
53
+ }, children: [_jsxs("span", { className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 font-mono text-xs", children: ["/", command.name] }), _jsx("span", { className: "min-w-0 text-xs", children: command.description })] }, command.id))) })), !compact && hasAttachments && (_jsx("div", { className: "flex max-h-32 gap-2 overflow-x-auto px-3 pt-3", children: imageAttachments.map((attachment) => (_jsxs("div", { className: "bg-muted/70 border-border flex max-w-48 shrink-0 items-center gap-2 rounded-xl border p-1.5 pr-2", children: [_jsx("div", { className: "bg-background flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border", children: attachment.previewUrl ? (_jsx("img", { src: attachment.previewUrl, alt: "", className: "size-full object-cover", draggable: false })) : (_jsx(ImageIcon, { className: "text-muted-foreground size-4" })) }), _jsx("span", { className: "min-w-0 truncate text-xs font-medium", title: attachment.path, children: attachment.name }), onRemoveImageAttachment && (_jsx("button", { type: "button", onClick: () => onRemoveImageAttachment(attachment.id), className: "text-muted-foreground hover:bg-accent hover:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md transition-colors", "aria-label": `Remove ${attachment.name}`, children: _jsx(X, { className: "size-3.5" }) }))] }, attachment.id))) })), _jsx("div", { className: cn('w-full px-5', compact ? 'py-4' : 'pb-2 pt-4'), children: _jsx(Textarea, { ref: inputRef, value: input, placeholder: placeholder, onChange: onInputChange, onKeyDown: handleKeyDown, className: cn('max-h-32 min-h-[24px] resize-none rounded-none border-0 !bg-transparent p-0 text-sm shadow-none focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:!bg-transparent', compact && 'max-h-6 min-h-6') }) }), !compact && (_jsxs("div", { className: "flex min-h-11 items-center justify-between gap-3 px-3 pb-3", children: [_jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-start gap-1", children: footerStartControls }), _jsx("div", { className: "min-w-0 flex-1" }), _jsx("div", { className: "flex min-w-0 shrink-0 items-center justify-end gap-0.5", children: footerControls }), _jsxs(Button, { type: showStopButton ? 'button' : 'submit', size: "icon", className: "bg-primary text-primary-foreground size-8 cursor-pointer rounded-full hover:opacity-70 disabled:opacity-30", disabled: !canSubmit && !isResponding, onClick: handleButtonClick, children: [showStopButton ? (_jsx(Square, { className: "fill-primary-foreground size-4 animate-pulse" })) : (_jsx(ArrowUp, { className: "size-4" })), _jsx("span", { className: "sr-only", children: showStopButton
64
54
  ? 'Stop generating'
65
55
  : isResponding
66
56
  ? 'Queue follow-up'
@@ -36,6 +36,6 @@ function PureMessages({ messages, status, checkpoints, restoringMessageId, onRes
36
36
  return (_jsxs(_Fragment, { children: [messages.map((message, index) => {
37
37
  const checkpoint = checkpoints?.get(message.id);
38
38
  return (_jsx(MessageRow, { message: message, isLast: index === messages.length - 1, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint }, message.id));
39
- }), isThinking && _jsx(ThinkingMessage, {}), isCompacting && _jsx(CompactingMessage, {})] }));
39
+ }), isThinking && !isCompacting && _jsx(ThinkingMessage, {}), isCompacting && _jsx(CompactingMessage, {})] }));
40
40
  }
41
41
  export const Messages = memo(PureMessages);
@@ -77,7 +77,7 @@ export interface ChatPanelProps {
77
77
  isExpanded: boolean;
78
78
  /** Toggle expanded state */
79
79
  onExpandedChange: (expanded: boolean) => void;
80
- /** Whether the panel is minimized (hidden below fold with only flap visible) */
80
+ /** Whether the panel is minimized (hidden below fold) */
81
81
  isMinimized?: boolean;
82
82
  /** Toggle minimized state */
83
83
  onMinimizedChange?: (minimized: boolean) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"chat-panel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-panel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-panel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-panel.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, MessageCircle, Pencil, Trash2, } from 'lucide-react';
3
+ import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Pencil, Trash2, } from 'lucide-react';
4
4
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
5
5
  import { cn } from '../../lib/utils';
6
6
  import { Button } from '../ui/button';
@@ -210,10 +210,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
210
210
  document.addEventListener('keydown', handleKeyDown);
211
211
  return () => document.removeEventListener('keydown', handleKeyDown);
212
212
  }, [controlsDisabled, isExpanded, handleNewChat]);
213
- // Handle clicking the minimized flap
214
- const handleFlapClick = useCallback(() => {
215
- onMinimizedChange?.(false);
216
- }, [onMinimizedChange]);
217
213
  // Handle minimize button - now goes to minimized state
218
214
  const handleMinimize = useCallback(() => {
219
215
  if (isExpanded) {
@@ -242,7 +238,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
242
238
  }
243
239
  items.push({ key: message.id, kind: 'message', message });
244
240
  }
245
- if (isThinking) {
241
+ if (isThinking && !isCompacting) {
246
242
  items.push({ key: 'thinking', kind: 'thinking' });
247
243
  }
248
244
  if (isCompacting) {
@@ -358,7 +354,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
358
354
  }
359
355
  };
360
356
  }, [isAtBottom, isExpanded, messages.length, scrollToBottom]);
361
- return (_jsxs(_Fragment, { children: [_jsx(AnimatePresence, { children: isExpanded && !isMinimized && (_jsx(motion.div, { "data-moldable-chat-backdrop": true, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, className: "fixed inset-0 z-40 bg-black/20", onClick: () => onExpandedChange(false) })) }), _jsx(AnimatePresence, { children: isMinimized && (_jsx(motion.div, { "data-moldable-chat-panel": true, initial: { y: 20, opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: 20, opacity: 0 }, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "fixed bottom-0 left-[calc(50%+var(--sidebar-width,0px)/2)] z-50 -translate-x-1/2", children: _jsxs("button", { onClick: handleFlapClick, className: cn('bg-background/95 hover:bg-background group flex cursor-pointer items-center gap-2 rounded-t-xl border border-b-0 px-4 py-2 shadow-lg backdrop-blur transition-colors', 'text-muted-foreground hover:text-foreground'), children: [_jsx(MessageCircle, { className: "size-4" }), _jsx("span", { className: "text-sm font-medium", children: "Chat" }), _jsx("span", { className: "bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary rounded px-1.5 py-0.5 text-xs transition-colors", children: "\u2318M" })] }) })) }), _jsx(motion.div, { "data-moldable-chat-panel": true, initial: false, animate: {
357
+ return (_jsxs(_Fragment, { children: [_jsx(AnimatePresence, { children: isExpanded && !isMinimized && (_jsx(motion.div, { "data-moldable-chat-backdrop": true, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, className: "fixed inset-0 z-40 bg-black/20", onClick: () => onExpandedChange(false) })) }), _jsx(motion.div, { "data-moldable-chat-panel": true, initial: false, animate: {
362
358
  width: isExpanded ? 'min(90vw, 640px)' : '400px',
363
359
  y: isMinimized ? 'calc(100% + 24px)' : 0,
364
360
  opacity: isMinimized ? 0 : 1,
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { useIsMobile } from './hooks/use-mobile';
8
8
  export { Markdown } from './components/markdown';
9
9
  export { RichMediaPlayer, type RichMediaPlayerProps, } from './components/rich-media-player';
10
10
  export { CodeBlock } from './components/code-block';
11
- export { AppErrorBoundary } from './components/app-error-boundary';
11
+ export { AppErrorBoundary, type AppErrorSource, } from './components/app-error-boundary';
12
+ export { installMoldableFrameLifecycle } from './lib/frame-lifecycle';
12
13
  export * from './components/chat';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -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,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,EAC1B,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAA;AAGvB,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,gCAAgC,CAAA;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAGlE,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,wBAAwB,EACxB,0BAA0B,EAC1B,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAA;AAGvB,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,gCAAgC,CAAA;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGnD,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,GACpB,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAA;AAGrE,cAAc,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ export { RichMediaPlayer, } from './components/rich-media-player';
18
18
  // Export CodeBlock
19
19
  export { CodeBlock } from './components/code-block';
20
20
  // Export app error boundary
21
- export { AppErrorBoundary } from './components/app-error-boundary';
21
+ export { AppErrorBoundary, } from './components/app-error-boundary';
22
+ // Export Moldable frame lifecycle
23
+ export { installMoldableFrameLifecycle } from './lib/frame-lifecycle';
22
24
  // Export chat components
23
25
  export * from './components/chat';
@@ -0,0 +1,2 @@
1
+ export declare function installMoldableFrameLifecycle(): void;
2
+ //# sourceMappingURL=frame-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-lifecycle.d.ts","sourceRoot":"","sources":["../../src/lib/frame-lifecycle.ts"],"names":[],"mappings":"AAgEA,wBAAgB,6BAA6B,IAAI,IAAI,CAapD"}
@@ -0,0 +1,47 @@
1
+ let frameLifecycleInstalled = false;
2
+ function postMoldableFrameMessage(message) {
3
+ if (typeof window === 'undefined' || window.parent === window)
4
+ return;
5
+ window.parent.postMessage(message, '*');
6
+ }
7
+ function reportAppReady(reason) {
8
+ postMoldableFrameMessage({ type: 'moldable:app-ready', reason });
9
+ }
10
+ function scheduleRenderReady() {
11
+ requestAnimationFrame(() => {
12
+ requestAnimationFrame(() => reportAppReady('render'));
13
+ });
14
+ }
15
+ function installViteHmrLifecycle() {
16
+ const hot = import.meta.hot;
17
+ if (!hot)
18
+ return;
19
+ hot.on('vite:beforeUpdate', () => {
20
+ postMoldableFrameMessage({ type: 'moldable:app-hmr-before-update' });
21
+ });
22
+ hot.on('vite:afterUpdate', () => {
23
+ reportAppReady('hmr');
24
+ postMoldableFrameMessage({ type: 'moldable:app-hmr-after-update' });
25
+ });
26
+ hot.on('vite:error', (payload) => {
27
+ postMoldableFrameMessage({
28
+ type: 'moldable:app-hmr-error',
29
+ message: payload.err?.message ??
30
+ payload.message ??
31
+ 'Vite hot reload failed while updating the app.',
32
+ stack: payload.err?.stack,
33
+ });
34
+ });
35
+ }
36
+ export function installMoldableFrameLifecycle() {
37
+ if (typeof window === 'undefined' || frameLifecycleInstalled)
38
+ return;
39
+ frameLifecycleInstalled = true;
40
+ installViteHmrLifecycle();
41
+ scheduleRenderReady();
42
+ if (document.readyState === 'complete') {
43
+ reportAppReady('load');
44
+ return;
45
+ }
46
+ window.addEventListener('load', () => reportAppReady('load'), { once: true });
47
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moldable-ai/ui",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "Shared UI components for Moldable applications",
5
5
  "author": "Desiderata LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -108,7 +108,7 @@
108
108
  "@types/react-dom": "^19.1.6",
109
109
  "jsdom": "^26.1.0",
110
110
  "typescript": "^5.8.3",
111
- "vitest": "^3.2.4"
111
+ "vitest": "^4.1.8"
112
112
  },
113
113
  "peerDependencies": {
114
114
  "react": "^19.0.0",