@marketrix.ai/widget 4.0.123 → 4.0.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/components/base/Flex.d.ts +1 -1
- package/dist/src/components/base/Surface.d.ts +6 -0
- package/dist/src/components/blocks/WidgetFab.d.ts +5 -2
- package/dist/src/components/chat/MessageItem.d.ts +1 -1
- package/dist/src/context/ChatContext.d.ts +6 -0
- package/dist/src/context/UIStateContext.d.ts +6 -8
- package/dist/src/context/sseReducer.d.ts +2 -2
- package/dist/src/design-system/component-tokens.d.ts +5 -0
- package/dist/src/design-system/semantic-tokens.d.ts +9 -0
- package/dist/src/hooks/useLatest.d.ts +1 -0
- package/dist/src/hooks/useWidget.d.ts +6 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/services/BrowserToolService.d.ts +4 -0
- package/dist/src/services/ChatService.d.ts +2 -2
- package/dist/src/services/ShowModeService.d.ts +6 -0
- package/dist/src/services/StorageService.d.ts +9 -4
- package/dist/src/services/StreamClient.d.ts +5 -0
- package/dist/src/types/index.d.ts +4 -3
- package/dist/src/utils/chat.d.ts +8 -3
- package/dist/src/utils/color.d.ts +12 -6
- package/dist/src/utils/validation.d.ts +2 -2
- package/dist/widget.mjs +64 -64
- package/package.json +3 -2
|
@@ -16,7 +16,7 @@ interface FlexProps extends SurfaceProps {
|
|
|
16
16
|
direction?: 'row' | 'column';
|
|
17
17
|
children?: ReactNode;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
type StackProps = Omit<FlexProps, 'direction'>;
|
|
20
20
|
export declare const Flex: import("react").ForwardRefExoticComponent<FlexProps & import("react").RefAttributes<HTMLElement>>;
|
|
21
21
|
export declare const Stack: import("react").ForwardRefExoticComponent<StackProps & import("react").RefAttributes<HTMLElement>>;
|
|
22
22
|
export {};
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* resolving `display` itself because `resolveLayoutStyle` is applied ahead of it. `resolveLayoutStyle`
|
|
17
17
|
* is handed the whole `props` (it reads only layout keys), while the DOM spread goes through
|
|
18
18
|
* `stripLayoutProps` — a layout token left on the props bag reaches the element as an unknown attribute.
|
|
19
|
+
*
|
|
20
|
+
* `forwardRef<HTMLElement, SurfaceProps>` is fixed, not generic per `as`: `forwardRef` cannot be made
|
|
21
|
+
* generic across call sites without its own internal cast, so a caller holding a `RefObject` typed to
|
|
22
|
+
* its specific element (`HTMLDivElement`, …) casts at the call site instead — `RefObject.current` is
|
|
23
|
+
* mutable and therefore invariant, so no subtyping relationship lets a `RefObject<HTMLDivElement>` stand
|
|
24
|
+
* in for `Ref<HTMLElement>` without one. `WidgetFab.tsx`, `MessageList.tsx` (×2) are the three sites.
|
|
19
25
|
*/
|
|
20
26
|
import { type ElementType } from 'react';
|
|
21
27
|
import { type ShadowToken } from '../../design-system/component-tokens';
|
|
@@ -13,12 +13,15 @@
|
|
|
13
13
|
* unify both). Pointer state is tracked in a ref; movement under DRAG_THRESHOLD_PX stays a click, beyond
|
|
14
14
|
* it the wrapper is translated on a rAF loop with velocity sampled into `velocityHistoryRef` so a flick
|
|
15
15
|
* lands where it was heading — `projectFlickVelocity` (module-level, pure) turns that sample history into
|
|
16
|
-
* a projected pixel delta
|
|
16
|
+
* a projected pixel delta: zero with fewer than two samples, else the average px/ms over the sampled span
|
|
17
|
+
* projected forward in px/s. On release
|
|
17
18
|
* `getNearestCornerByTranslation` picks the corner, the wrapper animates there for SNAP_DURATION_MS via
|
|
18
19
|
* `left`/`top` transitions, and `commitPositionAfterAnimation` calls `onPositionCommit` on
|
|
19
20
|
* `transitionend` (with a timeout fallback, since a hidden tab fires no transition events) — the
|
|
20
21
|
* committed corner is the one being animated TO, so two snaps in flight cannot commit the abandoned one
|
|
21
|
-
* (`abandonSnapRef`)
|
|
22
|
+
* (`abandonSnapRef`), which the unmount effect also calls so a snap animating when the widget is torn
|
|
23
|
+
* down does not leave its `transitionend` listener and fallback timer running past the component's life.
|
|
24
|
+
* `suppressUntilRef` stamps a time after which a click may open the widget again,
|
|
22
25
|
* so the pointer-up that ends a drag is not read as a tap. The wrapper is measured with a
|
|
23
26
|
* ResizeObserver in a layout effect so the pixel position is right on the first paint; preview mode
|
|
24
27
|
* disables everything. Exported so `WidgetFab.test.tsx`'s `renderHook` case can drive it directly.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* more work is coming; a message with no parts at all falls back to a bare `Surface`.
|
|
22
22
|
*/
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import type
|
|
24
|
+
import { type ChatMessage } from '../../types';
|
|
25
25
|
interface MessageItemProps {
|
|
26
26
|
message: ChatMessage;
|
|
27
27
|
isLastMessage: boolean;
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
* which carries no task id. Every failure on the tool and stop paths reaches `uiActions.setError` as well
|
|
18
18
|
* as the console: an undelivered `tool/response` leaves the agent waiting on a reply that never comes, so
|
|
19
19
|
* the run stalls with nothing on screen unless the visitor is told, and `do` mode may still be clicking.
|
|
20
|
+
*
|
|
21
|
+
* `event.type === 'task/status' && isTerminalTaskStatus(event.status)` reads `event.status` on every
|
|
22
|
+
* branch, but only the `task/status` variant of `WidgetEvent` carries a `status` field at all — on any
|
|
23
|
+
* other event it is `undefined`, which `isTerminalTaskStatus` (an `in` check against the status map)
|
|
24
|
+
* always reports as non-terminal. The `&&` can never observably differ from an `||` here; it stays `&&`
|
|
25
|
+
* because that is what a reader expects a type-narrowing guard to say.
|
|
20
26
|
*/
|
|
21
27
|
import React from 'react';
|
|
22
28
|
import type { ChatMessage, InstructionType } from '../types';
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `UIStateProvider` / `useUIStateContext` — the widget's view state: open/closed, active view, current
|
|
3
3
|
* mode (tell/show/do) and the error banner. Actions are stable (memoised once) so consumers can depend
|
|
4
|
-
* on them without re-rendering; `applyState` merges a partial for restore-from-storage.
|
|
4
|
+
* on them without re-rendering; `applyState` merges a partial for restore-from-storage. `UIState` is a
|
|
5
|
+
* `Pick` of the public `WidgetState` (`../types`) rather than its own duplicate shape, and stays
|
|
6
|
+
* unexported — it never needs to be named outside this file, and `applyState`'s declaration-file
|
|
7
|
+
* emission resolves through the already-exported `WidgetState` instead.
|
|
5
8
|
*/
|
|
6
9
|
import React from 'react';
|
|
7
|
-
import type { InstructionType, WidgetView } from '../types';
|
|
8
|
-
|
|
9
|
-
isOpen: boolean;
|
|
10
|
-
activeView: WidgetView;
|
|
11
|
-
currentMode: InstructionType;
|
|
12
|
-
error?: string | undefined;
|
|
13
|
-
}
|
|
10
|
+
import type { InstructionType, WidgetState, WidgetView } from '../types';
|
|
11
|
+
type UIState = Pick<WidgetState, 'isOpen' | 'activeView' | 'currentMode' | 'error'>;
|
|
14
12
|
interface UIStateActions {
|
|
15
13
|
setActiveView: (view: WidgetView) => void;
|
|
16
14
|
toggleWidget: () => void;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* closed is noise, which is what a duplicated `chat/response` looks like.
|
|
25
25
|
*/
|
|
26
26
|
import type { WidgetEvent } from '../sdk';
|
|
27
|
-
import {
|
|
27
|
+
import type { ChatMessage, InstructionType } from '../types';
|
|
28
28
|
type TaskPhase = 'idle' | 'running' | 'stopped';
|
|
29
29
|
export interface TaskState {
|
|
30
30
|
phase: TaskPhase;
|
|
@@ -42,7 +42,7 @@ export interface SseEffect {
|
|
|
42
42
|
mode: InstructionType;
|
|
43
43
|
explanation: string;
|
|
44
44
|
}
|
|
45
|
-
interface ReduceResult {
|
|
45
|
+
export interface ReduceResult {
|
|
46
46
|
state: SseState;
|
|
47
47
|
effects: SseEffect[];
|
|
48
48
|
}
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* no two tokens are synonyms. Per-tenant values are NOT here: `semantic-tokens.ts` owns everything derived
|
|
7
7
|
* from widget settings, and this file is only what no tenant can change.
|
|
8
8
|
*
|
|
9
|
+
* Every `notificationToneStyles` colour is fixed (no tenant setting touches a toast), so each pair is
|
|
10
|
+
* measured once here against the WCAG threshold it actually needs — `closeColor` is a UI icon (3:1
|
|
11
|
+
* against `background`), `titleColor`/`bodyColor` are text (4.5:1) — and a test pins every ratio so a
|
|
12
|
+
* future palette edit can't silently regress below it.
|
|
13
|
+
*
|
|
9
14
|
* `LAYER_TOKENS` is the z-index ladder (screen-edge glow < panel < dialog < toast), based just above the
|
|
10
15
|
* 2^31-ish ceiling most host pages use so the widget sits over everything without the values overflowing a
|
|
11
16
|
* 32-bit int. `showHighlight`/`showPopup` are a separate, much higher pair near the int32 ceiling: Show
|
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* settings object against those defaults and derives the muted/faint/hover/contrast variants;
|
|
11
11
|
* `semanticTokensToCssCustomProperties`, the token → `--var` map.
|
|
12
12
|
*
|
|
13
|
+
* `color.ring` is NOT the raw accent — a customer's `widget_accent_color` has no contrast guarantee
|
|
14
|
+
* against whatever it sits next to (WCAG 2.4.11/1.4.11 need the focus indicator ≥3:1 against the colours
|
|
15
|
+
* adjacent to it on both sides), so it is `getContrastingColor(widget_background_color)`, the same
|
|
16
|
+
* black/white pick `primaryForeground`/`secondaryForeground` use. `index.css` pairs it with
|
|
17
|
+
* `--ring-offset` (the background colour itself) as a two-tone ring: an inset halo matching the surface,
|
|
18
|
+
* then the ring outside it, so both sides of the ring measure against the one colour it is guaranteed to
|
|
19
|
+
* clear against, whatever the outlined control's own colour is.
|
|
20
|
+
*
|
|
13
21
|
* Radius and both durations are fixed rather than per-tenant: every widget row in production holds these
|
|
14
22
|
* values and no surface writes them. Settings are filtered for explicit `undefined` before merging —
|
|
15
23
|
* a plain spread would let an `undefined` key shadow its default instead of falling back to it. The
|
|
@@ -31,6 +39,7 @@ type SemanticTokens = {
|
|
|
31
39
|
secondaryForeground: string;
|
|
32
40
|
secondaryBg: string;
|
|
33
41
|
secondaryHover: string;
|
|
42
|
+
ring: string;
|
|
34
43
|
};
|
|
35
44
|
radius: string;
|
|
36
45
|
motion: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useLatest<T>(value: T): React.RefObject<T>;
|
|
@@ -29,6 +29,11 @@ export declare const useWidget: () => {
|
|
|
29
29
|
closeWidget: () => void;
|
|
30
30
|
setMode: (mode: import("..").InstructionType) => void;
|
|
31
31
|
setError: (error: string | undefined) => void;
|
|
32
|
-
applyState: (payload: Partial<
|
|
32
|
+
applyState: (payload: Partial<{
|
|
33
|
+
error?: string | undefined | undefined;
|
|
34
|
+
currentMode: import("..").InstructionType;
|
|
35
|
+
isOpen: boolean;
|
|
36
|
+
activeView: import("../types").WidgetView;
|
|
37
|
+
}>) => void;
|
|
33
38
|
};
|
|
34
39
|
};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* dashboard wrapper and the script-tag auto-init hook. `README.md` is the customer-facing surface these
|
|
4
4
|
* exports make up, named and default alike. `initWidget` is the guarded, coalescing production entry over
|
|
5
5
|
* `initWidgetInternal`; `mount` builds the shadow-DOM container; `unmountWidget` tears down stream,
|
|
6
|
-
* recorder, screen share and
|
|
6
|
+
* recorder, screen share, any in-flight show-mode overlay (which owns host-page listeners and DOM
|
|
7
|
+
* nodes outside the shadow root, so it does not go with `active.instance.unmount()`) and tree;
|
|
7
8
|
* `updateMarketrixConfig` re-mounts with client settings merged in, on whichever path the current mount
|
|
8
9
|
* came from; `mountWidget` dispatches on shape — `settings` → preview (no network), credentials → live.
|
|
9
10
|
*
|
|
@@ -38,7 +39,7 @@ export { getCurrentConfig };
|
|
|
38
39
|
export declare const MarketrixWidgetPreview: React.FC<MarketrixWidgetPreviewProps>;
|
|
39
40
|
export declare const mountWidget: (config: AddWidgetConfig) => Promise<void>;
|
|
40
41
|
export type { InstructionType } from './sdk';
|
|
41
|
-
export type { AddWidgetConfig, ChatMessage, ClientOwnedConfig, MarketrixConfig, MarketrixWidgetPreviewProps, WidgetState, } from './types';
|
|
42
|
+
export type { AddWidgetConfig, ChatMessage, ClientOwnedConfig, MarketrixConfig, MarketrixWidgetPreviewProps, WidgetSettingsData, WidgetState, } from './types';
|
|
42
43
|
declare const _default: {
|
|
43
44
|
MarketrixWidgetPreview: React.FC<MarketrixWidgetPreviewProps>;
|
|
44
45
|
mountWidget: (config: AddWidgetConfig) => Promise<void>;
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
* same failure. `httpUrl` admits only http(s) — `extract` feeds the model page-controlled hrefs, so a raw
|
|
18
18
|
* target would let `javascript:` run in the HOST origin; its bare catch is the same verdict as a rejected
|
|
19
19
|
* protocol, an unparseable string being exactly a value that is not a URL.
|
|
20
|
+
*
|
|
21
|
+
* `scrollToText`'s walker only ever yields a Text node from inside `document.body`'s tree, so
|
|
22
|
+
* `node.parentElement` is never null there — the optional-chained read is for TypeScript, not a runtime
|
|
23
|
+
* branch this loop can take.
|
|
20
24
|
*/
|
|
21
25
|
import type { InstructionType } from '../types';
|
|
22
26
|
interface TextData {
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* That is why `StreamClient.ready` must resolve BEFORE the POST: registration is what gives the reply
|
|
8
8
|
* somewhere to land.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* `ChatService` never files the `widget_question` activity-log row itself: `StreamClient` sends `user_id`
|
|
11
11
|
* once, at `widgetStream` registration, and the api derives the row from `chat_id`'s bound application on
|
|
12
|
-
* every Tell/Show/Do command, so
|
|
12
|
+
* every Tell/Show/Do command, so no per-message credential re-send is needed here.
|
|
13
13
|
*/
|
|
14
14
|
import type { InstructionType } from '../sdk';
|
|
15
15
|
export declare function chatPost(message: string, mode: InstructionType, requestId: string): Promise<void>;
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
* `ACCENT_COLOR`/`TEXT_COLOR` are raw literals rather than design-system tokens: the highlight and popup
|
|
21
21
|
* mount to `document.body` on the HOST page, outside the shadow root, so `index.css`'s `:host`-scoped
|
|
22
22
|
* CSS custom properties never reach them.
|
|
23
|
+
*
|
|
24
|
+
* `trackElement`'s `!this.currentElement || !this.currentHighlight` and the click handler's
|
|
25
|
+
* `!this.currentElement || !this.resolvePromise` cannot observe a mixed state: `showToolAction` sets
|
|
26
|
+
* every one of these fields together and `cleanup` clears every one of them together, so within a
|
|
27
|
+
* single stage they are always all-null or all-set. The guards stay as defensive redundancy against a
|
|
28
|
+
* future edit that breaks that pairing, not because either can independently be null today.
|
|
23
29
|
*/
|
|
24
30
|
interface ShowModeOptions {
|
|
25
31
|
element: HTMLElement;
|
|
@@ -15,18 +15,23 @@
|
|
|
15
15
|
* another's.
|
|
16
16
|
*
|
|
17
17
|
* The chat snapshot is `{messages, currentMode, isOpen}` — chat_id, config and timestamp are deliberately
|
|
18
|
-
* excluded.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* excluded. `StoredMessage` is the ONE place `content` still exists as a field: a live `ChatMessage` has
|
|
19
|
+
* none (every reader derives `messageText(parts)` instead), but a transcript written before `parts`
|
|
20
|
+
* existed has only `content` on disk, so `readChatSnapshot` backfills a text part from it and
|
|
21
|
+
* `writeChatSnapshot` derives `content` back from `parts` on the way out, keeping the persisted shape
|
|
22
|
+
* readable by an older widget version without carrying the redundant field in memory. Reading also
|
|
23
|
+
* revives `timestamp` to a `Date`; writing drops `videoStream` (unserializable, dead on reload),
|
|
24
|
+
* rewriting it as "Screen sharing ended".
|
|
21
25
|
*
|
|
22
26
|
* `sanitizeStoredContext` is hand-rolled, not zod, per the package-level rule that a schema imported as a
|
|
23
27
|
* VALUE anywhere reachable from `src/index.tsx` pulls zod's whole runtime into the bundle. Each field
|
|
24
28
|
* falls back to `DEFAULT_CONTEXT`'s value individually, so a partially-corrupt payload keeps the fields
|
|
25
29
|
* that DID parse rather than discarding the whole context.
|
|
26
30
|
*/
|
|
27
|
-
import type
|
|
31
|
+
import { type ChatMessage, type InstructionType, type MarketrixConfig, type ValidWidgetConfig } from '../types';
|
|
28
32
|
type StoredMessage = Omit<ChatMessage, 'videoStream' | 'timestamp'> & {
|
|
29
33
|
timestamp: string;
|
|
34
|
+
content: string;
|
|
30
35
|
};
|
|
31
36
|
export interface ChatSnapshot {
|
|
32
37
|
messages: ChatMessage[];
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* read by a visitor on a customer's page, so they name the state and the way out rather than the counter, and
|
|
18
18
|
* `giveUp` needs no console line of its own for the same reason. A dial or stream that will be retried warns;
|
|
19
19
|
* only the rejected credential is an error, being the one failure nothing here recovers from.
|
|
20
|
+
*
|
|
21
|
+
* `send` never turns its own POST failure into a user-facing `onError` — the raw failure (network cause, a
|
|
22
|
+
* 4xx/5xx body) goes only to `logWarn`, since every caller already reports its own human sentence on the
|
|
23
|
+
* same catch (`ChatContext`'s message/tool-response/stop paths); notifying here too would have shown the
|
|
24
|
+
* caller's visitor a second, raw-text toast racing the first.
|
|
20
25
|
*/
|
|
21
26
|
import { type WidgetCommand, type WidgetEvent } from '../sdk';
|
|
22
27
|
export declare class StreamGaveUpError extends Error {
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
* `ChatMessage.pendingContent` queues a message behind an open screen-access request, sent once it
|
|
16
16
|
* resolves. A `streaming` `MessagePart` accumulates `chat/delta` fragments until the final
|
|
17
17
|
* `chat/response` replaces it. `taskStatus`/`MessagePart.status` are presentational only, not the wire
|
|
18
|
-
* vocabulary (`task/status.status`). `messageText` joins text parts and IS the text
|
|
19
|
-
*
|
|
18
|
+
* vocabulary (`task/status.status`). `messageText` joins text parts and IS the text — `ChatMessage` has
|
|
19
|
+
* no `content` field of its own; a render site calls `messageText(msg.parts)` directly. The one
|
|
20
|
+
* exception is `StorageService`'s persisted `StoredMessage`, which keeps its own `content` string to
|
|
21
|
+
* migrate a transcript stored before `parts` existed — see that file's header.
|
|
20
22
|
*/
|
|
21
23
|
import type { InstructionType, WidgetSettingsData } from '../sdk';
|
|
22
24
|
import type { WidgetRenderedSettings } from '../utils/validation';
|
|
@@ -37,7 +39,6 @@ export type MarketrixConfig = Partial<WidgetRenderedSettings> & ClientOwnedConfi
|
|
|
37
39
|
export type ValidWidgetConfig = MarketrixConfig & Required<Pick<MarketrixConfig, keyof WidgetRenderedSettings | 'isPreviewMode'>>;
|
|
38
40
|
export interface ChatMessage {
|
|
39
41
|
id: string;
|
|
40
|
-
content: string;
|
|
41
42
|
sender: 'user' | 'agent';
|
|
42
43
|
timestamp: Date;
|
|
43
44
|
mode?: InstructionType | undefined;
|
package/dist/src/utils/chat.d.ts
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* `lastIndexWhere` (also used by `useScreenShare`), and `addProgressLine` / `markProgressLineComplete` /
|
|
4
4
|
* `markProgressLineFailed`, which append or settle the open progress part for one `browserToolName` via
|
|
5
5
|
* `openLineFor` and the shared `patchPart` copy-on-write. `createMessage` and its per-sender constructors are
|
|
6
|
-
* the ONLY way a `ChatMessage` is built: ids are `<prefix>-<uuid>` since two messages minted in
|
|
7
|
-
*
|
|
6
|
+
* the ONLY way a `ChatMessage` is built: ids are `<prefix>-<uuid>` since two messages minted in the same millisecond
|
|
7
|
+
* would otherwise collide, and empty content yields no `text` part, the screen-share bubble rendering from `videoStream`
|
|
8
8
|
* alone and a placeholder having nothing to say yet. `SCREEN_ACCESS_PROMPT` is the one wording of the
|
|
9
9
|
* screen-access ask, the transcript card and the toolbar dialog being two renderings of one question.
|
|
10
|
+
* `CHAT_FAILURE_TEXT` is the one human sentence for "the assistant could not process that turn" —
|
|
11
|
+
* `ChatContext`'s message-post catch and `sseReducer`'s `chat/error` case both settle a bubble with it
|
|
12
|
+
* rather than the raw POST failure or the raw server `error` string, which may carry request/response
|
|
13
|
+
* internals a visitor must never see.
|
|
10
14
|
*
|
|
11
15
|
* `findMessageForProgress` picks the agent reply a `tool/call` or progress event renders into, by ranked
|
|
12
16
|
* predicates: the first rank matching anything wins, within a rank the newest message, and no match at all is a
|
|
@@ -37,7 +41,8 @@ export declare const createUserMessage: (content: string, mode?: InstructionType
|
|
|
37
41
|
export declare const createAgentMessage: (content: string) => ChatMessage;
|
|
38
42
|
export declare const createSystemMessage: (content: string, idPrefix: string) => ChatMessage;
|
|
39
43
|
export declare const SCREEN_ACCESS_PROMPT = "Can I take a look at your screen?";
|
|
44
|
+
export declare const CHAT_FAILURE_TEXT = "I'm sorry, I encountered an error processing your request. Please try again.";
|
|
40
45
|
export declare const createScreenAccessRequestMessage: (mode: InstructionType | undefined, pendingContent?: string) => ChatMessage;
|
|
41
|
-
export declare const createScreenshareMessage: (stream: MediaStream
|
|
46
|
+
export declare const createScreenshareMessage: (stream: MediaStream) => ChatMessage;
|
|
42
47
|
export declare const createPlaceholderMessage: (mode: InstructionType) => ChatMessage;
|
|
43
48
|
export {};
|
|
@@ -6,12 +6,17 @@
|
|
|
6
6
|
* `rgb()`/`rgba()` string into channels, and returns null for anything else. Only those two notations are
|
|
7
7
|
* read: a named colour, `hsl()` or a `var(--…)` custom property is unreadable here by design, and a channel
|
|
8
8
|
* above 255 is refused rather than clamped, so a malformed setting never silently becomes a valid colour.
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
9
|
+
* `contrastRatio` is the one home for the WCAG formula — relative luminance is sRGB gamma-decoded per
|
|
10
|
+
* channel, weighted .2126/.7152/.0722, and the ratio is `(lighter + 0.05) / (darker + 0.05)`.
|
|
11
|
+
* `getContrastingColor` picks whichever of black or white scores higher against it: this is the single
|
|
12
|
+
* place a tenant colour without its own paired foreground setting (a button's accent, a status pill)
|
|
13
|
+
* gets one synthesized, and comparing the two ratios directly (rather than a `luminance > 0.5` split,
|
|
14
|
+
* whose crossover sits at ≈0.179, not 0.5) means every synthesized foreground clears the AA 4.5:1
|
|
15
|
+
* threshold by construction — the higher of the two ratios is never below ~4.6:1. An unreadable
|
|
16
|
+
* background falls back to BLACK, never white: tenant surfaces skew light, so black stays legible where
|
|
17
|
+
* white would vanish. `addOpacity` re-emits a colour as `rgba()` at the given alpha and passes an
|
|
18
|
+
* unreadable one through UNCHANGED — it stays a CSS value the browser can still resolve, where an
|
|
19
|
+
* `rgba(NaN, …)` would render nothing.
|
|
15
20
|
*
|
|
16
21
|
* `backgroundGradient` is the one home for `widget_background_color` as a `backgroundImage`: the setting may
|
|
17
22
|
* already be a gradient, which is legal only as `backgroundImage`, so a flat colour is emitted as a same-stop
|
|
@@ -24,6 +29,7 @@ type Rgb = {
|
|
|
24
29
|
b: number;
|
|
25
30
|
};
|
|
26
31
|
export declare function toRgb(color: string): Rgb | null;
|
|
32
|
+
export declare function contrastRatio(a: string, b: string): number | null;
|
|
27
33
|
export declare function getContrastingColor(color: string): string;
|
|
28
34
|
export declare function addOpacity(color: string, opacity: number): string;
|
|
29
35
|
export declare function backgroundGradient(color: string): string;
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* key — and `RENDER_CONSTANT_NAMES` mirrors api's `WIDGET_RENDER_CONSTANTS` by hand under the same check.
|
|
15
15
|
*
|
|
16
16
|
* `parseWidgetSettings` PICKS as well as validates: a widget's settings arrive carrying the render constants and the
|
|
17
|
-
* result is spread into the widget config, so unknown keys passing through would leak them where zod
|
|
18
|
-
* them. Render constants stay guarded, since a legacy bundle's stored value must keep passing, but are dropped
|
|
17
|
+
* result is spread into the widget config, so unknown keys passing through would leak them where a zod-parsed
|
|
18
|
+
* object would drop them. Render constants stay guarded, since a legacy bundle's stored value must keep passing, but are dropped
|
|
19
19
|
* from the picked result, since nothing renders them.
|
|
20
20
|
*/
|
|
21
21
|
import type { WidgetSettingsData } from '../sdk';
|