@marketrix.ai/widget 3.8.495 → 3.8.497

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `LiveDot` — the ping/core span pair that keys `index.css`'s `mtx-live-dot*` rules, the pulsing dot the
3
+ * header's screen-share button and a video message's "Live" pill both wear. The markup contract is fixed
4
+ * by the CSS (an `mtx-live-dot` wrapper around an `mtx-live-dot-ping` and an `mtx-live-dot-core`); only
5
+ * `style` on the wrapper varies per caller (positioning it absolutely over an icon, or tinting it via
6
+ * `currentColor`).
7
+ */
8
+ import type { CSSProperties } from 'react';
9
+ export declare function LiveDot({ style }: {
10
+ style?: CSSProperties;
11
+ }): import("react").JSX.Element;
@@ -6,6 +6,11 @@
6
6
  * tables — the `default`/`none` entries are empty, so a bare `Surface` is a plain element — and
7
7
  * `SurfaceProps` the prop surface: `LayoutProps` plus the host element's HTML attributes.
8
8
  *
9
+ * `floatingCard` is a `variant` shorthand for the card-background/border/card-elevation/card-padding/xl-
10
+ * rounded/margin bundle both `HomeView`'s recent-conversation card and `ChatView`'s composer card use —
11
+ * the margin lives in `variantStyles` since both call sites want it, while `ChatView`'s extra
12
+ * `marginTop: 'auto'` stays an override on its own `style` prop rather than joining the preset.
13
+ *
9
14
  * `className` is dropped from those attributes and re-declared because it is INTERNAL to `blocks/`:
10
15
  * layout props are the styling API everywhere else, and the only legitimate classes are the
11
16
  * `index.css` hooks the block components key on.
@@ -21,13 +26,16 @@
21
26
  import { type ElementType } from 'react';
22
27
  import { type ShadowToken } from '../../design-system/component-tokens';
23
28
  import { type LayoutProps } from './layoutProps';
24
- export type SurfaceBackground = 'default' | 'card';
25
- export type SurfacePadding = 'none' | 'card' | 'toast';
29
+ type SurfaceBackground = 'default' | 'card';
30
+ type SurfacePadding = 'none' | 'card' | 'toast';
31
+ type SurfaceVariant = 'floatingCard';
26
32
  export interface SurfaceProps extends LayoutProps, Omit<React.HTMLAttributes<HTMLElement>, 'className'> {
27
33
  as?: ElementType;
28
34
  background?: SurfaceBackground;
29
35
  elevation?: ShadowToken;
30
36
  paddingPreset?: SurfacePadding;
37
+ variant?: SurfaceVariant;
31
38
  className?: string;
32
39
  }
33
40
  export declare const Surface: import("react").ForwardRefExoticComponent<SurfaceProps & import("react").RefAttributes<HTMLElement>>;
41
+ export {};
@@ -14,7 +14,7 @@
14
14
  * literal union of the keys, and `satisfies` fails a malformed entry at compile time without widening the
15
15
  * value type. The bundle is a single chunk, so every entry here is unconditional weight in each host page.
16
16
  */
17
- export interface IconPath {
17
+ interface IconPath {
18
18
  d: string;
19
19
  fill?: string;
20
20
  stroke?: string;
@@ -130,3 +130,4 @@ export declare const icons: {
130
130
  };
131
131
  };
132
132
  export type IconName = keyof typeof icons;
133
+ export {};
@@ -17,10 +17,15 @@
17
17
  * `LAYOUT_KEYS` must list every key of `LayoutProps`: `stripLayoutProps` filters by that set, so a
18
18
  * layout prop missing from it reaches the DOM as an unknown attribute. `as` and `style` are in it
19
19
  * because the consuming component (`Surface`) applies them itself rather than forwarding them.
20
+ *
21
+ * `withClass(base, extra)` appends an optional caller `className` to a component's fixed base class
22
+ * (`Button`, `Icon`, `Avatar`). It is NOT the banned `cn()`: there is no variant list to merge or
23
+ * dedup, just a plain conditional concat of one fixed string and one optional string — variants stay
24
+ * on `data-*` attributes per the styling rule in `../../../CLAUDE.md`.
20
25
  */
21
26
  import type { CSSProperties, ElementType } from 'react';
22
27
  import { type RadiusToken } from '../../design-system/component-tokens';
23
- export type SpacingToken = 'none' | '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
28
+ type SpacingToken = 'none' | '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
24
29
  export declare const SPACING_SCALE: Record<SpacingToken, string>;
25
30
  declare const ALIGN: {
26
31
  readonly start: "flex-start";
@@ -60,6 +65,7 @@ export interface LayoutProps {
60
65
  width?: 'full' | 'auto';
61
66
  height?: 'full' | 'auto';
62
67
  minWidth?: '0';
68
+ minHeight?: '0';
63
69
  border?: boolean | keyof typeof BORDER_SIDE;
64
70
  rounded?: boolean | RadiusToken;
65
71
  animate?: 'spin' | 'ping' | 'pulse' | 'fadeIn' | 'none';
@@ -69,4 +75,5 @@ export interface LayoutProps {
69
75
  }
70
76
  export declare function resolveLayoutStyle(props: LayoutProps): CSSProperties;
71
77
  export declare function stripLayoutProps<T extends LayoutProps>(props: T): Omit<T, keyof LayoutProps>;
78
+ export declare const withClass: (base: string, extra?: string) => string;
72
79
  export {};
@@ -1,33 +1,10 @@
1
- /**
2
- * The widget's one notification surface: a Base UI Toast provider, the toast renderer, and the effect
3
- * that drives toasts from widget state. Base UI owns the live region, the dismiss timers, hover-to-pause
4
- * and stacking; before this the widget announced nothing to a screen reader and ran its own setTimeout.
5
- *
6
- * `NotificationList` renders every live toast and stays a component of its own because `useToastManager`
7
- * only resolves inside `Toast.Provider`; both text lines truncate through `Text`'s own prop, a toast
8
- * carrying an action lets its title wrap instead, and a toast's `type` is a free string in Base UI, so it
9
- * is narrowed inline to the three tones `notificationToneStyles` understands, anything else falling back
10
- * to `neutral`. `NotificationProvider` wraps the provider, portal and viewport — `container` is the
11
- * widget's CLOSED shadow root, since portalling to `document.body` instead would leave the injected
12
- * styles behind, and `offsetBottom` raises the viewport above the launcher when the launcher also sits
13
- * at the bottom, so the two cannot overlap. `useNotifications` re-exports Base UI's toast manager as the
14
- * one door for adding and closing toasts.
15
- *
16
- * `WidgetNotifications` renders nothing; it mirrors the `error` and `greeting` props into toasts and
17
- * closes them when the prop clears. Both use a STABLE id, so `add` upserts and a re-render cannot stack
18
- * duplicates of the same condition. The error toast carries `timeout: 0` — it stays until acted on
19
- * (dismissed or retried); only the greeting is transient.
20
- */
21
- import { Toast } from '@base-ui/react/toast';
22
1
  import React from 'react';
23
- export declare const GREETING_TIMEOUT_MS = 8000;
24
2
  export interface NotificationProviderProps {
25
3
  children?: React.ReactNode;
26
4
  container?: HTMLElement | null;
27
5
  offsetBottom?: number;
28
6
  }
29
7
  export declare const NotificationProvider: React.FC<NotificationProviderProps>;
30
- export declare const useNotifications: typeof Toast.useToastManager;
31
8
  export interface WidgetNotificationsProps {
32
9
  error?: string;
33
10
  onClearError: () => void;
@@ -15,7 +15,6 @@ import React from 'react';
15
15
  import type { ChatMessage } from '../../types';
16
16
  interface MessageItemProps {
17
17
  message: ChatMessage;
18
- index: number;
19
18
  isLastMessage: boolean;
20
19
  onScreenAccessAllow?: () => void;
21
20
  onScreenAccessDeny?: () => void;
@@ -21,7 +21,7 @@
21
21
  import React from 'react';
22
22
  import type { ChatMessage, InstructionType } from '../types';
23
23
  import { type TaskState } from './sseReducer';
24
- export interface ChatActions {
24
+ interface ChatActions {
25
25
  addMessage: (message: ChatMessage) => void;
26
26
  updateMessage: (messageId: string, updates: Partial<ChatMessage>) => void;
27
27
  removeMessage: (messageId: string) => void;
@@ -29,7 +29,7 @@ export interface ChatActions {
29
29
  clearMessages: () => void;
30
30
  messageDispatch: (content: string, mode?: InstructionType, skipUserMessage?: boolean) => Promise<void>;
31
31
  }
32
- export interface TaskActions {
32
+ interface TaskActions {
33
33
  resetTask: () => void;
34
34
  stopTask: () => Promise<void>;
35
35
  }
@@ -11,7 +11,7 @@ export interface UIState {
11
11
  currentMode: InstructionType;
12
12
  error?: string;
13
13
  }
14
- export interface UIStateActions {
14
+ interface UIStateActions {
15
15
  setActiveView: (view: WidgetView) => void;
16
16
  toggleWidget: () => void;
17
17
  closeWidget: () => void;
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import type { WidgetEvent } from '../sdk';
22
22
  import { type ChatMessage, type InstructionType } from '../types';
23
- export type TaskPhase = 'idle' | 'running' | 'stopped';
23
+ type TaskPhase = 'idle' | 'running' | 'stopped';
24
24
  export interface TaskState {
25
25
  phase: TaskPhase;
26
26
  mode?: InstructionType;
@@ -37,7 +37,7 @@ export interface SseEffect {
37
37
  mode: InstructionType;
38
38
  explanation: string;
39
39
  }
40
- export interface ReduceResult {
40
+ interface ReduceResult {
41
41
  state: SseState;
42
42
  effects: SseEffect[];
43
43
  }
@@ -2,11 +2,12 @@
2
2
  * Focus trap for the messenger panel: while `isActive`, focus starts inside `containerRef`, Tab cycles
3
3
  * within it, Escape calls `onEscape`, and on deactivation focus returns to whatever held it before.
4
4
  *
5
- * The tabbable-candidate query is `utils/dom`'s shared `TABBABLE_SELECTOR`; `activeElementIn` reads the
6
- * focused element as seen from a container's own root; `getFocusables` lists a container's visible tabbable elements; and
7
- * `useFocusTrap(containerRef, isActive, {onEscape, focusTargetRef})` focuses `focusTargetRef` (else the
8
- * first focusable), installs one capture-phase `keydown` listener on `document`, and restores focus on
9
- * the active→inactive edge.
5
+ * The tabbable candidates come from `utils/dom`'s shared `focusablesIn` (built on `TABBABLE_SELECTOR`,
6
+ * visibility and `aria-hidden` ancestry the same filter `keySimulation`'s Tab simulation uses, so the
7
+ * widget's own tab order and the host page's can't re-diverge); `activeElementIn` reads the focused
8
+ * element as seen from a container's own root; and `useFocusTrap(containerRef, isActive, {onEscape,
9
+ * focusTargetRef})` focuses `focusTargetRef` (else the first focusable), installs one capture-phase
10
+ * `keydown` listener on `document`, and restores focus on the active→inactive edge.
10
11
  *
11
12
  * Inside the widget's closed shadow root `document.activeElement` retargets to the HOST, never naming
12
13
  * an element of the widget's own tree; `activeElementIn` reads through `container.getRootNode()`
@@ -16,7 +17,7 @@
16
17
  * the customer's page. Both key arms bail unless focus is currently inside the container, since the
17
18
  * listener sits on `document` ahead of host-page handlers and an unguarded Escape would close the
18
19
  * widget mid-typing. Tab `preventDefault`s only at the two ends; `previousActiveRef` edge-triggers the
19
- * restore once on close, and `getFocusables` drops hidden/`aria-hidden` elements the selector can't express.
20
+ * restore once on close.
20
21
  */
21
22
  export declare function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, isActive: boolean, options?: {
22
23
  onEscape?: () => void;
@@ -1,5 +1,5 @@
1
- import type { WidgetPosition } from '../types';
2
- export declare function useResize(settingsWidth: string | undefined, settingsHeight: string | undefined, position: WidgetPosition, tenantScope: string, isPreviewMode: boolean): {
1
+ import type { MarketrixConfig, WidgetPosition } from '../types';
2
+ export declare function useResize(settingsWidth: string | undefined, settingsHeight: string | undefined, position: WidgetPosition, config: MarketrixConfig, isPreviewMode: boolean): {
3
3
  widthPx: string;
4
4
  heightPx: string;
5
5
  grip: {
@@ -16,7 +16,7 @@
16
16
  * at. `notInteractableReason`'s `document.body.contains` check must stay first: ShowModeService uses it as its
17
17
  * removal watchdog and keeps no identity snapshot of its own.
18
18
  */
19
- export interface ValidatedElementResult {
19
+ interface ValidatedElementResult {
20
20
  element: HTMLElement | null;
21
21
  error?: string;
22
22
  }
@@ -31,3 +31,4 @@ export declare class DomService {
31
31
  getValidatedElement(index: number): ValidatedElementResult;
32
32
  }
33
33
  export declare const domService: DomService;
34
+ export {};
@@ -18,7 +18,7 @@
18
18
  * placement takes the first of right/left/above/below that fits then clamps, its 120px height an assumption,
19
19
  * and the watchdog tests `document.body.contains` first, covering removal as well as occlusion.
20
20
  */
21
- export interface ShowModeOptions {
21
+ interface ShowModeOptions {
22
22
  element: HTMLElement;
23
23
  explanation: string;
24
24
  browserToolName: string;
@@ -49,3 +49,4 @@ export declare class ShowModeService {
49
49
  private escapeHtml;
50
50
  }
51
51
  export declare const showModeService: ShowModeService;
52
+ export {};
@@ -17,9 +17,12 @@
17
17
  * The snapshot is `{messages, currentMode, isOpen}` — chat_id, config and timestamp are deliberately excluded.
18
18
  * Reading revives `timestamp` to a `Date` and backfills a text part for messages stored before `parts` existed;
19
19
  * writing drops `videoStream` (unserializable, dead on reload), rewriting it as `Screen sharing ended`.
20
+ *
21
+ * `scopedKey(name, config)` is the one place `<name>_<tenantScope>` is assembled — the position and resize-size
22
+ * keys share it with the chat context key, so all three browser-local entries partition by tenant identically.
20
23
  */
21
24
  import type { ChatMessage, InstructionType, MarketrixConfig, ValidWidgetConfig } from '../types';
22
- export type StoredMessage = Omit<ChatMessage, 'videoStream' | 'timestamp'> & {
25
+ type StoredMessage = Omit<ChatMessage, 'videoStream' | 'timestamp'> & {
23
26
  timestamp: string;
24
27
  };
25
28
  export interface ChatSnapshot {
@@ -31,13 +34,14 @@ export type CredentialedConfig = ValidWidgetConfig & {
31
34
  mtxId: string;
32
35
  mtxKey: string;
33
36
  };
34
- export type MarketrixChatContext = Omit<ChatSnapshot, 'messages'> & {
37
+ type MarketrixChatContext = Omit<ChatSnapshot, 'messages'> & {
35
38
  chat_id: string | null;
36
39
  messages: StoredMessage[];
37
40
  config: MarketrixConfig | null;
38
41
  timestamp: number;
39
42
  };
40
43
  export declare function tenantScope(config: MarketrixConfig): string;
44
+ export declare function scopedKey(name: string, config: MarketrixConfig): string;
41
45
  export declare function readLocal(key: string): string | null;
42
46
  export declare function writeLocal(key: string, value: string): void;
43
47
  declare class StorageService {
@@ -21,7 +21,7 @@
21
21
  import { type WidgetCommand, type WidgetEvent } from '../sdk';
22
22
  export declare class StreamGaveUpError extends Error {
23
23
  }
24
- export interface StreamClientCallbacks {
24
+ interface StreamClientCallbacks {
25
25
  onMessage?: (event: WidgetEvent) => void;
26
26
  onError?: (error: Error) => void;
27
27
  }
@@ -62,3 +62,4 @@ export declare class StreamClient {
62
62
  private clearReconnectTimer;
63
63
  }
64
64
  export declare const streamClient: StreamClient;
65
+ export {};
@@ -1,15 +1,8 @@
1
- /**
2
- * The shared widget-settings fixture the config-driven tests build from: `getMockWidgetConfig(overrides)`
3
- * returns a complete, schema-valid tenant config — every rendered setting plus the `mtxId`/`mtxKey` credential,
4
- * api host and preview flag a mounted widget needs — shallow-merged with `overrides`.
5
- *
6
- * `MockWidgetConfig` widens `ValidWidgetConfig` with the four render constants (`widget_border_radius`,
7
- * `widget_font_size`, `widget_animation_duration`, `widget_fade_duration`). `ValidWidgetConfig` is built on
8
- * `WidgetRenderedSettings`, which omits them, but callers hand this fixture straight to
9
- * `WidgetSettingsDataSchema.parse()`, which demands the whole wire shape. It is `Valid`, not partial, so
10
- * `renderWidget` can hand it to `WidgetRoot` without a cast — the fixture really does set every field.
11
- */
12
- import type { ValidWidgetConfig, WidgetSettingsData } from '../types';
1
+ import type { ChatMessage, ValidWidgetConfig, WidgetSettingsData } from '../types';
2
+ export declare const flushMicrotasks: () => Promise<void>;
3
+ export declare const mountTarget: () => HTMLDivElement;
4
+ export declare function agentMessage(overrides?: Partial<ChatMessage>): ChatMessage;
13
5
  type MockWidgetConfig = ValidWidgetConfig & Pick<WidgetSettingsData, 'widget_border_radius' | 'widget_font_size' | 'widget_animation_duration' | 'widget_fade_duration'>;
14
6
  export declare function getMockWidgetConfig(overrides?: Partial<MockWidgetConfig>): MockWidgetConfig;
7
+ export declare function validSettings(overrides?: Partial<MockWidgetConfig>): WidgetSettingsData;
15
8
  export {};
@@ -11,5 +11,10 @@
11
11
  *
12
12
  * Every fill is conditional, so a real implementation — a future jsdom, or a per-test override
13
13
  * installed before this file — wins.
14
+ *
15
+ * `resetDom` is the shared body-clearing helper for tests that mount outside Testing Library's own
16
+ * render tree (so RTL's automatic per-test cleanup does not reach them) — `replaceChildren()` over
17
+ * `innerHTML = ''` avoids re-parsing a fresh, empty document fragment on every reset.
14
18
  */
15
19
  import '@testing-library/jest-dom/vitest';
20
+ export declare function resetDom(): void;
@@ -34,7 +34,7 @@ export type MarketrixConfig = Partial<WidgetRenderedSettings> & ClientOwnedConfi
34
34
  mtxApp?: number;
35
35
  isPreviewMode?: boolean;
36
36
  };
37
- export type ValidWidgetConfig = MarketrixConfig & Required<Pick<MarketrixConfig, keyof WidgetRenderedSettings>>;
37
+ export type ValidWidgetConfig = MarketrixConfig & Required<Pick<MarketrixConfig, keyof WidgetRenderedSettings | 'isPreviewMode'>>;
38
38
  export interface ChatMessage {
39
39
  id: string;
40
40
  content: string;
@@ -1,7 +1,7 @@
1
1
  import { type Root } from 'react-dom/client';
2
2
  import type { NotificationTone } from '../design-system/component-tokens';
3
3
  import type { MarketrixConfig, ValidWidgetConfig } from '../types';
4
- export interface WidgetMount {
4
+ interface WidgetMount {
5
5
  instance: Root;
6
6
  config: ValidWidgetConfig;
7
7
  container: HTMLElement;
@@ -22,3 +22,4 @@ export declare const getCurrentConfig: () => ValidWidgetConfig | null;
22
22
  export declare const showHostPageNotice: (message: string, tone?: NotificationTone) => void;
23
23
  export declare const hideHostPageNotice: () => void;
24
24
  export declare const autoInitializeWidget: (initWidget: (config: MarketrixConfig) => Promise<void>) => void;
25
+ export {};
@@ -20,7 +20,7 @@
20
20
  import type { ChatMessage, InstructionType } from '../types';
21
21
  export declare const getModeDisplayName: (mode: InstructionType) => string;
22
22
  export declare const formatMessageTime: (date: Date | undefined) => string;
23
- export interface FindMessageOptions {
23
+ interface FindMessageOptions {
24
24
  messages: ChatMessage[];
25
25
  isTaskRunning: boolean;
26
26
  currentMode: InstructionType;
@@ -40,3 +40,4 @@ export declare const SCREEN_ACCESS_PROMPT = "Can I take a look at your screen?";
40
40
  export declare const createScreenAccessRequestMessage: (mode: InstructionType | undefined, pendingContent?: string) => ChatMessage;
41
41
  export declare const createScreenshareMessage: (stream: MediaStream, mode?: InstructionType) => ChatMessage;
42
42
  export declare const createPlaceholderMessage: (mode: InstructionType) => ChatMessage;
43
+ export {};
@@ -17,8 +17,16 @@
17
17
  * both chains are climbed. Its one `try` is deliberate — the host page owns this DOM and may have patched
18
18
  * anything on it, so a poisoned element is logged with the real error and skipped rather than aborting the
19
19
  * whole indexing pass.
20
+ *
21
+ * `focusablesIn` is the one home for "which `TABBABLE_SELECTOR` matches are actually reachable" —
22
+ * `useFocusTrap` (the widget's own tree) and `keySimulation`'s Tab simulation (the host page) both call
23
+ * it so they can't re-diverge. Per WAI-ARIA, `aria-hidden="true"` removes an element (and its whole
24
+ * subtree) from the accessibility tree, so it must not receive focus — `isAriaHidden` walks ancestors,
25
+ * not just the element itself, since a hidden container hides everything under it even though none of
26
+ * those descendants carry the attribute.
20
27
  */
21
28
  export declare const WIDGET_SHADOW_HOST_CLASS = "marketrix-widget-container";
22
29
  export declare const TABBABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
30
+ export declare function focusablesIn(root: ParentNode): HTMLElement[];
23
31
  export declare function disabledReason(el: Element): string | null;
24
32
  export declare function isIndexable(el: Element | null): boolean;
@@ -23,7 +23,7 @@ export declare function isHTMLElement(element: Element | null): element is HTMLE
23
23
  export declare function isHTMLScriptElement(element: Element | null): element is HTMLScriptElement;
24
24
  declare const RENDER_CONSTANT_NAMES: readonly ["widget_border_radius", "widget_font_size", "widget_animation_duration", "widget_fade_duration"];
25
25
  export type WidgetRenderedSettings = Omit<WidgetSettingsData, (typeof RENDER_CONSTANT_NAMES)[number]>;
26
- export type WidgetSettingsResult = {
26
+ type WidgetSettingsResult = {
27
27
  settings: WidgetRenderedSettings;
28
28
  invalidFields?: undefined;
29
29
  } | {
@@ -6,7 +6,7 @@
6
6
  * narrows an unknown — a value read back out of localStorage — to one of the four, testing a list of
7
7
  * names rather than `in CORNERS`, so the keys every object inherits (`toString`, `__proto__`) are
8
8
  * rejected. `getPanelPositionStyle` turns a corner into the inline style pinning an element to it.
9
- * `getResizeGrip`, whose return type is exported as `ResizeGrip`, describes the handle on the corner
9
+ * `getResizeGrip` describes the handle on the corner
10
10
  * diagonally OPPOSITE the pinned one — the panel grows away from its anchor, so that is the only
11
11
  * corner free to move; `growX`/`growY` are the signs converting pointer delta into size delta, and
12
12
  * `cursor` is the diagonal the grip itself lies on. `getAnchorTopLeft` resolves a corner to viewport
@@ -42,7 +42,6 @@ export declare const getResizeGrip: (position: WidgetPosition) => {
42
42
  growY: number;
43
43
  cursor: string;
44
44
  };
45
- export type ResizeGrip = ReturnType<typeof getResizeGrip>;
46
45
  export declare const getAnchorTopLeft: (position: WidgetPosition, vw: number, vh: number, w: number, h: number) => {
47
46
  x: number;
48
47
  y: number;