@ai-matrx/design-system 0.36.0 → 0.38.0
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 +31 -0
- package/dist/content-transfer.cjs +81 -17
- package/dist/content-transfer.cjs.map +1 -1
- package/dist/content-transfer.js +81 -17
- package/dist/content-transfer.js.map +1 -1
- package/dist/data-table/copy-helpers.d.cts +1 -1
- package/dist/data-table/copy-helpers.d.ts +1 -1
- package/dist/data-table/data-row-inspector.cjs +81 -17
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js +83 -19
- package/dist/data-table/data-row-inspector.js.map +1 -1
- package/dist/data-table/data-row-window.cjs +81 -17
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js +83 -19
- package/dist/data-table/data-row-window.js.map +1 -1
- package/dist/data-table/filter-engine.d.cts +1 -1
- package/dist/data-table/filter-engine.d.ts +1 -1
- package/dist/data-table/host.d.cts +1 -1
- package/dist/data-table/host.d.ts +1 -1
- package/dist/data-table/index.cjs +127 -25
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.d.cts +2 -2
- package/dist/data-table/index.d.ts +2 -2
- package/dist/data-table/index.js +223 -121
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/infer-filter.d.cts +1 -1
- package/dist/data-table/infer-filter.d.ts +1 -1
- package/dist/data-table/layered-filters.d.cts +1 -1
- package/dist/data-table/layered-filters.d.ts +1 -1
- package/dist/data-table/query-control.d.cts +1 -1
- package/dist/data-table/query-control.d.ts +1 -1
- package/dist/data-table/types.cjs.map +1 -1
- package/dist/data-table/types.d.cts +1 -1
- package/dist/data-table/types.d.ts +1 -1
- package/dist/data-table/url-state.d.cts +1 -1
- package/dist/data-table/url-state.d.ts +1 -1
- package/dist/data-table/xlsx.d.cts +1 -1
- package/dist/data-table/xlsx.d.ts +1 -1
- package/dist/index.cjs +81 -17
- 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 +91 -27
- package/dist/index.js.map +1 -1
- package/dist/{types-Cxm5XK0L.d.ts → types-B8vwElPz.d.ts} +25 -1
- package/dist/{types-kiV-CAuZ.d.cts → types-BuMHbFjs.d.cts} +25 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.38.0 — 2026-09-23
|
|
4
|
+
|
|
5
|
+
**On desktop a Dialog is a window, not a wall.** (register ARE-006, `common-docs/projects/ai-reachable-everywhere/REGISTER.md`.)
|
|
6
|
+
|
|
7
|
+
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:
|
|
8
|
+
|
|
9
|
+
* a click outside never closes it — `DialogContent dismissOnOutsideClick` opts a quick picker back in;
|
|
10
|
+
* Escape closes it only when pressed inside it — Escape pressed in the page belongs to the page;
|
|
11
|
+
* `DialogHeader` drags it (clamped on screen, double-click recenters);
|
|
12
|
+
* it carries its own shadow and ring, since there is no scrim.
|
|
13
|
+
|
|
14
|
+
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).
|
|
15
|
+
|
|
16
|
+
**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.
|
|
17
|
+
|
|
18
|
+
## 0.37.1 — 2026-09-23 (0.37.0 was tagged but its dts build failed under TypeScript 6 before the registry; same contents)
|
|
19
|
+
|
|
20
|
+
**Four data-table changes that were on main and never published.** (published by lane
|
|
21
|
+
PUBLISH-SWEEP-4.)
|
|
22
|
+
|
|
23
|
+
* **Keyboard multi-expand restored** — expanded-detail rows open and close from the keyboard in
|
|
24
|
+
the multi-expand arm again (`MatrxDataTable.expanded-detail.test.tsx`).
|
|
25
|
+
* **`coverage.loaded`** — the number of rows loaded from the source BEFORE a host narrows `data`
|
|
26
|
+
with a domain filter; defaults to `data.length`, so a filtered page no longer reports the
|
|
27
|
+
filtered count as what was loaded.
|
|
28
|
+
* **`toolbar.titleCount`** — a source-owned total shown beside the shared title.
|
|
29
|
+
* **`toolbar.customSearch`** — a caller-owned search control in the canonical title-row search
|
|
30
|
+
slot, for a deliberately narrower query contract; it never changes table query state.
|
|
31
|
+
|
|
32
|
+
No consumer action; every addition is optional. Toolchain moved to TypeScript 6.
|
|
33
|
+
|
|
3
34
|
## 0.36.0 — 2026-09-23
|
|
4
35
|
|
|
5
36
|
**A press inside a popover a grid cell opened is no longer a press on the cell.** (lane
|
|
@@ -269,7 +269,8 @@ var Dialog = ({
|
|
|
269
269
|
children,
|
|
270
270
|
...props
|
|
271
271
|
}) => {
|
|
272
|
-
const
|
|
272
|
+
const isMobile = useIsMobile();
|
|
273
|
+
const modal = props.modal ?? isMobile;
|
|
273
274
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DialogPrimitive.Root, { ...props, modal, children }) });
|
|
274
275
|
};
|
|
275
276
|
Dialog.displayName = "Dialog";
|
|
@@ -315,6 +316,11 @@ DialogContentPrimitive.displayName = "DialogContentPrimitive";
|
|
|
315
316
|
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
317
|
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
318
|
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";
|
|
319
|
+
var DialogWindowHandleContext = React5.createContext(null);
|
|
320
|
+
var WINDOW_KEEP_VISIBLE = 80;
|
|
321
|
+
function isInteractiveTarget(target) {
|
|
322
|
+
return target instanceof Element && Boolean(target.closest("button, a, input, textarea, select, [role='button'], [contenteditable='true']"));
|
|
323
|
+
}
|
|
318
324
|
var DialogContent = React5.forwardRef(
|
|
319
325
|
({
|
|
320
326
|
className,
|
|
@@ -323,15 +329,50 @@ var DialogContent = React5.forwardRef(
|
|
|
323
329
|
animated = true,
|
|
324
330
|
showCloseButton = true,
|
|
325
331
|
container,
|
|
332
|
+
dismissOnOutsideClick = false,
|
|
333
|
+
onInteractOutside,
|
|
334
|
+
onEscapeKeyDown,
|
|
335
|
+
style,
|
|
326
336
|
...props
|
|
327
337
|
}, ref) => {
|
|
328
338
|
const isMobile = useIsMobile();
|
|
329
339
|
const isModal = useRadixDialogModal();
|
|
330
340
|
const injectedContainer = usePortalContainer(container);
|
|
331
341
|
const asSheet = mobileSheet && isMobile;
|
|
342
|
+
const windowed = !isModal && !asSheet;
|
|
332
343
|
const [containerEl, setContainerEl] = React5.useState(
|
|
333
344
|
null
|
|
334
345
|
);
|
|
346
|
+
const [offset, setOffset] = React5.useState({ x: 0, y: 0 });
|
|
347
|
+
const dragRef = React5.useRef(null);
|
|
348
|
+
const handle = React5.useMemo(() => {
|
|
349
|
+
if (!windowed) return null;
|
|
350
|
+
const clamp = (value, limit) => Math.max(-limit, Math.min(limit, value));
|
|
351
|
+
return {
|
|
352
|
+
onPointerDown: (event) => {
|
|
353
|
+
if (event.button !== 0 || isInteractiveTarget(event.target)) return;
|
|
354
|
+
dragRef.current = { x: event.clientX, y: event.clientY, baseX: offset.x, baseY: offset.y };
|
|
355
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
356
|
+
},
|
|
357
|
+
onPointerMove: (event) => {
|
|
358
|
+
const start = dragRef.current;
|
|
359
|
+
if (!start) return;
|
|
360
|
+
setOffset({
|
|
361
|
+
x: clamp(start.baseX + event.clientX - start.x, window.innerWidth / 2 - WINDOW_KEEP_VISIBLE / 2),
|
|
362
|
+
y: clamp(start.baseY + event.clientY - start.y, window.innerHeight / 2 - WINDOW_KEEP_VISIBLE / 2)
|
|
363
|
+
});
|
|
364
|
+
},
|
|
365
|
+
onPointerUp: (event) => {
|
|
366
|
+
if (!dragRef.current) return;
|
|
367
|
+
dragRef.current = null;
|
|
368
|
+
event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
369
|
+
},
|
|
370
|
+
onPointerCancel: () => {
|
|
371
|
+
dragRef.current = null;
|
|
372
|
+
},
|
|
373
|
+
onDoubleClick: () => setOffset({ x: 0, y: 0 })
|
|
374
|
+
};
|
|
375
|
+
}, [windowed, offset.x, offset.y]);
|
|
335
376
|
const mergedRef = React5.useCallback(
|
|
336
377
|
(node) => {
|
|
337
378
|
setContainerEl(node);
|
|
@@ -359,19 +400,33 @@ var DialogContent = React5.forwardRef(
|
|
|
359
400
|
// can sit beside a host's floating window manager (which starts at
|
|
360
401
|
// z=1000); staying below that boundary makes a newly focused window
|
|
361
402
|
// usable without coupling the two systems.
|
|
362
|
-
!isModal && "z-[900]"
|
|
403
|
+
!isModal && "z-[900]",
|
|
404
|
+
// Without an overlay the card needs its own separation from the page.
|
|
405
|
+
windowed && "shadow-2xl ring-1 ring-border/60"
|
|
363
406
|
),
|
|
407
|
+
style: windowed && (offset.x !== 0 || offset.y !== 0) ? { ...style, translate: `${offset.x}px ${offset.y}px` } : style,
|
|
408
|
+
onInteractOutside: (event) => {
|
|
409
|
+
onInteractOutside?.(event);
|
|
410
|
+
if (windowed && !dismissOnOutsideClick) event.preventDefault();
|
|
411
|
+
},
|
|
412
|
+
onEscapeKeyDown: (event) => {
|
|
413
|
+
onEscapeKeyDown?.(event);
|
|
414
|
+
const pressedIn = event.target instanceof Node && event.target !== document.body ? event.target : document.activeElement;
|
|
415
|
+
if (windowed && containerEl && !(pressedIn && containerEl.contains(pressedIn))) {
|
|
416
|
+
event.preventDefault();
|
|
417
|
+
}
|
|
418
|
+
},
|
|
364
419
|
...hasDescription ? {} : { "aria-describedby": void 0 },
|
|
365
420
|
...props,
|
|
366
421
|
children: [
|
|
367
422
|
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)(
|
|
423
|
+
/* @__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
424
|
PortalContainerProvider,
|
|
370
425
|
{
|
|
371
426
|
container: containerEl ?? injectedContainer ?? null,
|
|
372
427
|
children
|
|
373
428
|
}
|
|
374
|
-
) }),
|
|
429
|
+
) }) }),
|
|
375
430
|
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
376
431
|
DialogPrimitive.Close,
|
|
377
432
|
{
|
|
@@ -394,19 +449,28 @@ DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
|
394
449
|
var DialogHeader = ({
|
|
395
450
|
className,
|
|
396
451
|
...props
|
|
397
|
-
}) =>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
"
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
452
|
+
}) => {
|
|
453
|
+
const handle = React5.useContext(DialogWindowHandleContext);
|
|
454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
455
|
+
"div",
|
|
456
|
+
{
|
|
457
|
+
"data-slot": "dialog-header",
|
|
458
|
+
...handle ? {
|
|
459
|
+
...handle,
|
|
460
|
+
"data-window-handle": "",
|
|
461
|
+
title: "Drag to move \xB7 double-click to recenter"
|
|
462
|
+
} : {},
|
|
463
|
+
className: cn(
|
|
464
|
+
// DialogContent owns an absolute close control. Reserve its hit area in
|
|
465
|
+
// every header so trailing actions never render underneath it.
|
|
466
|
+
"flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
|
|
467
|
+
handle && "cursor-grab select-none active:cursor-grabbing",
|
|
468
|
+
className
|
|
469
|
+
),
|
|
470
|
+
...props
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
};
|
|
410
474
|
DialogHeader.displayName = "DialogHeader";
|
|
411
475
|
var DialogFooter = ({
|
|
412
476
|
className,
|