@moldable-ai/ui 0.2.12 → 0.2.14

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.
@@ -3,7 +3,6 @@ type ErrorSource = 'react' | 'window' | 'promise';
3
3
  interface AppErrorBoundaryProps {
4
4
  appName: string;
5
5
  children: ReactNode;
6
- surface?: 'app' | 'widget';
7
6
  }
8
7
  interface AppErrorBoundaryState {
9
8
  error: Error | null;
@@ -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;IACnB,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;CAC3B;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,CAclB;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,KAAK,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAA;AAWjD,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;AAqDD,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;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,6 +26,19 @@ function formatError(error, source, componentStack) {
26
26
  parts.push(`Source: ${source}`);
27
27
  return parts.join('\n\n');
28
28
  }
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,
39
+ };
40
+ window.parent.postMessage(message, '*');
41
+ }
29
42
  export class AppErrorBoundary extends Component {
30
43
  state = {
31
44
  error: null,
@@ -50,16 +63,19 @@ export class AppErrorBoundary extends Component {
50
63
  componentDidCatch(error, info) {
51
64
  console.error(`${this.props.appName} UI crashed:`, error, info);
52
65
  this.setState({ componentStack: info.componentStack ?? null });
66
+ reportClientErrorToMoldable(this.props.appName, error, 'react', info.componentStack ?? null);
53
67
  }
54
68
  handleWindowError = (event) => {
55
69
  const error = event.error instanceof Error ? event.error : new Error(event.message);
56
70
  console.error(`${this.props.appName} uncaught frontend error:`, error);
57
71
  this.setState({ error, source: 'window', componentStack: null });
72
+ reportClientErrorToMoldable(this.props.appName, error, 'window', null);
58
73
  };
59
74
  handleUnhandledRejection = (event) => {
60
75
  const error = toError(event.reason);
61
76
  console.error(`${this.props.appName} unhandled promise rejection:`, error);
62
77
  this.setState({ error, source: 'promise', componentStack: null });
78
+ reportClientErrorToMoldable(this.props.appName, error, 'promise', null);
63
79
  };
64
80
  reload = () => {
65
81
  window.location.reload();
@@ -68,10 +84,9 @@ export class AppErrorBoundary extends Component {
68
84
  const { error, source, componentStack } = this.state;
69
85
  if (!error)
70
86
  return;
71
- const surfaceLabel = this.props.surface === 'widget' ? ' widget' : ' full app';
72
87
  const errorReport = formatError(error, source, componentStack);
73
88
  const text = [
74
- `${this.props.appName}${surfaceLabel} hit an uncaught frontend error.`,
89
+ `${this.props.appName} hit an uncaught frontend error.`,
75
90
  'Please inspect and fix the client crash.',
76
91
  errorReport,
77
92
  ].join('\n\n');
@@ -1,5 +1,5 @@
1
1
  import type { ChangeEvent, FormEvent, ReactNode, RefObject } from 'react';
2
- export type ChatSubmitMode = 'send' | 'steer' | 'queue';
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":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAGT,SAAS,EACT,SAAS,EACV,MAAM,OAAO,CAAA;AAKd,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEvD,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
+ {"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"}
@@ -30,8 +30,8 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
30
30
  onSubmit(undefined, isResponding ? 'queue' : 'send');
31
31
  }
32
32
  };
33
- // Keep the stop control available while a response is in progress.
34
- const showStopButton = isResponding;
33
+ // During a response, Enter/primary submit queues follow-up text.
34
+ const showStopButton = isResponding && !canSubmit;
35
35
  const handleButtonClick = (e) => {
36
36
  // When rendered as stop button (type="button"), always call onStop
37
37
  // Don't re-check conditions - trust the render decision to avoid race conditions
@@ -53,6 +53,6 @@ export function ChatInput({ input, onInputChange, onSubmit, isResponding, placeh
53
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
54
54
  ? 'Stop generating'
55
55
  : isResponding
56
- ? 'Steer response'
56
+ ? 'Queue follow-up'
57
57
  : 'Send message' })] })] }))] }) }) }) }));
58
58
  }
@@ -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';
@@ -153,7 +153,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
153
153
  }
154
154
  if (!input.trim() && imageAttachments.length === 0)
155
155
  return;
156
- const submitMode = mode ?? (isResponding ? 'steer' : 'send');
156
+ const submitMode = mode ?? (isResponding ? 'queue' : 'send');
157
157
  if (!isExpanded) {
158
158
  onExpandedChange(true);
159
159
  }
@@ -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
@@ -3,11 +3,11 @@ export { ThemeProvider, useTheme, themeScript, type Theme } from './lib/theme';
3
3
  export { WorkspaceProvider, useWorkspace, WORKSPACE_HEADER, } from './lib/workspace';
4
4
  export { useMoldableCommands, useMoldableCommand, useMoldableAppCommands, useMoldableNavigationPop, useMoldableNavigationState, isInMoldable, sendToMoldable, pushMoldableNavigation, popMoldableNavigation, resetMoldableNavigation, downloadFile, type AppCommand, type CommandAction, type CommandsResponse, type CommandMessage, type MoldableNavigationEntry, type MoldableNavigationPopMessage, type MoldableNavigationStateMessage, type DownloadFileOptions, } from './lib/commands';
5
5
  export * from './components/ui';
6
+ export { TODAY_KIND_RANK, TODAY_KIND_TTL_MS, makeTodayItem, type TodayItem, type TodayItemKind, type TodaySurface, type TodayAction, type TodayResponse, type ResumeState, type HydratedTodayItem, type HydratedResume, } from './lib/today';
6
7
  export { useIsMobile } from './hooks/use-mobile';
7
8
  export { Markdown } from './components/markdown';
8
9
  export { RichMediaPlayer, type RichMediaPlayerProps, } from './components/rich-media-player';
9
10
  export { CodeBlock } from './components/code-block';
10
- export { WidgetLayout } from './components/widget-layout';
11
11
  export { AppErrorBoundary } from './components/app-error-boundary';
12
12
  export * from './components/chat';
13
13
  //# 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,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,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAGzD,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,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAGlE,cAAc,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -8,6 +8,8 @@ export { WorkspaceProvider, useWorkspace, WORKSPACE_HEADER, } from './lib/worksp
8
8
  export { useMoldableCommands, useMoldableCommand, useMoldableAppCommands, useMoldableNavigationPop, useMoldableNavigationState, isInMoldable, sendToMoldable, pushMoldableNavigation, popMoldableNavigation, resetMoldableNavigation, downloadFile, } from './lib/commands';
9
9
  // Export UI components
10
10
  export * from './components/ui';
11
+ // Export Today contract
12
+ export { TODAY_KIND_RANK, TODAY_KIND_TTL_MS, makeTodayItem, } from './lib/today';
11
13
  // Export hooks
12
14
  export { useIsMobile } from './hooks/use-mobile';
13
15
  // Export Markdown
@@ -15,8 +17,6 @@ export { Markdown } from './components/markdown';
15
17
  export { RichMediaPlayer, } from './components/rich-media-player';
16
18
  // Export CodeBlock
17
19
  export { CodeBlock } from './components/code-block';
18
- // Export WidgetLayout
19
- export { WidgetLayout } from './components/widget-layout';
20
20
  // Export app error boundary
21
21
  export { AppErrorBoundary } from './components/app-error-boundary';
22
22
  // Export chat components
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Today contract — the shared shape apps use to contribute to the Moldable
3
+ * "Today" home view, and the host uses to aggregate + triage them.
4
+ *
5
+ * See prds/today-view.prd.md. The guiding rule: silence is the default. An app
6
+ * contributes an item ONLY when something earns attention (a resume point, an
7
+ * in-flight job, a blocker, a time-sensitive nudge). It does not mirror an
8
+ * always-on overview.
9
+ */
10
+ /**
11
+ * Why a contribution earns attention. Drives ranking, styling, and default decay.
12
+ * (prds/today-view.prd.md §3)
13
+ */
14
+ export type TodayItemKind = 'resume' | 'active' | 'blocked' | 'timely' | 'threshold' | 'milestone' | 'agent-activity';
15
+ /** How an item renders. Most items are `text`; `widget` is the rare live case. */
16
+ export type TodaySurface = 'text' | 'nudge' | 'metric' | 'widget';
17
+ /**
18
+ * An action a user can take directly from a Today card. Reuses the app-command
19
+ * vocabulary (navigate/message) plus Today-specific affordances.
20
+ */
21
+ export type TodayAction =
22
+ /** Open the contributing app (optionally deep-linked to a route/entity). */
23
+ {
24
+ type: 'open-app';
25
+ label: string;
26
+ deepLink?: string;
27
+ }
28
+ /** Call one of the app's own `/api/moldable/rpc` methods in place. */
29
+ | {
30
+ type: 'rpc';
31
+ label: string;
32
+ method: string;
33
+ params?: unknown;
34
+ /** If set, confirm with the user before running (destructive actions). */
35
+ confirm?: string;
36
+ /** Optional toast/label shown on success. */
37
+ successLabel?: string;
38
+ }
39
+ /** Drop a prompt into the unified chat to follow up / interrogate. */
40
+ | {
41
+ type: 'message';
42
+ label: string;
43
+ prompt: string;
44
+ }
45
+ /** Navigate the app to a specific path (app-command `navigate` semantics). */
46
+ | {
47
+ type: 'navigate';
48
+ label: string;
49
+ path: string;
50
+ }
51
+ /** Dismiss the item (host-handled; honors `cadence`). */
52
+ | {
53
+ type: 'dismiss';
54
+ label?: string;
55
+ };
56
+ /**
57
+ * A single Today contribution. Apps return zero or more of these from
58
+ * `GET /api/moldable/today`. `appId` is attached by the host (it knows which
59
+ * app it queried), so apps never set it.
60
+ */
61
+ export interface TodayItem {
62
+ /**
63
+ * Stable id for this *logical* item (e.g. `resume:lesson:hanon` or
64
+ * `timer:active`). Used for dedupe + persisting dismissals across refreshes.
65
+ */
66
+ id: string;
67
+ kind: TodayItemKind;
68
+ /** Defaults to `text`. */
69
+ surface?: TodaySurface;
70
+ /** One scannable line. ("Resume Lesson 2 of 4: Hanon Hand Agility") */
71
+ title: string;
72
+ /** Optional second line of context. */
73
+ subtitle?: string;
74
+ /** Emoji or lucide icon name; falls back to the app icon. */
75
+ icon?: string;
76
+ /** Optional accent color (CSS value) for emphasis. */
77
+ accentColor?: string;
78
+ /** Ordered actions; the first is treated as primary. */
79
+ actions?: TodayAction[];
80
+ /**
81
+ * For `surface: 'widget'` — a temporary, actionable embed summoned only for
82
+ * this item. `path` is served by the app.
83
+ */
84
+ widget?: {
85
+ path: string;
86
+ height?: number;
87
+ };
88
+ /** App hint, 0–100. The host has final say over ordering (PRD §6). */
89
+ priority?: number;
90
+ /** ISO timestamp; defaults to now when omitted. */
91
+ createdAt?: string;
92
+ /** ISO timestamp; host applies a per-kind default when omitted. */
93
+ expiresAt?: string;
94
+ /** Defaults to true. */
95
+ dismissible?: boolean;
96
+ /** Anti-repeat policy. `once` = don't resurface same day after dismiss. */
97
+ cadence?: 'once' | 'daily' | 'while-true';
98
+ /** Optional grouping label the agent/host may use to cluster items. */
99
+ groupHint?: string;
100
+ }
101
+ /**
102
+ * The most recent "pick up where you left off" point for an app. Powers the
103
+ * Resume rail. Distinct from a `resume`-kind item so the host can render it as
104
+ * a first-class, always-available rail rather than an attention card.
105
+ */
106
+ export interface ResumeState {
107
+ title: string;
108
+ subtitle?: string;
109
+ icon?: string;
110
+ /** Where opening the app should land. */
111
+ deepLink?: string;
112
+ /** ISO timestamp of last interaction; used to rank the rail by recency. */
113
+ lastTouchedAt?: string;
114
+ }
115
+ /** Response shape for `GET /api/moldable/today`. */
116
+ export interface TodayResponse {
117
+ items: TodayItem[];
118
+ resume?: ResumeState | null;
119
+ /** ISO timestamp the app generated this; host may use for caching. */
120
+ generatedAt?: string;
121
+ }
122
+ /** Host-side: a TodayItem enriched with which app produced it. */
123
+ export interface HydratedTodayItem extends TodayItem {
124
+ appId: string;
125
+ appName: string;
126
+ appIcon?: string;
127
+ appIconPath?: string;
128
+ }
129
+ /** Host-side resume entry (ResumeState + provenance). */
130
+ export interface HydratedResume extends ResumeState {
131
+ appId: string;
132
+ appName: string;
133
+ appIcon?: string;
134
+ appIconPath?: string;
135
+ }
136
+ /**
137
+ * Kind → ranking weight (higher surfaces first). The host's deterministic
138
+ * triage baseline; the Today agent may re-rank, but this is the floor.
139
+ * (prds/today-view.prd.md §6)
140
+ */
141
+ export declare const TODAY_KIND_RANK: Record<TodayItemKind, number>;
142
+ /** Kind → default time-to-live (ms) when an item omits `expiresAt`. */
143
+ export declare const TODAY_KIND_TTL_MS: Record<TodayItemKind, number>;
144
+ /**
145
+ * Normalize a partial item into a complete TodayItem with sensible defaults.
146
+ * Apps building items by hand can use this, or just return literal JSON — the
147
+ * host applies the same defaults defensively (see `normalizeTodayItem`).
148
+ */
149
+ export declare function makeTodayItem(item: Omit<TodayItem, 'createdAt' | 'surface' | 'dismissible'> & Partial<Pick<TodayItem, 'createdAt' | 'surface' | 'dismissible'>>): TodayItem;
150
+ //# sourceMappingURL=today.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"today.d.ts","sourceRoot":"","sources":["../../src/lib/today.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Today contract — the shared shape apps use to contribute to the Moldable
3
+ * "Today" home view, and the host uses to aggregate + triage them.
4
+ *
5
+ * See prds/today-view.prd.md. The guiding rule: silence is the default. An app
6
+ * contributes an item ONLY when something earns attention (a resume point, an
7
+ * in-flight job, a blocker, a time-sensitive nudge). It does not mirror an
8
+ * always-on overview.
9
+ */
10
+ /**
11
+ * Kind → ranking weight (higher surfaces first). The host's deterministic
12
+ * triage baseline; the Today agent may re-rank, but this is the floor.
13
+ * (prds/today-view.prd.md §6)
14
+ */
15
+ export const TODAY_KIND_RANK = {
16
+ blocked: 100,
17
+ timely: 90,
18
+ active: 80,
19
+ resume: 70,
20
+ threshold: 60,
21
+ 'agent-activity': 40,
22
+ milestone: 20,
23
+ };
24
+ /** Kind → default time-to-live (ms) when an item omits `expiresAt`. */
25
+ export const TODAY_KIND_TTL_MS = {
26
+ blocked: 24 * 60 * 60 * 1000,
27
+ timely: 6 * 60 * 60 * 1000,
28
+ active: 2 * 60 * 60 * 1000,
29
+ resume: 14 * 24 * 60 * 60 * 1000,
30
+ threshold: 24 * 60 * 60 * 1000,
31
+ 'agent-activity': 48 * 60 * 60 * 1000,
32
+ milestone: 24 * 60 * 60 * 1000,
33
+ };
34
+ /**
35
+ * Normalize a partial item into a complete TodayItem with sensible defaults.
36
+ * Apps building items by hand can use this, or just return literal JSON — the
37
+ * host applies the same defaults defensively (see `normalizeTodayItem`).
38
+ */
39
+ export function makeTodayItem(item) {
40
+ const createdAt = item.createdAt ?? new Date().toISOString();
41
+ const expiresAt = item.expiresAt ??
42
+ new Date(Date.parse(createdAt) + TODAY_KIND_TTL_MS[item.kind]).toISOString();
43
+ return {
44
+ surface: 'text',
45
+ dismissible: true,
46
+ ...item,
47
+ createdAt,
48
+ expiresAt,
49
+ };
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moldable-ai/ui",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
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",
@@ -101,7 +101,7 @@
101
101
  --card-foreground: oklch(0.141 0.005 285.823);
102
102
  --popover: oklch(1 0 0);
103
103
  --popover-foreground: oklch(0.141 0.005 285.823);
104
- --primary: oklch(0.7145 0.185 45.03);
104
+ --primary: oklch(0.205 0 0);
105
105
  --primary-foreground: oklch(0.985 0 0);
106
106
  --secondary: oklch(0.967 0.001 286.375);
107
107
  --secondary-foreground: oklch(0.21 0.006 285.885);
@@ -154,8 +154,8 @@
154
154
  --card-foreground: oklch(0.985 0 0);
155
155
  --popover: oklch(0.269 0.0018 286.28);
156
156
  --popover-foreground: oklch(0.985 0 0);
157
- --primary: oklch(0.7145 0.185 45.03);
158
- --primary-foreground: oklch(0.985 0 0);
157
+ --primary: oklch(0.985 0 0);
158
+ --primary-foreground: oklch(0.205 0 0);
159
159
  --secondary: oklch(0.3375 0.0035 286.21);
160
160
  --secondary-foreground: oklch(0.985 0 0);
161
161
  --muted: oklch(0.3375 0.0035 286.21);