@marketrix.ai/widget 4.0.110 → 4.0.111
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,27 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `Surface` is the canonical container primitive: a polymorphic `forwardRef` element (`as`, default
|
|
3
3
|
* `div`) that composes the shared layout-token vocabulary with a `background` token, a `SHADOW`
|
|
4
|
-
* `elevation` token and a `paddingPreset`, all emitted as inline style
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* `elevation` token and a `paddingPreset`, all emitted as inline style — the `default`/`none` lookup
|
|
5
|
+
* entries are empty, so a bare `Surface` is a plain element. `className` is dropped from the host
|
|
6
|
+
* attributes and re-declared because it is INTERNAL to `blocks/`: layout props are the styling API
|
|
7
|
+
* everywhere else, and the only legitimate classes are the `index.css` hooks the block components key on.
|
|
8
8
|
*
|
|
9
9
|
* `floatingCard` is a `variant` shorthand for the card-background/border/card-elevation/card-padding/xl-
|
|
10
10
|
* rounded/margin bundle both `HomeView`'s recent-conversation card and `ChatView`'s composer card use —
|
|
11
11
|
* the margin lives in `variantStyles` since both call sites want it, while `ChatView`'s extra
|
|
12
12
|
* `marginTop: 'auto'` stays an override on its own `style` prop rather than joining the preset.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* the caller's own `style` last, so an inline style always wins. `Flex` depends on that tail
|
|
20
|
-
* position, resolving `display` itself because `resolveLayoutStyle` is applied ahead of it.
|
|
21
|
-
*
|
|
22
|
-
* `resolveLayoutStyle` is handed the whole `props` (it reads only layout keys), while the DOM spread
|
|
23
|
-
* goes through `stripLayoutProps` — a layout token left on the props bag reaches the element as an
|
|
24
|
-
* unknown attribute.
|
|
14
|
+
* Style order is fixed and load-bearing: background → padding preset → elevation → layout props → the
|
|
15
|
+
* caller's own `style` last, so an inline style always wins; `Flex` depends on that tail position,
|
|
16
|
+
* resolving `display` itself because `resolveLayoutStyle` is applied ahead of it. `resolveLayoutStyle`
|
|
17
|
+
* is handed the whole `props` (it reads only layout keys), while the DOM spread goes through
|
|
18
|
+
* `stripLayoutProps` — a layout token left on the props bag reaches the element as an unknown attribute.
|
|
25
19
|
*/
|
|
26
20
|
import { type ElementType } from 'react';
|
|
27
21
|
import { type ShadowToken } from '../../design-system/component-tokens';
|
|
@@ -3,25 +3,23 @@
|
|
|
3
3
|
* `resolveLayoutStyle` which reduces them to a `CSSProperties` object, and `stripLayoutProps` which
|
|
4
4
|
* removes them from a props bag so the remainder can be spread onto a DOM element. `SPACING_SCALE` is
|
|
5
5
|
* the exported `SpacingToken`→pixel table, declared smallest-first so a token name orders the same way
|
|
6
|
-
* as the pixels it emits
|
|
7
|
-
* and `BORDER_SIDE` are the private lookups for the remaining token families.
|
|
6
|
+
* as the pixels it emits.
|
|
8
7
|
*
|
|
9
8
|
* Layout props resolve to a style object rather than class names: as classes they were interpolated
|
|
10
|
-
* (`p-${token}`), which no scanner could see, so a build-time safelist emitting the whole 8x7 matrix
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* (`__tests__/stylesheet-contract.test.ts` pins the pairing).
|
|
9
|
+
* (`p-${token}`), which no scanner could see, so a build-time safelist emitting the whole 8x7 matrix was
|
|
10
|
+
* the only thing keeping them alive and a missing entry failed silently at runtime. `resolveLayoutStyle`
|
|
11
|
+
* emits a property only for a prop set to a non-default value (`grow: false`, `shrink: true`, `border:
|
|
12
|
+
* false`, `rounded: false` and `animate: 'none'` deliberately emit nothing), and its `ANIMATION` values
|
|
13
|
+
* name `mtx-*` keyframes `index.css` must define.
|
|
16
14
|
*
|
|
17
15
|
* `LAYOUT_KEYS` must list every key of `LayoutProps`: `stripLayoutProps` filters by that set, so a
|
|
18
16
|
* layout prop missing from it reaches the DOM as an unknown attribute. `as` and `style` are in it
|
|
19
17
|
* because the consuming component (`Surface`) applies them itself rather than forwarding them.
|
|
20
18
|
*
|
|
21
|
-
* `withClass(base, extra)` appends an optional caller `className` to a component's fixed base class
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
19
|
+
* `withClass(base, extra)` appends an optional caller `className` to a component's fixed base class. It
|
|
20
|
+
* is NOT the banned `cn()`: there is no variant list to merge or dedup, just a plain conditional concat
|
|
21
|
+
* of one fixed string and one optional string — variants stay on `data-*` attributes per the styling
|
|
22
|
+
* rule in `../../../CLAUDE.md`.
|
|
25
23
|
*/
|
|
26
24
|
import type { CSSProperties, ElementType } from 'react';
|
|
27
25
|
import { type RadiusToken } from '../../design-system/component-tokens';
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/**
|
|
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
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* widget's own tab order and the host page's
|
|
8
|
-
*
|
|
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.
|
|
4
|
+
* `useFocusTrap(containerRef, isActive, {onEscape, focusTargetRef})` focuses `focusTargetRef` (else the
|
|
5
|
+
* first focusable), installs one capture-phase `keydown` listener on `document`, and restores focus on
|
|
6
|
+
* the active→inactive edge. The tabbable candidates come from `utils/dom`'s shared `focusablesIn`, the
|
|
7
|
+
* same filter `keySimulation`'s Tab simulation uses, so the widget's own tab order and the host page's
|
|
8
|
+
* can't re-diverge.
|
|
11
9
|
*
|
|
12
10
|
* Inside the widget's closed shadow root `document.activeElement` retargets to the HOST, never naming
|
|
13
11
|
* an element of the widget's own tree; `activeElementIn` reads through `container.getRootNode()`
|
|
14
12
|
* instead and is the ONE home for that retargeting — eslint's `no-restricted-properties` bans the bare
|
|
15
|
-
* read everywhere else. Hand-rolled on purpose: `MessengerShell` is a NON-modal panel, not a Dialog,
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* read everywhere else. Hand-rolled on purpose: `MessengerShell` is a NON-modal panel, not a Dialog, and
|
|
14
|
+
* Base UI exposes no standalone focus trap; reaching it by making the panel a Dialog would inert the
|
|
15
|
+
* customer's page. Both key arms bail unless focus is currently inside the container, since the
|
|
18
16
|
* listener sits on `document` ahead of host-page handlers and an unguarded Escape would close the
|
|
19
|
-
* widget mid-typing.
|
|
20
|
-
* restore once on close.
|
|
17
|
+
* widget mid-typing.
|
|
21
18
|
*/
|
|
22
19
|
export declare function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, isActive: boolean, options?: {
|
|
23
20
|
onEscape?: () => void;
|
package/dist/src/utils/dom.d.ts
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Predicates the agent's element index runs against the HOST page's DOM — what counts as a control and
|
|
3
|
-
* whether it is reachable
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* whether it is reachable. `TABBABLE_SELECTOR` is the one tab-order candidate query: `send_keys`'s Tab
|
|
4
|
+
* simulation walks the host page with it and `useFocusTrap` the widget's own tree, and they must agree
|
|
5
|
+
* on what the browser would focus next. `WIDGET_SHADOW_HOST_CLASS`, set by `bootstrap` on the shadow
|
|
6
|
+
* host, lets `DomService` recognise its own overlay chrome instead of reporting it as obscuring the host
|
|
7
|
+
* page.
|
|
7
8
|
*
|
|
8
|
-
* `ancestry` walks element → `parentElement`, crossing each shadow boundary at its host
|
|
9
|
-
* `parentElement` walk stops dead at a `ShadowRoot
|
|
10
|
-
*
|
|
11
|
-
* `aria-disabled`, or an `inert` ancestor) as a sentence fragment completing `DomService`'s
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* anything on it, so a poisoned element is logged with the real error and skipped rather than aborting the
|
|
19
|
-
* whole indexing pass.
|
|
9
|
+
* `ancestry` walks element → `parentElement`, crossing each shadow boundary at its host, since a bare
|
|
10
|
+
* `parentElement` walk stops dead at a `ShadowRoot` and a control inside a host-page web component would
|
|
11
|
+
* read as top-level. `disabledReason` names why an element cannot be operated (disabled control,
|
|
12
|
+
* `aria-disabled`, or an `inert` ancestor) as a sentence fragment completing `DomService`'s `Element
|
|
13
|
+
* <n> …` message — reword both together. `isIndexable` is `DomService`'s geometry-aware fallback after
|
|
14
|
+
* its cheap selector/handler checks; visibility there climbs both the `overflow: hidden|clip` chain
|
|
15
|
+
* (that walk stops at `document.body`) and the shadow-host size, since either can hide an element
|
|
16
|
+
* despite a non-zero rect. Its one `try` is deliberate — the host page owns this DOM and may have
|
|
17
|
+
* patched anything on it, so a poisoned element is logged with the real error and skipped rather than
|
|
18
|
+
* aborting the whole indexing pass.
|
|
20
19
|
*
|
|
21
20
|
* `focusablesIn` is the one home for "which `TABBABLE_SELECTOR` matches are actually reachable" —
|
|
22
|
-
* `useFocusTrap`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* those descendants carry the attribute.
|
|
21
|
+
* `useFocusTrap` and `keySimulation`'s Tab simulation both call it so they can't re-diverge.
|
|
22
|
+
* `isAriaHidden` walks ancestors, not just the element itself, since a hidden container hides everything
|
|
23
|
+
* under it (per WAI-ARIA, `aria-hidden="true"` removes an element and its whole subtree from the
|
|
24
|
+
* accessibility tree) even though none of those descendants carry the attribute.
|
|
27
25
|
*/
|
|
28
26
|
export declare const WIDGET_SHADOW_HOST_CLASS = "marketrix-widget-container";
|
|
29
27
|
export declare const TABBABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
|