@ai-matrx/design-system 0.37.1 → 0.38.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.
- package/CHANGELOG.md +21 -0
- package/dist/content-transfer.cjs +84 -18
- package/dist/content-transfer.cjs.map +1 -1
- package/dist/content-transfer.js +84 -18
- package/dist/content-transfer.js.map +1 -1
- package/dist/data-table/data-row-inspector.cjs +84 -18
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js +86 -20
- package/dist/data-table/data-row-inspector.js.map +1 -1
- package/dist/data-table/data-row-window.cjs +84 -18
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js +86 -20
- package/dist/data-table/data-row-window.js.map +1 -1
- package/dist/data-table/index.cjs +85 -19
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.js +181 -115
- package/dist/data-table/index.js.map +1 -1
- package/dist/index.cjs +84 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +94 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -792,6 +792,20 @@ declare function CreatablePicker({ value, options, onSelect, placeholder, search
|
|
|
792
792
|
* `aria-describedby` is dropped when there is no description rather than
|
|
793
793
|
* pointing at nothing.
|
|
794
794
|
*
|
|
795
|
+
* 6. ON DESKTOP A DIALOG IS A WINDOW, NOT A WALL (0.38.0, Arman 2026-09-23:
|
|
796
|
+
* "none of the built-in page ai integrations are accessible because the
|
|
797
|
+
* page is totally blocked"). Unless the caller passes `modal`, a desktop
|
|
798
|
+
* dialog does not block the page: no overlay, the page, the Agents menu,
|
|
799
|
+
* the assist dock and right-click AI stay usable beside it. It behaves like
|
|
800
|
+
* a window: a click outside never closes it (`dismissOnOutsideClick` opts a
|
|
801
|
+
* quick picker back in), Escape closes it only while focus is inside it
|
|
802
|
+
* (Escape in the page belongs to the page), and its `DialogHeader` drags
|
|
803
|
+
* it, clamped on screen, double-click to recenter. On a phone it stays the
|
|
804
|
+
* blocking bottom sheet — nothing useful sits behind a sheet. Confirmations
|
|
805
|
+
* are `AlertDialog`, a different component, and stay blocking. This is a
|
|
806
|
+
* LIGHT window: the host's heavy window manager (tray, persistence) is a
|
|
807
|
+
* separate system and must not be pulled into every dialog.
|
|
808
|
+
*
|
|
795
809
|
* SEAM INVERSIONS. The host original resolved its portal target through
|
|
796
810
|
* app-shaped hooks (a popped-out window-panel body). Here that is the
|
|
797
811
|
* package's `PortalContainerProvider` seam, with an explicit `container` prop
|
|
@@ -828,6 +842,13 @@ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitiv
|
|
|
828
842
|
*/
|
|
829
843
|
declare const DialogContentPrimitive: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
830
844
|
interface DialogContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
|
|
845
|
+
/**
|
|
846
|
+
* Windowed (non-blocking) dialogs never close from a click outside them —
|
|
847
|
+
* the person is reaching for the page or an AI control beside the window.
|
|
848
|
+
* Pass `true` for a quick picker that should close when the person clicks
|
|
849
|
+
* away. Ignored on a blocking dialog, which keeps Radix's behaviour.
|
|
850
|
+
*/
|
|
851
|
+
dismissOnOutsideClick?: boolean;
|
|
831
852
|
/** Render as a bottom sheet below the mobile breakpoint. Default `true`. */
|
|
832
853
|
mobileSheet?: boolean;
|
|
833
854
|
/** Render the built-in close control. Default `true`. */
|
package/dist/index.d.ts
CHANGED
|
@@ -792,6 +792,20 @@ declare function CreatablePicker({ value, options, onSelect, placeholder, search
|
|
|
792
792
|
* `aria-describedby` is dropped when there is no description rather than
|
|
793
793
|
* pointing at nothing.
|
|
794
794
|
*
|
|
795
|
+
* 6. ON DESKTOP A DIALOG IS A WINDOW, NOT A WALL (0.38.0, Arman 2026-09-23:
|
|
796
|
+
* "none of the built-in page ai integrations are accessible because the
|
|
797
|
+
* page is totally blocked"). Unless the caller passes `modal`, a desktop
|
|
798
|
+
* dialog does not block the page: no overlay, the page, the Agents menu,
|
|
799
|
+
* the assist dock and right-click AI stay usable beside it. It behaves like
|
|
800
|
+
* a window: a click outside never closes it (`dismissOnOutsideClick` opts a
|
|
801
|
+
* quick picker back in), Escape closes it only while focus is inside it
|
|
802
|
+
* (Escape in the page belongs to the page), and its `DialogHeader` drags
|
|
803
|
+
* it, clamped on screen, double-click to recenter. On a phone it stays the
|
|
804
|
+
* blocking bottom sheet — nothing useful sits behind a sheet. Confirmations
|
|
805
|
+
* are `AlertDialog`, a different component, and stay blocking. This is a
|
|
806
|
+
* LIGHT window: the host's heavy window manager (tray, persistence) is a
|
|
807
|
+
* separate system and must not be pulled into every dialog.
|
|
808
|
+
*
|
|
795
809
|
* SEAM INVERSIONS. The host original resolved its portal target through
|
|
796
810
|
* app-shaped hooks (a popped-out window-panel body). Here that is the
|
|
797
811
|
* package's `PortalContainerProvider` seam, with an explicit `container` prop
|
|
@@ -828,6 +842,13 @@ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitiv
|
|
|
828
842
|
*/
|
|
829
843
|
declare const DialogContentPrimitive: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
830
844
|
interface DialogContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
|
|
845
|
+
/**
|
|
846
|
+
* Windowed (non-blocking) dialogs never close from a click outside them —
|
|
847
|
+
* the person is reaching for the page or an AI control beside the window.
|
|
848
|
+
* Pass `true` for a quick picker that should close when the person clicks
|
|
849
|
+
* away. Ignored on a blocking dialog, which keeps Radix's behaviour.
|
|
850
|
+
*/
|
|
851
|
+
dismissOnOutsideClick?: boolean;
|
|
831
852
|
/** Render as a bottom sheet below the mobile breakpoint. Default `true`. */
|
|
832
853
|
mobileSheet?: boolean;
|
|
833
854
|
/** Render the built-in close control. Default `true`. */
|
package/dist/index.js
CHANGED
|
@@ -1873,12 +1873,14 @@ import * as VisuallyHidden2 from "@radix-ui/react-visually-hidden";
|
|
|
1873
1873
|
import { treeContainsComponent as treeContainsComponent3 } from "@ai-matrx/kit/react-tree";
|
|
1874
1874
|
import * as React17 from "react";
|
|
1875
1875
|
import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1876
|
+
var DialogWindowedByDefaultContext = React17.createContext(false);
|
|
1876
1877
|
var Dialog = ({
|
|
1877
1878
|
children,
|
|
1878
1879
|
...props
|
|
1879
1880
|
}) => {
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1881
|
+
const isMobile = useIsMobile();
|
|
1882
|
+
const modal = props.modal ?? isMobile;
|
|
1883
|
+
return /* @__PURE__ */ jsx21(DialogWindowedByDefaultContext.Provider, { value: props.modal === void 0, children: /* @__PURE__ */ jsx21(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ jsx21(DialogPrimitive2.Root, { ...props, modal, children }) }) });
|
|
1882
1884
|
};
|
|
1883
1885
|
Dialog.displayName = "Dialog";
|
|
1884
1886
|
var DialogTrigger = DialogPrimitive2.Trigger;
|
|
@@ -1926,6 +1928,11 @@ DialogContentPrimitive.displayName = "DialogContentPrimitive";
|
|
|
1926
1928
|
var DIALOG_DESKTOP_CLASSES2 = "matrx-dialog-card fixed inset-0 z-[10000] m-auto grid h-fit min-w-0 w-full max-w-lg gap-4 max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full sm:rounded-lg";
|
|
1927
1929
|
var DIALOG_MOBILE_SHEET_CLASSES2 = "matrx-mobile-sheet matrx-dialog-card fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] gap-4 [--dialog-pad:1rem] overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain";
|
|
1928
1930
|
var DIALOG_MOBILE_SHEET_OVERRIDE2 = "inset-x-0 bottom-0 left-0 right-0 top-auto translate-none w-full max-w-full max-h-[90dvh] rounded-b-none rounded-t-2xl overflow-y-auto";
|
|
1931
|
+
var DialogWindowHandleContext = React17.createContext(null);
|
|
1932
|
+
var WINDOW_KEEP_VISIBLE = 80;
|
|
1933
|
+
function isInteractiveTarget(target) {
|
|
1934
|
+
return target instanceof Element && Boolean(target.closest("button, a, input, textarea, select, [role='button'], [contenteditable='true']"));
|
|
1935
|
+
}
|
|
1929
1936
|
var DialogContent = React17.forwardRef(
|
|
1930
1937
|
({
|
|
1931
1938
|
className,
|
|
@@ -1934,15 +1941,51 @@ var DialogContent = React17.forwardRef(
|
|
|
1934
1941
|
animated = true,
|
|
1935
1942
|
showCloseButton = true,
|
|
1936
1943
|
container,
|
|
1944
|
+
dismissOnOutsideClick = false,
|
|
1945
|
+
onInteractOutside,
|
|
1946
|
+
onEscapeKeyDown,
|
|
1947
|
+
style,
|
|
1937
1948
|
...props
|
|
1938
1949
|
}, ref) => {
|
|
1939
1950
|
const isMobile = useIsMobile();
|
|
1940
1951
|
const isModal = useRadixDialogModal();
|
|
1941
1952
|
const injectedContainer = usePortalContainer(container);
|
|
1942
1953
|
const asSheet = mobileSheet && isMobile;
|
|
1954
|
+
const windowed = !isModal && !asSheet;
|
|
1955
|
+
const windowedByDefault = React17.useContext(DialogWindowedByDefaultContext);
|
|
1943
1956
|
const [containerEl, setContainerEl] = React17.useState(
|
|
1944
1957
|
null
|
|
1945
1958
|
);
|
|
1959
|
+
const [offset, setOffset] = React17.useState({ x: 0, y: 0 });
|
|
1960
|
+
const dragRef = React17.useRef(null);
|
|
1961
|
+
const handle = React17.useMemo(() => {
|
|
1962
|
+
if (!windowed) return null;
|
|
1963
|
+
const clamp = (value, limit) => Math.max(-limit, Math.min(limit, value));
|
|
1964
|
+
return {
|
|
1965
|
+
onPointerDown: (event) => {
|
|
1966
|
+
if (event.button !== 0 || isInteractiveTarget(event.target)) return;
|
|
1967
|
+
dragRef.current = { x: event.clientX, y: event.clientY, baseX: offset.x, baseY: offset.y };
|
|
1968
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
1969
|
+
},
|
|
1970
|
+
onPointerMove: (event) => {
|
|
1971
|
+
const start = dragRef.current;
|
|
1972
|
+
if (!start) return;
|
|
1973
|
+
setOffset({
|
|
1974
|
+
x: clamp(start.baseX + event.clientX - start.x, window.innerWidth / 2 - WINDOW_KEEP_VISIBLE / 2),
|
|
1975
|
+
y: clamp(start.baseY + event.clientY - start.y, window.innerHeight / 2 - WINDOW_KEEP_VISIBLE / 2)
|
|
1976
|
+
});
|
|
1977
|
+
},
|
|
1978
|
+
onPointerUp: (event) => {
|
|
1979
|
+
if (!dragRef.current) return;
|
|
1980
|
+
dragRef.current = null;
|
|
1981
|
+
event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
1982
|
+
},
|
|
1983
|
+
onPointerCancel: () => {
|
|
1984
|
+
dragRef.current = null;
|
|
1985
|
+
},
|
|
1986
|
+
onDoubleClick: () => setOffset({ x: 0, y: 0 })
|
|
1987
|
+
};
|
|
1988
|
+
}, [windowed, offset.x, offset.y]);
|
|
1946
1989
|
const mergedRef = React17.useCallback(
|
|
1947
1990
|
(node) => {
|
|
1948
1991
|
setContainerEl(node);
|
|
@@ -1970,19 +2013,33 @@ var DialogContent = React17.forwardRef(
|
|
|
1970
2013
|
// can sit beside a host's floating window manager (which starts at
|
|
1971
2014
|
// z=1000); staying below that boundary makes a newly focused window
|
|
1972
2015
|
// usable without coupling the two systems.
|
|
1973
|
-
!isModal && "z-[900]"
|
|
2016
|
+
!isModal && !windowedByDefault && "z-[900]",
|
|
2017
|
+
// Without an overlay the card needs its own separation from the page.
|
|
2018
|
+
windowed && "shadow-2xl ring-1 ring-border/60"
|
|
1974
2019
|
),
|
|
2020
|
+
style: windowed && (offset.x !== 0 || offset.y !== 0) ? { ...style, translate: `${offset.x}px ${offset.y}px` } : style,
|
|
2021
|
+
onInteractOutside: (event) => {
|
|
2022
|
+
onInteractOutside?.(event);
|
|
2023
|
+
if (windowed && !dismissOnOutsideClick) event.preventDefault();
|
|
2024
|
+
},
|
|
2025
|
+
onEscapeKeyDown: (event) => {
|
|
2026
|
+
onEscapeKeyDown?.(event);
|
|
2027
|
+
const pressedIn = event.target instanceof Node && event.target !== document.body ? event.target : document.activeElement;
|
|
2028
|
+
if (windowed && containerEl && !(pressedIn && containerEl.contains(pressedIn))) {
|
|
2029
|
+
event.preventDefault();
|
|
2030
|
+
}
|
|
2031
|
+
},
|
|
1975
2032
|
...hasDescription ? {} : { "aria-describedby": void 0 },
|
|
1976
2033
|
...props,
|
|
1977
2034
|
children: [
|
|
1978
2035
|
hasTitle ? null : /* @__PURE__ */ jsx21(VisuallyHidden2.Root, { children: /* @__PURE__ */ jsx21(DialogPrimitive2.Title, { children: "Dialog" }) }),
|
|
1979
|
-
/* @__PURE__ */ jsx21(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ jsx21(
|
|
2036
|
+
/* @__PURE__ */ jsx21(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ jsx21(DialogWindowHandleContext.Provider, { value: handle, children: /* @__PURE__ */ jsx21(
|
|
1980
2037
|
PortalContainerProvider,
|
|
1981
2038
|
{
|
|
1982
2039
|
container: containerEl ?? injectedContainer ?? null,
|
|
1983
2040
|
children
|
|
1984
2041
|
}
|
|
1985
|
-
) }),
|
|
2042
|
+
) }) }),
|
|
1986
2043
|
showCloseButton ? /* @__PURE__ */ jsxs10(
|
|
1987
2044
|
DialogPrimitive2.Close,
|
|
1988
2045
|
{
|
|
@@ -2005,19 +2062,28 @@ DialogContent.displayName = DialogPrimitive2.Content.displayName;
|
|
|
2005
2062
|
var DialogHeader = ({
|
|
2006
2063
|
className,
|
|
2007
2064
|
...props
|
|
2008
|
-
}) =>
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
"
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2065
|
+
}) => {
|
|
2066
|
+
const handle = React17.useContext(DialogWindowHandleContext);
|
|
2067
|
+
return /* @__PURE__ */ jsx21(
|
|
2068
|
+
"div",
|
|
2069
|
+
{
|
|
2070
|
+
"data-slot": "dialog-header",
|
|
2071
|
+
...handle ? {
|
|
2072
|
+
...handle,
|
|
2073
|
+
"data-window-handle": "",
|
|
2074
|
+
title: "Drag to move \xB7 double-click to recenter"
|
|
2075
|
+
} : {},
|
|
2076
|
+
className: cn(
|
|
2077
|
+
// DialogContent owns an absolute close control. Reserve its hit area in
|
|
2078
|
+
// every header so trailing actions never render underneath it.
|
|
2079
|
+
"flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
|
|
2080
|
+
handle && "cursor-grab select-none active:cursor-grabbing",
|
|
2081
|
+
className
|
|
2082
|
+
),
|
|
2083
|
+
...props
|
|
2084
|
+
}
|
|
2085
|
+
);
|
|
2086
|
+
};
|
|
2021
2087
|
DialogHeader.displayName = "DialogHeader";
|
|
2022
2088
|
var DialogFooter = ({
|
|
2023
2089
|
className,
|
|
@@ -2207,7 +2273,7 @@ var DropdownMenuShortcut = ({
|
|
|
2207
2273
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
2208
2274
|
|
|
2209
2275
|
// src/editable-label.tsx
|
|
2210
|
-
import { useCallback as useCallback3, useEffect as useEffect2, useRef as
|
|
2276
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
2211
2277
|
import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2212
2278
|
function EditableLabel({
|
|
2213
2279
|
value,
|
|
@@ -2233,7 +2299,7 @@ function EditableLabel({
|
|
|
2233
2299
|
const [draft, setDraft] = useState4(value);
|
|
2234
2300
|
const [error, setError] = useState4(null);
|
|
2235
2301
|
const [busy, setBusy] = useState4(false);
|
|
2236
|
-
const inputRef =
|
|
2302
|
+
const inputRef = useRef3(null);
|
|
2237
2303
|
useEffect2(() => {
|
|
2238
2304
|
if (!editing) setDraft(value);
|
|
2239
2305
|
}, [value, editing]);
|
|
@@ -2514,7 +2580,7 @@ var Label3 = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
2514
2580
|
Label3.displayName = LabelPrimitive.Root.displayName;
|
|
2515
2581
|
|
|
2516
2582
|
// src/overflow-toolbar.tsx
|
|
2517
|
-
import { useLayoutEffect, useMemo, useRef as
|
|
2583
|
+
import { useLayoutEffect, useMemo as useMemo2, useRef as useRef4, useState as useState5 } from "react";
|
|
2518
2584
|
import { Fragment, jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2519
2585
|
var GAP_PX = 6;
|
|
2520
2586
|
var TONE = {
|
|
@@ -2596,13 +2662,13 @@ function OverflowToolbar({
|
|
|
2596
2662
|
renderOverflowMenu,
|
|
2597
2663
|
renderTooltip
|
|
2598
2664
|
}) {
|
|
2599
|
-
const visibleActions =
|
|
2665
|
+
const visibleActions = useMemo2(
|
|
2600
2666
|
() => actions.filter((a) => !a.hidden),
|
|
2601
2667
|
[actions]
|
|
2602
2668
|
);
|
|
2603
|
-
const containerRef =
|
|
2604
|
-
const ghostRef =
|
|
2605
|
-
const leadingRef =
|
|
2669
|
+
const containerRef = useRef4(null);
|
|
2670
|
+
const ghostRef = useRef4(null);
|
|
2671
|
+
const leadingRef = useRef4(null);
|
|
2606
2672
|
const [visibleCount, setVisibleCount] = useState5(visibleActions.length);
|
|
2607
2673
|
const signature = visibleActions.map(
|
|
2608
2674
|
(a) => `${a.id}:${a.hideLabel ? 1 : 0}:${a.running ? 1 : 0}:${a.runningLabel ?? ""}:${a.label}`
|
|
@@ -4005,15 +4071,15 @@ var TextareaWithPrefix = React32.forwardRef(
|
|
|
4005
4071
|
TextareaWithPrefix.displayName = "TextareaWithPrefix";
|
|
4006
4072
|
|
|
4007
4073
|
// src/use-scroll-fade.ts
|
|
4008
|
-
import { useCallback as useCallback5, useEffect as useEffect4, useRef as
|
|
4074
|
+
import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef6, useState as useState8 } from "react";
|
|
4009
4075
|
var EPSILON = 2;
|
|
4010
4076
|
function useScrollFade() {
|
|
4011
4077
|
const [state, setState] = useState8({
|
|
4012
4078
|
top: false,
|
|
4013
4079
|
bottom: false
|
|
4014
4080
|
});
|
|
4015
|
-
const nodeRef =
|
|
4016
|
-
const cleanupRef =
|
|
4081
|
+
const nodeRef = useRef6(null);
|
|
4082
|
+
const cleanupRef = useRef6(null);
|
|
4017
4083
|
const measure = useCallback5(() => {
|
|
4018
4084
|
const el = nodeRef.current;
|
|
4019
4085
|
if (!el) return;
|