@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.
Files changed (47) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/content-transfer.cjs +81 -17
  3. package/dist/content-transfer.cjs.map +1 -1
  4. package/dist/content-transfer.js +81 -17
  5. package/dist/content-transfer.js.map +1 -1
  6. package/dist/data-table/copy-helpers.d.cts +1 -1
  7. package/dist/data-table/copy-helpers.d.ts +1 -1
  8. package/dist/data-table/data-row-inspector.cjs +81 -17
  9. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  10. package/dist/data-table/data-row-inspector.js +83 -19
  11. package/dist/data-table/data-row-inspector.js.map +1 -1
  12. package/dist/data-table/data-row-window.cjs +81 -17
  13. package/dist/data-table/data-row-window.cjs.map +1 -1
  14. package/dist/data-table/data-row-window.js +83 -19
  15. package/dist/data-table/data-row-window.js.map +1 -1
  16. package/dist/data-table/filter-engine.d.cts +1 -1
  17. package/dist/data-table/filter-engine.d.ts +1 -1
  18. package/dist/data-table/host.d.cts +1 -1
  19. package/dist/data-table/host.d.ts +1 -1
  20. package/dist/data-table/index.cjs +127 -25
  21. package/dist/data-table/index.cjs.map +1 -1
  22. package/dist/data-table/index.d.cts +2 -2
  23. package/dist/data-table/index.d.ts +2 -2
  24. package/dist/data-table/index.js +223 -121
  25. package/dist/data-table/index.js.map +1 -1
  26. package/dist/data-table/infer-filter.d.cts +1 -1
  27. package/dist/data-table/infer-filter.d.ts +1 -1
  28. package/dist/data-table/layered-filters.d.cts +1 -1
  29. package/dist/data-table/layered-filters.d.ts +1 -1
  30. package/dist/data-table/query-control.d.cts +1 -1
  31. package/dist/data-table/query-control.d.ts +1 -1
  32. package/dist/data-table/types.cjs.map +1 -1
  33. package/dist/data-table/types.d.cts +1 -1
  34. package/dist/data-table/types.d.ts +1 -1
  35. package/dist/data-table/url-state.d.cts +1 -1
  36. package/dist/data-table/url-state.d.ts +1 -1
  37. package/dist/data-table/xlsx.d.cts +1 -1
  38. package/dist/data-table/xlsx.d.ts +1 -1
  39. package/dist/index.cjs +81 -17
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +21 -0
  42. package/dist/index.d.ts +21 -0
  43. package/dist/index.js +91 -27
  44. package/dist/index.js.map +1 -1
  45. package/dist/{types-Cxm5XK0L.d.ts → types-B8vwElPz.d.ts} +25 -1
  46. package/dist/{types-kiV-CAuZ.d.cts → types-BuMHbFjs.d.cts} +25 -1
  47. package/package.json +7 -7
@@ -163,7 +163,8 @@ var Dialog = ({
163
163
  children,
164
164
  ...props
165
165
  }) => {
166
- const modal = props.modal ?? true;
166
+ const isMobile = useIsMobile();
167
+ const modal = props.modal ?? isMobile;
167
168
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DialogPrimitive.Root, { ...props, modal, children }) });
168
169
  };
169
170
  Dialog.displayName = "Dialog";
@@ -209,6 +210,11 @@ DialogContentPrimitive.displayName = "DialogContentPrimitive";
209
210
  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";
210
211
  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";
211
212
  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";
213
+ var DialogWindowHandleContext = React4.createContext(null);
214
+ var WINDOW_KEEP_VISIBLE = 80;
215
+ function isInteractiveTarget(target) {
216
+ return target instanceof Element && Boolean(target.closest("button, a, input, textarea, select, [role='button'], [contenteditable='true']"));
217
+ }
212
218
  var DialogContent = React4.forwardRef(
213
219
  ({
214
220
  className,
@@ -217,15 +223,50 @@ var DialogContent = React4.forwardRef(
217
223
  animated = true,
218
224
  showCloseButton = true,
219
225
  container,
226
+ dismissOnOutsideClick = false,
227
+ onInteractOutside,
228
+ onEscapeKeyDown,
229
+ style,
220
230
  ...props
221
231
  }, ref) => {
222
232
  const isMobile = useIsMobile();
223
233
  const isModal = useRadixDialogModal();
224
234
  const injectedContainer = usePortalContainer(container);
225
235
  const asSheet = mobileSheet && isMobile;
236
+ const windowed = !isModal && !asSheet;
226
237
  const [containerEl, setContainerEl] = React4.useState(
227
238
  null
228
239
  );
240
+ const [offset, setOffset] = React4.useState({ x: 0, y: 0 });
241
+ const dragRef = React4.useRef(null);
242
+ const handle = React4.useMemo(() => {
243
+ if (!windowed) return null;
244
+ const clamp = (value, limit) => Math.max(-limit, Math.min(limit, value));
245
+ return {
246
+ onPointerDown: (event) => {
247
+ if (event.button !== 0 || isInteractiveTarget(event.target)) return;
248
+ dragRef.current = { x: event.clientX, y: event.clientY, baseX: offset.x, baseY: offset.y };
249
+ event.currentTarget.setPointerCapture?.(event.pointerId);
250
+ },
251
+ onPointerMove: (event) => {
252
+ const start = dragRef.current;
253
+ if (!start) return;
254
+ setOffset({
255
+ x: clamp(start.baseX + event.clientX - start.x, window.innerWidth / 2 - WINDOW_KEEP_VISIBLE / 2),
256
+ y: clamp(start.baseY + event.clientY - start.y, window.innerHeight / 2 - WINDOW_KEEP_VISIBLE / 2)
257
+ });
258
+ },
259
+ onPointerUp: (event) => {
260
+ if (!dragRef.current) return;
261
+ dragRef.current = null;
262
+ event.currentTarget.releasePointerCapture?.(event.pointerId);
263
+ },
264
+ onPointerCancel: () => {
265
+ dragRef.current = null;
266
+ },
267
+ onDoubleClick: () => setOffset({ x: 0, y: 0 })
268
+ };
269
+ }, [windowed, offset.x, offset.y]);
229
270
  const mergedRef = React4.useCallback(
230
271
  (node) => {
231
272
  setContainerEl(node);
@@ -253,19 +294,33 @@ var DialogContent = React4.forwardRef(
253
294
  // can sit beside a host's floating window manager (which starts at
254
295
  // z=1000); staying below that boundary makes a newly focused window
255
296
  // usable without coupling the two systems.
256
- !isModal && "z-[900]"
297
+ !isModal && "z-[900]",
298
+ // Without an overlay the card needs its own separation from the page.
299
+ windowed && "shadow-2xl ring-1 ring-border/60"
257
300
  ),
301
+ style: windowed && (offset.x !== 0 || offset.y !== 0) ? { ...style, translate: `${offset.x}px ${offset.y}px` } : style,
302
+ onInteractOutside: (event) => {
303
+ onInteractOutside?.(event);
304
+ if (windowed && !dismissOnOutsideClick) event.preventDefault();
305
+ },
306
+ onEscapeKeyDown: (event) => {
307
+ onEscapeKeyDown?.(event);
308
+ const pressedIn = event.target instanceof Node && event.target !== document.body ? event.target : document.activeElement;
309
+ if (windowed && containerEl && !(pressedIn && containerEl.contains(pressedIn))) {
310
+ event.preventDefault();
311
+ }
312
+ },
258
313
  ...hasDescription ? {} : { "aria-describedby": void 0 },
259
314
  ...props,
260
315
  children: [
261
316
  hasTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VisuallyHidden.Root, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DialogPrimitive.Title, { children: "Dialog" }) }),
262
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
317
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DialogWindowHandleContext.Provider, { value: handle, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
263
318
  PortalContainerProvider,
264
319
  {
265
320
  container: containerEl ?? injectedContainer ?? null,
266
321
  children
267
322
  }
268
- ) }),
323
+ ) }) }),
269
324
  showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
270
325
  DialogPrimitive.Close,
271
326
  {
@@ -288,19 +343,28 @@ DialogContent.displayName = DialogPrimitive.Content.displayName;
288
343
  var DialogHeader = ({
289
344
  className,
290
345
  ...props
291
- }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
292
- "div",
293
- {
294
- "data-slot": "dialog-header",
295
- className: cn(
296
- // DialogContent owns an absolute close control. Reserve its hit area in
297
- // every header so trailing actions never render underneath it.
298
- "flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
299
- className
300
- ),
301
- ...props
302
- }
303
- );
346
+ }) => {
347
+ const handle = React4.useContext(DialogWindowHandleContext);
348
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
349
+ "div",
350
+ {
351
+ "data-slot": "dialog-header",
352
+ ...handle ? {
353
+ ...handle,
354
+ "data-window-handle": "",
355
+ title: "Drag to move \xB7 double-click to recenter"
356
+ } : {},
357
+ className: cn(
358
+ // DialogContent owns an absolute close control. Reserve its hit area in
359
+ // every header so trailing actions never render underneath it.
360
+ "flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
361
+ handle && "cursor-grab select-none active:cursor-grabbing",
362
+ className
363
+ ),
364
+ ...props
365
+ }
366
+ );
367
+ };
304
368
  DialogHeader.displayName = "DialogHeader";
305
369
  var DialogFooter = ({
306
370
  className,