@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.38.1 — 2026-09-23
|
|
4
|
+
|
|
5
|
+
**A default window-style Dialog sits with the layer that opened it.** In 0.38.0 every non-blocking dialog took the older `z-[900]` layer, which put a dialog opened from a menu, a popover or a host window BEHIND its opener (caught by matrx-frontend's nested-portal guard before adoption). A dialog that is a window because the caller said nothing about `modal` now sits at `z-[10000]`, as a blocking dialog always did; a caller that passes `modal={false}` explicitly keeps `z-[900]` (the coexistence contract below a host window manager). Two tests.
|
|
6
|
+
|
|
7
|
+
**Consumer action:** none.
|
|
8
|
+
|
|
9
|
+
## 0.38.0 — 2026-09-23
|
|
10
|
+
|
|
11
|
+
**On desktop a Dialog is a window, not a wall.** (register ARE-006, `common-docs/projects/ai-reachable-everywhere/REGISTER.md`.)
|
|
12
|
+
|
|
13
|
+
Arman, on a blocking settings dialog: *"none of the built-in page ai integrations are accessible because the page is totally blocked."* Unless the caller passes `modal`, a desktop `Dialog` no longer blocks the page: no overlay, and the page, its menus and every AI control beside it stay usable. It behaves like a light window:
|
|
14
|
+
|
|
15
|
+
* a click outside never closes it — `DialogContent dismissOnOutsideClick` opts a quick picker back in;
|
|
16
|
+
* Escape closes it only when pressed inside it — Escape pressed in the page belongs to the page;
|
|
17
|
+
* `DialogHeader` drags it (clamped on screen, double-click recenters);
|
|
18
|
+
* it carries its own shadow and ring, since there is no scrim.
|
|
19
|
+
|
|
20
|
+
Unchanged: the API (`open`, `onOpenChange`, `DialogTrigger`, `DialogClose`); `AlertDialog` / `ConfirmDialog` (a different component, still blocking); the phone bottom sheet (still blocking); any caller passing `modal` explicitly. `SavedViewsControl` no longer shows its error twice while its save window is open (the page is visible now).
|
|
21
|
+
|
|
22
|
+
**Consumer action:** none required. A screen that genuinely must block (a destructive step that is not a confirmation) passes `modal`. A screen whose content relied on closing when the person clicked away passes `dismissOnOutsideClick`. A test that queries the whole document for a role the page ALSO carries must scope to the dialog (`within(dialog)`), because the page behind is no longer hidden from assistive technology.
|
|
23
|
+
|
|
3
24
|
## 0.37.1 — 2026-09-23 (0.37.0 was tagged but its dts build failed under TypeScript 6 before the registry; same contents)
|
|
4
25
|
|
|
5
26
|
**Four data-table changes that were on main and never published.** (published by lane
|
|
@@ -265,12 +265,14 @@ function useIsMobile() {
|
|
|
265
265
|
|
|
266
266
|
// src/dialog.tsx
|
|
267
267
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
268
|
+
var DialogWindowedByDefaultContext = React5.createContext(false);
|
|
268
269
|
var Dialog = ({
|
|
269
270
|
children,
|
|
270
271
|
...props
|
|
271
272
|
}) => {
|
|
272
|
-
const
|
|
273
|
-
|
|
273
|
+
const isMobile = useIsMobile();
|
|
274
|
+
const modal = props.modal ?? isMobile;
|
|
275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogWindowedByDefaultContext.Provider, { value: props.modal === void 0, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogPrimitive.Root, { ...props, modal, children }) }) });
|
|
274
276
|
};
|
|
275
277
|
Dialog.displayName = "Dialog";
|
|
276
278
|
var DialogPortal = ({
|
|
@@ -315,6 +317,11 @@ DialogContentPrimitive.displayName = "DialogContentPrimitive";
|
|
|
315
317
|
var DIALOG_DESKTOP_CLASSES = "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";
|
|
316
318
|
var DIALOG_MOBILE_SHEET_CLASSES = "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";
|
|
317
319
|
var DIALOG_MOBILE_SHEET_OVERRIDE = "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";
|
|
320
|
+
var DialogWindowHandleContext = React5.createContext(null);
|
|
321
|
+
var WINDOW_KEEP_VISIBLE = 80;
|
|
322
|
+
function isInteractiveTarget(target) {
|
|
323
|
+
return target instanceof Element && Boolean(target.closest("button, a, input, textarea, select, [role='button'], [contenteditable='true']"));
|
|
324
|
+
}
|
|
318
325
|
var DialogContent = React5.forwardRef(
|
|
319
326
|
({
|
|
320
327
|
className,
|
|
@@ -323,15 +330,51 @@ var DialogContent = React5.forwardRef(
|
|
|
323
330
|
animated = true,
|
|
324
331
|
showCloseButton = true,
|
|
325
332
|
container,
|
|
333
|
+
dismissOnOutsideClick = false,
|
|
334
|
+
onInteractOutside,
|
|
335
|
+
onEscapeKeyDown,
|
|
336
|
+
style,
|
|
326
337
|
...props
|
|
327
338
|
}, ref) => {
|
|
328
339
|
const isMobile = useIsMobile();
|
|
329
340
|
const isModal = useRadixDialogModal();
|
|
330
341
|
const injectedContainer = usePortalContainer(container);
|
|
331
342
|
const asSheet = mobileSheet && isMobile;
|
|
343
|
+
const windowed = !isModal && !asSheet;
|
|
344
|
+
const windowedByDefault = React5.useContext(DialogWindowedByDefaultContext);
|
|
332
345
|
const [containerEl, setContainerEl] = React5.useState(
|
|
333
346
|
null
|
|
334
347
|
);
|
|
348
|
+
const [offset, setOffset] = React5.useState({ x: 0, y: 0 });
|
|
349
|
+
const dragRef = React5.useRef(null);
|
|
350
|
+
const handle = React5.useMemo(() => {
|
|
351
|
+
if (!windowed) return null;
|
|
352
|
+
const clamp = (value, limit) => Math.max(-limit, Math.min(limit, value));
|
|
353
|
+
return {
|
|
354
|
+
onPointerDown: (event) => {
|
|
355
|
+
if (event.button !== 0 || isInteractiveTarget(event.target)) return;
|
|
356
|
+
dragRef.current = { x: event.clientX, y: event.clientY, baseX: offset.x, baseY: offset.y };
|
|
357
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
358
|
+
},
|
|
359
|
+
onPointerMove: (event) => {
|
|
360
|
+
const start = dragRef.current;
|
|
361
|
+
if (!start) return;
|
|
362
|
+
setOffset({
|
|
363
|
+
x: clamp(start.baseX + event.clientX - start.x, window.innerWidth / 2 - WINDOW_KEEP_VISIBLE / 2),
|
|
364
|
+
y: clamp(start.baseY + event.clientY - start.y, window.innerHeight / 2 - WINDOW_KEEP_VISIBLE / 2)
|
|
365
|
+
});
|
|
366
|
+
},
|
|
367
|
+
onPointerUp: (event) => {
|
|
368
|
+
if (!dragRef.current) return;
|
|
369
|
+
dragRef.current = null;
|
|
370
|
+
event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
371
|
+
},
|
|
372
|
+
onPointerCancel: () => {
|
|
373
|
+
dragRef.current = null;
|
|
374
|
+
},
|
|
375
|
+
onDoubleClick: () => setOffset({ x: 0, y: 0 })
|
|
376
|
+
};
|
|
377
|
+
}, [windowed, offset.x, offset.y]);
|
|
335
378
|
const mergedRef = React5.useCallback(
|
|
336
379
|
(node) => {
|
|
337
380
|
setContainerEl(node);
|
|
@@ -359,19 +402,33 @@ var DialogContent = React5.forwardRef(
|
|
|
359
402
|
// can sit beside a host's floating window manager (which starts at
|
|
360
403
|
// z=1000); staying below that boundary makes a newly focused window
|
|
361
404
|
// usable without coupling the two systems.
|
|
362
|
-
!isModal && "z-[900]"
|
|
405
|
+
!isModal && !windowedByDefault && "z-[900]",
|
|
406
|
+
// Without an overlay the card needs its own separation from the page.
|
|
407
|
+
windowed && "shadow-2xl ring-1 ring-border/60"
|
|
363
408
|
),
|
|
409
|
+
style: windowed && (offset.x !== 0 || offset.y !== 0) ? { ...style, translate: `${offset.x}px ${offset.y}px` } : style,
|
|
410
|
+
onInteractOutside: (event) => {
|
|
411
|
+
onInteractOutside?.(event);
|
|
412
|
+
if (windowed && !dismissOnOutsideClick) event.preventDefault();
|
|
413
|
+
},
|
|
414
|
+
onEscapeKeyDown: (event) => {
|
|
415
|
+
onEscapeKeyDown?.(event);
|
|
416
|
+
const pressedIn = event.target instanceof Node && event.target !== document.body ? event.target : document.activeElement;
|
|
417
|
+
if (windowed && containerEl && !(pressedIn && containerEl.contains(pressedIn))) {
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
}
|
|
420
|
+
},
|
|
364
421
|
...hasDescription ? {} : { "aria-describedby": void 0 },
|
|
365
422
|
...props,
|
|
366
423
|
children: [
|
|
367
424
|
hasTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VisuallyHidden.Root, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogPrimitive.Title, { children: "Dialog" }) }),
|
|
368
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogWindowHandleContext.Provider, { value: handle, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
369
426
|
PortalContainerProvider,
|
|
370
427
|
{
|
|
371
428
|
container: containerEl ?? injectedContainer ?? null,
|
|
372
429
|
children
|
|
373
430
|
}
|
|
374
|
-
) }),
|
|
431
|
+
) }) }),
|
|
375
432
|
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
376
433
|
DialogPrimitive.Close,
|
|
377
434
|
{
|
|
@@ -394,19 +451,28 @@ DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
|
394
451
|
var DialogHeader = ({
|
|
395
452
|
className,
|
|
396
453
|
...props
|
|
397
|
-
}) =>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
"
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
454
|
+
}) => {
|
|
455
|
+
const handle = React5.useContext(DialogWindowHandleContext);
|
|
456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
457
|
+
"div",
|
|
458
|
+
{
|
|
459
|
+
"data-slot": "dialog-header",
|
|
460
|
+
...handle ? {
|
|
461
|
+
...handle,
|
|
462
|
+
"data-window-handle": "",
|
|
463
|
+
title: "Drag to move \xB7 double-click to recenter"
|
|
464
|
+
} : {},
|
|
465
|
+
className: cn(
|
|
466
|
+
// DialogContent owns an absolute close control. Reserve its hit area in
|
|
467
|
+
// every header so trailing actions never render underneath it.
|
|
468
|
+
"flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
|
|
469
|
+
handle && "cursor-grab select-none active:cursor-grabbing",
|
|
470
|
+
className
|
|
471
|
+
),
|
|
472
|
+
...props
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
};
|
|
410
476
|
DialogHeader.displayName = "DialogHeader";
|
|
411
477
|
var DialogFooter = ({
|
|
412
478
|
className,
|