@movable/ui 4.1.1 → 4.2.1

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,4 +1,5 @@
1
1
  import { ButtonProps } from '@mui/material';
2
+ import type { ReactNode } from 'react';
2
3
  type PrimaryButtonType = ButtonProps & {
3
4
  label: string;
4
5
  loading?: boolean;
@@ -11,7 +12,7 @@ type ActionButtonPropType = {
11
12
  close?: closeButtonType;
12
13
  };
13
14
  type InkWorkflowHeaderProps = {
14
- label: string;
15
+ label: ReactNode;
15
16
  Stepper?: JSX.Element;
16
17
  ButtonGroup?: JSX.Element | ActionButtonPropType;
17
18
  subtitle?: string;
@@ -0,0 +1,40 @@
1
+ import { ReactNode } from 'react';
2
+ import { SxProps, Theme } from '@mui/material';
3
+ export type ChatChip = {
4
+ id: string;
5
+ label: string;
6
+ icon?: ReactNode;
7
+ };
8
+ export type ScopeOption = {
9
+ value: string;
10
+ label: string;
11
+ icon?: ReactNode;
12
+ };
13
+ export type InkAiChatInputProps = {
14
+ value: string;
15
+ onChange: (value: string) => void;
16
+ onSubmit: (value: string) => void;
17
+ isGenerating?: boolean;
18
+ onStop?: () => void;
19
+ disabled?: boolean;
20
+ placeholder?: string;
21
+ chips?: ChatChip[];
22
+ onRemoveChip?: (id: string) => void;
23
+ scopeOptions?: ScopeOption[];
24
+ scopeValue?: string;
25
+ onScopeChange?: (value: string) => void;
26
+ onAttachClick?: () => void;
27
+ onMentionClick?: () => void;
28
+ autoFocus?: boolean;
29
+ /**
30
+ * Stable name for the textarea. Also used as a fallback id for the scope
31
+ * select. Generated via `useId()` if omitted — supply explicitly when
32
+ * rendering multiple instances on the same page or when the consumer needs
33
+ * a predictable selector.
34
+ */
35
+ name?: string;
36
+ className?: string;
37
+ sx?: SxProps<Theme>;
38
+ };
39
+ declare const InkAiChatInput: import("react").ForwardRefExoticComponent<InkAiChatInputProps & import("react").RefAttributes<HTMLDivElement>>;
40
+ export { InkAiChatInput };
@@ -0,0 +1 @@
1
+ export { InkAiChatInput, type InkAiChatInputProps, type ChatChip, type ScopeOption, } from './InkAiChatInput';
@@ -0,0 +1,40 @@
1
+ import { SxProps, Theme } from '@mui/material';
2
+ export type InkAiAssistantMessageProps = {
3
+ /** Markdown string to render. */
4
+ content: string;
5
+ /**
6
+ * True when the LLM has accepted the prompt but has not yet produced any
7
+ * output. Renders the `InkAiThinkingIndicator` instead of the body.
8
+ * Mirrors CopilotKit's `isLoading` slot prop.
9
+ */
10
+ isLoading?: boolean;
11
+ /** True while the assistant is still streaming this message. Hides actions. */
12
+ isGenerating?: boolean;
13
+ /** Show the action row. Default: true when not generating. */
14
+ showActions?: boolean;
15
+ /**
16
+ * Optional label for the thinking indicator shown when `isLoading` is true
17
+ * or `content` is empty. Defaults to "Thinking…" (set by
18
+ * `InkAiThinkingIndicator`).
19
+ */
20
+ thinkingLabel?: string;
21
+ /**
22
+ * Called when the user clicks copy. Defaults to
23
+ * `navigator.clipboard.writeText(content)`.
24
+ */
25
+ onCopy?: (content: string) => void;
26
+ /** Called when the user clicks a feedback button. */
27
+ onFeedback?: (kind: 'up' | 'down') => void;
28
+ className?: string;
29
+ sx?: SxProps<Theme>;
30
+ };
31
+ /**
32
+ * Renders an assistant message: markdown body styled with MUI typography
33
+ * + an inline action row (thumbs up/down/copy). No CopilotKit dependency —
34
+ * the consuming app wires this into CopilotKit's `AssistantMessage` slot.
35
+ *
36
+ * When `isLoading` is true, or when `content` is empty/whitespace, the
37
+ * `InkAiThinkingIndicator` is rendered in place of the body and the action
38
+ * row is hidden.
39
+ */
40
+ export declare const InkAiAssistantMessage: ({ content, isLoading, isGenerating, showActions, thinkingLabel, onCopy, onFeedback, className, sx, }: InkAiAssistantMessageProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { SxProps, Theme } from '@mui/material';
2
+ export type InkAiMessageActionsProps = {
3
+ /** Called when the copy button is clicked. */
4
+ onCopy: () => void;
5
+ /** Called when a feedback button is clicked. */
6
+ onFeedback?: (kind: 'up' | 'down') => void;
7
+ className?: string;
8
+ sx?: SxProps<Theme>;
9
+ };
10
+ /**
11
+ * Action row rendered below an assistant message. Three buttons in an 8px
12
+ * horizontal stack: good response, bad response, copy message.
13
+ */
14
+ export declare const InkAiMessageActions: ({ onCopy, onFeedback, className, sx, }: InkAiMessageActionsProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { SxProps, Theme } from '@mui/material';
3
+ export type InkAiUserMessageProps = {
4
+ /** Text content of the message. */
5
+ content: ReactNode;
6
+ className?: string;
7
+ sx?: SxProps<Theme>;
8
+ };
9
+ /**
10
+ * Light-blue user message bubble matching the Movable Ink AI assistant Figma
11
+ * design. Purely presentational — right-alignment within a conversation
12
+ * column is the parent's responsibility.
13
+ */
14
+ export declare const InkAiUserMessage: ({ content, className, sx, }: InkAiUserMessageProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { InkAiUserMessage, type InkAiUserMessageProps, } from './InkAiUserMessage';
2
+ export { InkAiAssistantMessage, type InkAiAssistantMessageProps, } from './InkAiAssistantMessage';
@@ -0,0 +1,8 @@
1
+ import type { MarkdownToJSX } from 'markdown-to-jsx';
2
+ /**
3
+ * Mapping passed to <Markdown options={{ overrides }} /> so markdown nodes
4
+ * inherit MUI typography/colors instead of browser defaults. Keeps the
5
+ * Movable Ink AI assistant brand styling (blue.800 inline link, semi-bold
6
+ * strong, body2 paragraphs, disc lists with 4px item gap).
7
+ */
8
+ export declare const markdownComponents: MarkdownToJSX.Overrides;
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ import { SxProps, Theme } from '@mui/material';
3
+ export type InkAiReasoningContentProps = {
4
+ /** Whether reasoning is still streaming. */
5
+ isStreaming?: boolean;
6
+ /** Whether the reasoning content has any text yet. */
7
+ hasContent?: boolean;
8
+ /**
9
+ * The reasoning content. CopilotKit passes the message body string here.
10
+ * Rendered as plain text inside caption typography.
11
+ */
12
+ children?: ReactNode;
13
+ className?: string;
14
+ sx?: SxProps<Theme>;
15
+ };
16
+ /**
17
+ * Body slot for CopilotKit's CopilotChatReasoningMessage `contentView`
18
+ * slot. Renders the streaming/static reasoning text in a left-bordered
19
+ * caption-typography block.
20
+ */
21
+ export declare const InkAiReasoningContent: ({ isStreaming, hasContent, children, className, sx, }: InkAiReasoningContentProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ import { SxProps, Theme } from '@mui/material';
2
+ export type InkAiReasoningHeaderProps = {
3
+ /** Currently expanded? Comes from CopilotKit. */
4
+ isOpen?: boolean;
5
+ /**
6
+ * Whether the reasoning is still streaming. Comes from CopilotKit.
7
+ * Drives the gradient/gray styling switch.
8
+ */
9
+ isStreaming?: boolean;
10
+ /**
11
+ * Whether reasoning has produced any content yet. Comes from CopilotKit.
12
+ * When false AND not streaming, the header is non-interactive and the
13
+ * chevron is hidden.
14
+ */
15
+ hasContent?: boolean;
16
+ /**
17
+ * Label string supplied by CopilotKit's CopilotChatReasoningMessage
18
+ * (e.g. "Thinking…", "Thought for 14 seconds"). Rendered as-is unless
19
+ * `formatLabel` is provided.
20
+ */
21
+ label?: string;
22
+ /**
23
+ * Optional escape hatch for consumers who want to rewrite CopilotKit's
24
+ * default wording without forking. Receives the original label and the
25
+ * current state; returns the string actually rendered.
26
+ */
27
+ formatLabel?: (label: string, ctx: {
28
+ isStreaming: boolean;
29
+ isOpen: boolean;
30
+ hasContent: boolean;
31
+ }) => string;
32
+ /** Click handler from CopilotKit; toggles open/closed. */
33
+ onClick?: () => void;
34
+ className?: string;
35
+ sx?: SxProps<Theme>;
36
+ };
37
+ /**
38
+ * Header row for CopilotKit's CopilotChatReasoningMessage `header` slot.
39
+ * Switches between a purple-gradient streaming label and a gray
40
+ * collapsible label with a rotating chevron.
41
+ */
42
+ export declare const InkAiReasoningHeader: ({ isOpen, isStreaming, hasContent, label, formatLabel, onClick, className, sx, }: InkAiReasoningHeaderProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { SxProps, Theme } from '@mui/material';
2
+ export type InkAiThinkingIndicatorProps = {
3
+ /**
4
+ * The text label rendered with the purple gradient. Default: "Thinking…".
5
+ * Pass a label appropriate to the flow (e.g. "Doing some calculations…").
6
+ */
7
+ label?: string;
8
+ className?: string;
9
+ sx?: SxProps<Theme>;
10
+ };
11
+ /**
12
+ * Single-line purple-gradient label rendered while the assistant is in a
13
+ * pre-output "loading" state — before any reasoning or content arrives.
14
+ * Intended for use inside a custom CopilotKit `AssistantMessage` slot.
15
+ */
16
+ export declare const InkAiThinkingIndicator: ({ label, className, sx, }: InkAiThinkingIndicatorProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import type { SxProps, Theme } from '@mui/material';
2
+ /**
3
+ * Movable Ink AI assistant shimmering brand gradient applied via
4
+ * background-clip: text. Two stacked gradients — a moving white highlight
5
+ * over a horizontal brand-color band — animated to sweep continuously.
6
+ *
7
+ * Used by `InkAiThinkingIndicator` and by the streaming-state label in
8
+ * `InkAiReasoningHeader`.
9
+ *
10
+ * Visuals match `sampleMessage.html` (`.ai-status-text` / `--active`),
11
+ * which is itself derived from the Figma reference:
12
+ * https://www.figma.com/design/ZbPxTAveBsb7RRJyMj4Fbw/AI-Assistants?node-id=2437-5612
13
+ *
14
+ * Honors `prefers-reduced-motion: reduce` by stopping the animation while
15
+ * keeping the static gradient visible.
16
+ */
17
+ export declare const gradientTextSx: SxProps<Theme>;
@@ -0,0 +1,3 @@
1
+ export { InkAiThinkingIndicator, type InkAiThinkingIndicatorProps, } from './InkAiThinkingIndicator';
2
+ export { InkAiReasoningHeader, type InkAiReasoningHeaderProps, } from './InkAiReasoningHeader';
3
+ export { InkAiReasoningContent, type InkAiReasoningContentProps, } from './InkAiReasoningContent';
@@ -13,6 +13,9 @@ export { InkToggleIcon } from './InkToggleIcon';
13
13
  export { InkToggleIconGroup, type InkToggleIconGroupProps, } from './InkToggleIconGroup';
14
14
  export { InkEmptyState } from './InkEmptyState';
15
15
  export { InkAttributeList } from './InkAttributeList';
16
+ export { InkAiChatInput, type InkAiChatInputProps, type ChatChip, type ScopeOption, } from './InkAiChatInput';
17
+ export { InkAiUserMessage, type InkAiUserMessageProps, InkAiAssistantMessage, type InkAiAssistantMessageProps, } from './InkAiMessages';
18
+ export { InkAiThinkingIndicator, type InkAiThinkingIndicatorProps, InkAiReasoningHeader, type InkAiReasoningHeaderProps, InkAiReasoningContent, type InkAiReasoningContentProps, } from './InkAiReasoning';
16
19
  export { InkImage } from './InkImage';
17
20
  export { InkDrawer } from './InkDrawer';
18
21
  export { InkComponentTile, type InkComponentTileProps, type InkTileIconProps, } from './InkComponentTile';
package/lib/index.d.ts CHANGED
@@ -127,6 +127,12 @@ declare type ChartProps<T extends ChartTypes> = {
127
127
 
128
128
  declare type ChartTypes = 'line' | 'bar' | 'pie';
129
129
 
130
+ export declare type ChatChip = {
131
+ id: string;
132
+ label: string;
133
+ icon?: ReactNode;
134
+ };
135
+
130
136
  declare type closeButtonType = {
131
137
  onClick: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
132
138
  };
@@ -341,6 +347,171 @@ export declare type InkAccordionProps = Omit<AccordionProps, 'children'> & {
341
347
  onDelete?: () => void;
342
348
  };
343
349
 
350
+ /**
351
+ * Renders an assistant message: markdown body styled with MUI typography
352
+ * + an inline action row (thumbs up/down/copy). No CopilotKit dependency —
353
+ * the consuming app wires this into CopilotKit's `AssistantMessage` slot.
354
+ *
355
+ * When `isLoading` is true, or when `content` is empty/whitespace, the
356
+ * `InkAiThinkingIndicator` is rendered in place of the body and the action
357
+ * row is hidden.
358
+ */
359
+ export declare const InkAiAssistantMessage: ({ content, isLoading, isGenerating, showActions, thinkingLabel, onCopy, onFeedback, className, sx, }: InkAiAssistantMessageProps) => JSX_2.Element;
360
+
361
+ export declare type InkAiAssistantMessageProps = {
362
+ /** Markdown string to render. */
363
+ content: string;
364
+ /**
365
+ * True when the LLM has accepted the prompt but has not yet produced any
366
+ * output. Renders the `InkAiThinkingIndicator` instead of the body.
367
+ * Mirrors CopilotKit's `isLoading` slot prop.
368
+ */
369
+ isLoading?: boolean;
370
+ /** True while the assistant is still streaming this message. Hides actions. */
371
+ isGenerating?: boolean;
372
+ /** Show the action row. Default: true when not generating. */
373
+ showActions?: boolean;
374
+ /**
375
+ * Optional label for the thinking indicator shown when `isLoading` is true
376
+ * or `content` is empty. Defaults to "Thinking…" (set by
377
+ * `InkAiThinkingIndicator`).
378
+ */
379
+ thinkingLabel?: string;
380
+ /**
381
+ * Called when the user clicks copy. Defaults to
382
+ * `navigator.clipboard.writeText(content)`.
383
+ */
384
+ onCopy?: (content: string) => void;
385
+ /** Called when the user clicks a feedback button. */
386
+ onFeedback?: (kind: 'up' | 'down') => void;
387
+ className?: string;
388
+ sx?: SxProps<Theme_2>;
389
+ };
390
+
391
+ export declare const InkAiChatInput: ForwardRefExoticComponent<InkAiChatInputProps & RefAttributes<HTMLDivElement>>;
392
+
393
+ export declare type InkAiChatInputProps = {
394
+ value: string;
395
+ onChange: (value: string) => void;
396
+ onSubmit: (value: string) => void;
397
+ isGenerating?: boolean;
398
+ onStop?: () => void;
399
+ disabled?: boolean;
400
+ placeholder?: string;
401
+ chips?: ChatChip[];
402
+ onRemoveChip?: (id: string) => void;
403
+ scopeOptions?: ScopeOption[];
404
+ scopeValue?: string;
405
+ onScopeChange?: (value: string) => void;
406
+ onAttachClick?: () => void;
407
+ onMentionClick?: () => void;
408
+ autoFocus?: boolean;
409
+ /**
410
+ * Stable name for the textarea. Also used as a fallback id for the scope
411
+ * select. Generated via `useId()` if omitted — supply explicitly when
412
+ * rendering multiple instances on the same page or when the consumer needs
413
+ * a predictable selector.
414
+ */
415
+ name?: string;
416
+ className?: string;
417
+ sx?: SxProps<Theme_2>;
418
+ };
419
+
420
+ /**
421
+ * Body slot for CopilotKit's CopilotChatReasoningMessage `contentView`
422
+ * slot. Renders the streaming/static reasoning text in a left-bordered
423
+ * caption-typography block.
424
+ */
425
+ export declare const InkAiReasoningContent: ({ isStreaming, hasContent, children, className, sx, }: InkAiReasoningContentProps) => JSX_2.Element | null;
426
+
427
+ export declare type InkAiReasoningContentProps = {
428
+ /** Whether reasoning is still streaming. */
429
+ isStreaming?: boolean;
430
+ /** Whether the reasoning content has any text yet. */
431
+ hasContent?: boolean;
432
+ /**
433
+ * The reasoning content. CopilotKit passes the message body string here.
434
+ * Rendered as plain text inside caption typography.
435
+ */
436
+ children?: ReactNode;
437
+ className?: string;
438
+ sx?: SxProps<Theme_2>;
439
+ };
440
+
441
+ /**
442
+ * Header row for CopilotKit's CopilotChatReasoningMessage `header` slot.
443
+ * Switches between a purple-gradient streaming label and a gray
444
+ * collapsible label with a rotating chevron.
445
+ */
446
+ export declare const InkAiReasoningHeader: ({ isOpen, isStreaming, hasContent, label, formatLabel, onClick, className, sx, }: InkAiReasoningHeaderProps) => JSX_2.Element;
447
+
448
+ export declare type InkAiReasoningHeaderProps = {
449
+ /** Currently expanded? Comes from CopilotKit. */
450
+ isOpen?: boolean;
451
+ /**
452
+ * Whether the reasoning is still streaming. Comes from CopilotKit.
453
+ * Drives the gradient/gray styling switch.
454
+ */
455
+ isStreaming?: boolean;
456
+ /**
457
+ * Whether reasoning has produced any content yet. Comes from CopilotKit.
458
+ * When false AND not streaming, the header is non-interactive and the
459
+ * chevron is hidden.
460
+ */
461
+ hasContent?: boolean;
462
+ /**
463
+ * Label string supplied by CopilotKit's CopilotChatReasoningMessage
464
+ * (e.g. "Thinking…", "Thought for 14 seconds"). Rendered as-is unless
465
+ * `formatLabel` is provided.
466
+ */
467
+ label?: string;
468
+ /**
469
+ * Optional escape hatch for consumers who want to rewrite CopilotKit's
470
+ * default wording without forking. Receives the original label and the
471
+ * current state; returns the string actually rendered.
472
+ */
473
+ formatLabel?: (label: string, ctx: {
474
+ isStreaming: boolean;
475
+ isOpen: boolean;
476
+ hasContent: boolean;
477
+ }) => string;
478
+ /** Click handler from CopilotKit; toggles open/closed. */
479
+ onClick?: () => void;
480
+ className?: string;
481
+ sx?: SxProps<Theme_2>;
482
+ };
483
+
484
+ /**
485
+ * Single-line purple-gradient label rendered while the assistant is in a
486
+ * pre-output "loading" state — before any reasoning or content arrives.
487
+ * Intended for use inside a custom CopilotKit `AssistantMessage` slot.
488
+ */
489
+ export declare const InkAiThinkingIndicator: ({ label, className, sx, }: InkAiThinkingIndicatorProps) => JSX_2.Element;
490
+
491
+ export declare type InkAiThinkingIndicatorProps = {
492
+ /**
493
+ * The text label rendered with the purple gradient. Default: "Thinking…".
494
+ * Pass a label appropriate to the flow (e.g. "Doing some calculations…").
495
+ */
496
+ label?: string;
497
+ className?: string;
498
+ sx?: SxProps<Theme_2>;
499
+ };
500
+
501
+ /**
502
+ * Light-blue user message bubble matching the Movable Ink AI assistant Figma
503
+ * design. Purely presentational — right-alignment within a conversation
504
+ * column is the parent's responsibility.
505
+ */
506
+ export declare const InkAiUserMessage: ({ content, className, sx, }: InkAiUserMessageProps) => JSX_2.Element;
507
+
508
+ export declare type InkAiUserMessageProps = {
509
+ /** Text content of the message. */
510
+ content: ReactNode;
511
+ className?: string;
512
+ sx?: SxProps<Theme_2>;
513
+ };
514
+
344
515
  /**
345
516
  * InkAlert component provides a consistent way to display alerts with proper
346
517
  * alignment and styling. It handles the vertical alignment issues when
@@ -1021,7 +1192,7 @@ export declare class InkWorkflowHeaderPageObject {
1021
1192
  }
1022
1193
 
1023
1194
  declare type InkWorkflowHeaderProps = {
1024
- label: string;
1195
+ label: ReactNode;
1025
1196
  Stepper?: JSX.Element;
1026
1197
  ButtonGroup?: JSX.Element | ActionButtonPropType;
1027
1198
  subtitle?: string;
@@ -1191,6 +1362,12 @@ declare type RobustCardProps = BaseProps & {
1191
1362
  directIndirect?: DirectIndirectData;
1192
1363
  };
1193
1364
 
1365
+ export declare type ScopeOption = {
1366
+ value: string;
1367
+ label: string;
1368
+ icon?: ReactNode;
1369
+ };
1370
+
1194
1371
  export declare type SecondaryMetricData = {
1195
1372
  value: string;
1196
1373
  label: string;