@ai-matrx/design-system 0.14.2 → 0.15.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 +49 -0
- package/README.md +26 -0
- package/dist/data-table/copy-helpers.cjs +149 -0
- package/dist/data-table/copy-helpers.cjs.map +1 -0
- package/dist/data-table/copy-helpers.d.cts +31 -0
- package/dist/data-table/copy-helpers.d.ts +31 -0
- package/dist/data-table/copy-helpers.js +127 -0
- package/dist/data-table/copy-helpers.js.map +1 -0
- package/dist/data-table/copy-types.cjs +19 -0
- package/dist/data-table/copy-types.cjs.map +1 -0
- package/dist/data-table/copy-types.d.cts +137 -0
- package/dist/data-table/copy-types.d.ts +137 -0
- package/dist/data-table/copy-types.js +1 -0
- package/dist/data-table/copy-types.js.map +1 -0
- package/dist/data-table/data-row-inspector.cjs +1016 -0
- package/dist/data-table/data-row-inspector.cjs.map +1 -0
- package/dist/data-table/data-row-inspector.d.cts +34 -0
- package/dist/data-table/data-row-inspector.d.ts +34 -0
- package/dist/data-table/data-row-inspector.js +988 -0
- package/dist/data-table/data-row-inspector.js.map +1 -0
- package/dist/data-table/data-row-window.cjs +1136 -0
- package/dist/data-table/data-row-window.cjs.map +1 -0
- package/dist/data-table/data-row-window.d.cts +29 -0
- package/dist/data-table/data-row-window.d.ts +29 -0
- package/dist/data-table/data-row-window.js +1110 -0
- package/dist/data-table/data-row-window.js.map +1 -0
- package/dist/data-table/filter-engine.cjs +314 -0
- package/dist/data-table/filter-engine.cjs.map +1 -0
- package/dist/data-table/filter-engine.d.cts +35 -0
- package/dist/data-table/filter-engine.d.ts +35 -0
- package/dist/data-table/filter-engine.js +292 -0
- package/dist/data-table/filter-engine.js.map +1 -0
- package/dist/data-table/host.cjs +40 -0
- package/dist/data-table/host.cjs.map +1 -0
- package/dist/data-table/host.d.cts +73 -0
- package/dist/data-table/host.d.ts +73 -0
- package/dist/data-table/host.js +20 -0
- package/dist/data-table/host.js.map +1 -0
- package/dist/data-table/index.cjs +6865 -0
- package/dist/data-table/index.cjs.map +1 -0
- package/dist/data-table/index.d.cts +27 -0
- package/dist/data-table/index.d.ts +27 -0
- package/dist/data-table/index.js +6869 -0
- package/dist/data-table/index.js.map +1 -0
- package/dist/data-table/infer-filter.cjs +114 -0
- package/dist/data-table/infer-filter.cjs.map +1 -0
- package/dist/data-table/infer-filter.d.cts +17 -0
- package/dist/data-table/infer-filter.d.ts +17 -0
- package/dist/data-table/infer-filter.js +92 -0
- package/dist/data-table/infer-filter.js.map +1 -0
- package/dist/data-table/layered-filters.cjs +249 -0
- package/dist/data-table/layered-filters.cjs.map +1 -0
- package/dist/data-table/layered-filters.d.cts +3 -0
- package/dist/data-table/layered-filters.d.ts +3 -0
- package/dist/data-table/layered-filters.js +229 -0
- package/dist/data-table/layered-filters.js.map +1 -0
- package/dist/data-table/pagination.cjs +595 -0
- package/dist/data-table/pagination.cjs.map +1 -0
- package/dist/data-table/pagination.d.cts +34 -0
- package/dist/data-table/pagination.d.ts +34 -0
- package/dist/data-table/pagination.js +563 -0
- package/dist/data-table/pagination.js.map +1 -0
- package/dist/data-table/query-control.cjs +129 -0
- package/dist/data-table/query-control.cjs.map +1 -0
- package/dist/data-table/query-control.d.cts +32 -0
- package/dist/data-table/query-control.d.ts +32 -0
- package/dist/data-table/query-control.js +107 -0
- package/dist/data-table/query-control.js.map +1 -0
- package/dist/data-table/scroll-pagination.cjs +222 -0
- package/dist/data-table/scroll-pagination.cjs.map +1 -0
- package/dist/data-table/scroll-pagination.d.cts +37 -0
- package/dist/data-table/scroll-pagination.d.ts +37 -0
- package/dist/data-table/scroll-pagination.js +202 -0
- package/dist/data-table/scroll-pagination.js.map +1 -0
- package/dist/data-table/types.cjs +19 -0
- package/dist/data-table/types.cjs.map +1 -0
- package/dist/data-table/types.d.cts +3 -0
- package/dist/data-table/types.d.ts +3 -0
- package/dist/data-table/types.js +1 -0
- package/dist/data-table/types.js.map +1 -0
- package/dist/data-table/url-state.cjs +201 -0
- package/dist/data-table/url-state.cjs.map +1 -0
- package/dist/data-table/url-state.d.cts +33 -0
- package/dist/data-table/url-state.d.ts +33 -0
- package/dist/data-table/url-state.js +184 -0
- package/dist/data-table/url-state.js.map +1 -0
- package/dist/data-table/uuid-cell.cjs +371 -0
- package/dist/data-table/uuid-cell.cjs.map +1 -0
- package/dist/data-table/uuid-cell.d.cts +31 -0
- package/dist/data-table/uuid-cell.d.ts +31 -0
- package/dist/data-table/uuid-cell.js +345 -0
- package/dist/data-table/uuid-cell.js.map +1 -0
- package/dist/data-table/xlsx.cjs +100 -0
- package/dist/data-table/xlsx.cjs.map +1 -0
- package/dist/data-table/xlsx.d.cts +16 -0
- package/dist/data-table/xlsx.d.ts +16 -0
- package/dist/data-table/xlsx.js +70 -0
- package/dist/data-table/xlsx.js.map +1 -0
- package/dist/index.cjs +10 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/dist/styles.css +22 -0
- package/dist/types-ClaxTaXq.d.ts +798 -0
- package/dist/types-XXbVB1sh.d.cts +798 -0
- package/package.json +164 -1
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
"use client";
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
|
+
|
|
32
|
+
// src/data-table/DataRowInspector.tsx
|
|
33
|
+
var DataRowInspector_exports = {};
|
|
34
|
+
__export(DataRowInspector_exports, {
|
|
35
|
+
DataRowInspector: () => DataRowInspector
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(DataRowInspector_exports);
|
|
38
|
+
|
|
39
|
+
// src/cn.ts
|
|
40
|
+
var import_clsx = require("clsx");
|
|
41
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
42
|
+
function cn(...inputs) {
|
|
43
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/data-table/copy.tsx
|
|
47
|
+
var import_react3 = require("react");
|
|
48
|
+
var import_clipboard = require("@ai-matrx/kit/clipboard");
|
|
49
|
+
|
|
50
|
+
// src/button.tsx
|
|
51
|
+
var import_react_slot = require("@radix-ui/react-slot");
|
|
52
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
53
|
+
var React = __toESM(require("react"), 1);
|
|
54
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
55
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
56
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
57
|
+
{
|
|
58
|
+
variants: {
|
|
59
|
+
variant: {
|
|
60
|
+
default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
|
|
61
|
+
/**
|
|
62
|
+
* An explicit spelling of `default`, identical by construction. It is
|
|
63
|
+
* not decoration: matrx-frontend's `ButtonMine` fork carried it, ~17
|
|
64
|
+
* call sites say `variant="primary"`, and the alternative to keeping
|
|
65
|
+
* the word was a host shim translating a prop — the massage C22 bans.
|
|
66
|
+
*/
|
|
67
|
+
primary: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
|
|
68
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
69
|
+
/** The affirmative twin of `destructive` — confirm, approve, publish. */
|
|
70
|
+
success: "bg-success text-success-foreground shadow-sm hover:bg-success/90",
|
|
71
|
+
outline: "border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
72
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
73
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
74
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
75
|
+
subtle: "border border-transparent bg-muted/50 text-foreground hover:border-border hover:bg-muted"
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* ONE size scale, xs → 3xl, plus the two icon boxes. The top and bottom
|
|
79
|
+
* of the scale came in from matrx-frontend's `ButtonMine` fork (2026-09-07):
|
|
80
|
+
* a dense toolbar needs `xs`, and a marketing/hero call to action needs
|
|
81
|
+
* `xl`+. A host that has to reach outside this scale forks the button,
|
|
82
|
+
* which is exactly how `ButtonMine` was born.
|
|
83
|
+
*/
|
|
84
|
+
size: {
|
|
85
|
+
xs: "h-6 rounded-md px-1 text-xs",
|
|
86
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
87
|
+
default: "h-9 px-4 py-2",
|
|
88
|
+
/** An explicit spelling of `default` (the fork's middle rung). */
|
|
89
|
+
md: "h-9 px-4 py-2",
|
|
90
|
+
lg: "h-10 rounded-md px-6",
|
|
91
|
+
xl: "h-12 px-8 py-3 text-base",
|
|
92
|
+
"2xl": "h-14 px-10 py-3 text-base",
|
|
93
|
+
"3xl": "h-16 px-12 py-3 text-base",
|
|
94
|
+
icon: "h-9 w-9",
|
|
95
|
+
"icon-sm": "h-7 w-7",
|
|
96
|
+
/** A circular icon box — an avatar-shaped control, not a square one. */
|
|
97
|
+
roundIcon: "h-8 w-8 rounded-full p-0"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
defaultVariants: {
|
|
101
|
+
variant: "default",
|
|
102
|
+
size: "default"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
var Button = React.forwardRef(
|
|
107
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
108
|
+
const Component = asChild ? import_react_slot.Slot : "button";
|
|
109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
110
|
+
Component,
|
|
111
|
+
{
|
|
112
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
113
|
+
ref,
|
|
114
|
+
...props
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
Button.displayName = "Button";
|
|
120
|
+
|
|
121
|
+
// src/popover.tsx
|
|
122
|
+
var PopoverPrimitive = __toESM(require("@radix-ui/react-popover"), 1);
|
|
123
|
+
var React3 = __toESM(require("react"), 1);
|
|
124
|
+
|
|
125
|
+
// src/motion.ts
|
|
126
|
+
var MOTION_OVERLAY = "matrx-motion-overlay";
|
|
127
|
+
var MOTION_DIALOG = "matrx-motion-dialog";
|
|
128
|
+
var MOTION_BOTTOM_SHEET = "matrx-motion-bottom-sheet";
|
|
129
|
+
var MOTION_POPPER = "matrx-motion-popper";
|
|
130
|
+
var MOTION_SHEET = {
|
|
131
|
+
top: "matrx-motion-sheet-top",
|
|
132
|
+
bottom: "matrx-motion-sheet-bottom",
|
|
133
|
+
left: "matrx-motion-sheet-left",
|
|
134
|
+
right: "matrx-motion-sheet-right",
|
|
135
|
+
center: "matrx-motion-sheet-center"
|
|
136
|
+
};
|
|
137
|
+
var MOTION_PULSE = "matrx-pulse";
|
|
138
|
+
var MOTION_SPIN = "matrx-spin";
|
|
139
|
+
var ALL_MOTION_CLASSES = [
|
|
140
|
+
MOTION_OVERLAY,
|
|
141
|
+
MOTION_DIALOG,
|
|
142
|
+
MOTION_BOTTOM_SHEET,
|
|
143
|
+
MOTION_POPPER,
|
|
144
|
+
...Object.values(MOTION_SHEET),
|
|
145
|
+
MOTION_PULSE,
|
|
146
|
+
MOTION_SPIN
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
// src/portal-container.tsx
|
|
150
|
+
var React2 = __toESM(require("react"), 1);
|
|
151
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
152
|
+
var CONTEXT_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.portal-container-context");
|
|
153
|
+
var contextRegistry = globalThis;
|
|
154
|
+
var PortalContainerContext = contextRegistry[CONTEXT_SLOT] ??= React2.createContext(void 0);
|
|
155
|
+
function PortalContainerProvider({
|
|
156
|
+
container,
|
|
157
|
+
children
|
|
158
|
+
}) {
|
|
159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PortalContainerContext.Provider, { value: container ?? void 0, children });
|
|
160
|
+
}
|
|
161
|
+
function usePortalContainer(explicit) {
|
|
162
|
+
const injected = React2.useContext(PortalContainerContext);
|
|
163
|
+
if (explicit !== void 0) {
|
|
164
|
+
return explicit ?? void 0;
|
|
165
|
+
}
|
|
166
|
+
return injected ?? void 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/popover.tsx
|
|
170
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
171
|
+
var Popover = PopoverPrimitive.Root;
|
|
172
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
173
|
+
var PopoverContent = React3.forwardRef(
|
|
174
|
+
({
|
|
175
|
+
className,
|
|
176
|
+
align = "center",
|
|
177
|
+
sideOffset = 4,
|
|
178
|
+
container,
|
|
179
|
+
animated = true,
|
|
180
|
+
...props
|
|
181
|
+
}, ref) => {
|
|
182
|
+
const portalContainer = usePortalContainer(container);
|
|
183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PopoverPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
184
|
+
PopoverPrimitive.Content,
|
|
185
|
+
{
|
|
186
|
+
ref,
|
|
187
|
+
align,
|
|
188
|
+
sideOffset,
|
|
189
|
+
className: cn(
|
|
190
|
+
// Cap to the viewport space Radix measured and scroll — a popover taller
|
|
191
|
+
// than the screen must never trap the user with unreachable content.
|
|
192
|
+
// z must EQUAL the dialog layer (z-[10000]), never exceed it: with equal
|
|
193
|
+
// z, DOM portal order decides, so a dialog opened FROM a popover stacks
|
|
194
|
+
// above it, and a popover opened from a dialog still stacks above the
|
|
195
|
+
// dialog. z-[10001] buried dialogs behind fullscreen popovers.
|
|
196
|
+
"z-[10000] w-72 max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
197
|
+
animated && MOTION_POPPER,
|
|
198
|
+
className
|
|
199
|
+
),
|
|
200
|
+
...props
|
|
201
|
+
}
|
|
202
|
+
) });
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
206
|
+
|
|
207
|
+
// src/dialog.tsx
|
|
208
|
+
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
209
|
+
var VisuallyHidden = __toESM(require("@radix-ui/react-visually-hidden"), 1);
|
|
210
|
+
var import_react_tree = require("@ai-matrx/kit/react-tree");
|
|
211
|
+
var React6 = __toESM(require("react"), 1);
|
|
212
|
+
|
|
213
|
+
// src/icons.tsx
|
|
214
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
215
|
+
function lucideProps(props) {
|
|
216
|
+
return {
|
|
217
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
218
|
+
viewBox: "0 0 24 24",
|
|
219
|
+
fill: "none",
|
|
220
|
+
stroke: "currentColor",
|
|
221
|
+
strokeWidth: 2,
|
|
222
|
+
strokeLinecap: "round",
|
|
223
|
+
strokeLinejoin: "round",
|
|
224
|
+
"aria-hidden": true,
|
|
225
|
+
...props
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function XIcon(props) {
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...lucideProps(props), children: [
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 6 6 18" }),
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "m6 6 12 12" })
|
|
232
|
+
] });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/radix-dialog-modal-context.tsx
|
|
236
|
+
var React4 = __toESM(require("react"), 1);
|
|
237
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
238
|
+
var CONTEXT_SLOT2 = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.dialog-modal-context");
|
|
239
|
+
var contextRegistry2 = globalThis;
|
|
240
|
+
var RadixDialogModalContext = contextRegistry2[CONTEXT_SLOT2] ??= React4.createContext(true);
|
|
241
|
+
function RadixDialogModalProvider({
|
|
242
|
+
children,
|
|
243
|
+
modal
|
|
244
|
+
}) {
|
|
245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RadixDialogModalContext.Provider, { value: modal, children });
|
|
246
|
+
}
|
|
247
|
+
function useRadixDialogModal() {
|
|
248
|
+
return React4.useContext(RadixDialogModalContext);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/use-is-mobile.ts
|
|
252
|
+
var React5 = __toESM(require("react"), 1);
|
|
253
|
+
var MOBILE_BREAKPOINT = 768;
|
|
254
|
+
function useIsMobile() {
|
|
255
|
+
const [isMobile, setIsMobile] = React5.useState(false);
|
|
256
|
+
const [hasMounted, setHasMounted] = React5.useState(false);
|
|
257
|
+
React5.useEffect(() => {
|
|
258
|
+
setHasMounted(true);
|
|
259
|
+
const onChange = () => {
|
|
260
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
261
|
+
};
|
|
262
|
+
onChange();
|
|
263
|
+
if (typeof window.matchMedia !== "function") {
|
|
264
|
+
return void 0;
|
|
265
|
+
}
|
|
266
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
267
|
+
mql.addEventListener("change", onChange);
|
|
268
|
+
return () => mql.removeEventListener("change", onChange);
|
|
269
|
+
}, []);
|
|
270
|
+
if (!hasMounted) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
return isMobile;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// src/dialog.tsx
|
|
277
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
278
|
+
var Dialog = ({
|
|
279
|
+
children,
|
|
280
|
+
...props
|
|
281
|
+
}) => {
|
|
282
|
+
const modal = props.modal ?? true;
|
|
283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RadixDialogModalProvider, { modal, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogPrimitive.Root, { ...props, modal, children }) });
|
|
284
|
+
};
|
|
285
|
+
Dialog.displayName = "Dialog";
|
|
286
|
+
var DialogPortal = ({
|
|
287
|
+
container,
|
|
288
|
+
...props
|
|
289
|
+
}) => {
|
|
290
|
+
const resolved = usePortalContainer(container);
|
|
291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogPrimitive.Portal, { container: resolved ?? null, ...props });
|
|
292
|
+
};
|
|
293
|
+
DialogPortal.displayName = "DialogPortal";
|
|
294
|
+
var CONTEXT_SLOT3 = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.dialog-container-context");
|
|
295
|
+
var contextRegistry3 = globalThis;
|
|
296
|
+
var DialogContainerContext = contextRegistry3[CONTEXT_SLOT3] ??= React6.createContext(null);
|
|
297
|
+
var DialogOverlay = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
298
|
+
DialogPrimitive.Overlay,
|
|
299
|
+
{
|
|
300
|
+
ref,
|
|
301
|
+
"data-slot": "dialog-overlay",
|
|
302
|
+
className: cn(
|
|
303
|
+
// Page context behind the modal stays readable; separation comes from a
|
|
304
|
+
// light token scrim, not a blur.
|
|
305
|
+
"fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim-soft)]",
|
|
306
|
+
MOTION_OVERLAY,
|
|
307
|
+
className
|
|
308
|
+
),
|
|
309
|
+
...props
|
|
310
|
+
}
|
|
311
|
+
));
|
|
312
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
313
|
+
var DialogContentPrimitive = React6.forwardRef((props, ref) => {
|
|
314
|
+
const isModal = useRadixDialogModal();
|
|
315
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
316
|
+
DialogPrimitive.Content,
|
|
317
|
+
{
|
|
318
|
+
...props,
|
|
319
|
+
ref,
|
|
320
|
+
"aria-modal": isModal || void 0
|
|
321
|
+
}
|
|
322
|
+
);
|
|
323
|
+
});
|
|
324
|
+
DialogContentPrimitive.displayName = "DialogContentPrimitive";
|
|
325
|
+
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";
|
|
326
|
+
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";
|
|
327
|
+
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";
|
|
328
|
+
var DialogContent = React6.forwardRef(
|
|
329
|
+
({
|
|
330
|
+
className,
|
|
331
|
+
children,
|
|
332
|
+
mobileSheet = true,
|
|
333
|
+
animated = true,
|
|
334
|
+
showCloseButton = true,
|
|
335
|
+
container,
|
|
336
|
+
...props
|
|
337
|
+
}, ref) => {
|
|
338
|
+
const isMobile = useIsMobile();
|
|
339
|
+
const isModal = useRadixDialogModal();
|
|
340
|
+
const injectedContainer = usePortalContainer(container);
|
|
341
|
+
const asSheet = mobileSheet && isMobile;
|
|
342
|
+
const [containerEl, setContainerEl] = React6.useState(
|
|
343
|
+
null
|
|
344
|
+
);
|
|
345
|
+
const mergedRef = React6.useCallback(
|
|
346
|
+
(node) => {
|
|
347
|
+
setContainerEl(node);
|
|
348
|
+
if (typeof ref === "function") ref(node);
|
|
349
|
+
else if (ref)
|
|
350
|
+
ref.current = node;
|
|
351
|
+
},
|
|
352
|
+
[ref]
|
|
353
|
+
);
|
|
354
|
+
const hasTitle = (0, import_react_tree.treeContainsComponent)(children, DialogTitle) || (0, import_react_tree.treeContainsComponent)(children, DialogPrimitive.Title);
|
|
355
|
+
const hasDescription = (0, import_react_tree.treeContainsComponent)(children, DialogDescription) || (0, import_react_tree.treeContainsComponent)(children, DialogPrimitive.Description);
|
|
356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(DialogPortal, { container, children: [
|
|
357
|
+
isModal ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogOverlay, {}) : null,
|
|
358
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
359
|
+
DialogContentPrimitive,
|
|
360
|
+
{
|
|
361
|
+
ref: mergedRef,
|
|
362
|
+
"data-slot": "dialog-content",
|
|
363
|
+
className: cn(
|
|
364
|
+
asSheet ? DIALOG_MOBILE_SHEET_CLASSES : DIALOG_DESKTOP_CLASSES,
|
|
365
|
+
animated && (asSheet ? MOTION_BOTTOM_SHEET : MOTION_DIALOG),
|
|
366
|
+
className,
|
|
367
|
+
asSheet && DIALOG_MOBILE_SHEET_OVERRIDE,
|
|
368
|
+
// A non-modal dialog is the coexistence contract for content that
|
|
369
|
+
// can sit beside a host's floating window manager (which starts at
|
|
370
|
+
// z=1000); staying below that boundary makes a newly focused window
|
|
371
|
+
// usable without coupling the two systems.
|
|
372
|
+
!isModal && "z-[900]"
|
|
373
|
+
),
|
|
374
|
+
...hasDescription ? {} : { "aria-describedby": void 0 },
|
|
375
|
+
...props,
|
|
376
|
+
children: [
|
|
377
|
+
hasTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VisuallyHidden.Root, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogPrimitive.Title, { children: "Dialog" }) }),
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogContainerContext.Provider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
379
|
+
PortalContainerProvider,
|
|
380
|
+
{
|
|
381
|
+
container: containerEl ?? injectedContainer ?? null,
|
|
382
|
+
children
|
|
383
|
+
}
|
|
384
|
+
) }),
|
|
385
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
386
|
+
DialogPrimitive.Close,
|
|
387
|
+
{
|
|
388
|
+
"data-slot": "dialog-close",
|
|
389
|
+
"aria-label": "Close",
|
|
390
|
+
className: "absolute right-2 top-4 flex h-11 w-11 items-center justify-center rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground sm:right-4 lg:h-10 lg:w-10",
|
|
391
|
+
children: [
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(XIcon, { className: "h-4 w-4" }),
|
|
393
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sr-only", children: "Close" })
|
|
394
|
+
]
|
|
395
|
+
}
|
|
396
|
+
) : null
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
)
|
|
400
|
+
] });
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
404
|
+
var DialogHeader = ({
|
|
405
|
+
className,
|
|
406
|
+
...props
|
|
407
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
408
|
+
"div",
|
|
409
|
+
{
|
|
410
|
+
"data-slot": "dialog-header",
|
|
411
|
+
className: cn(
|
|
412
|
+
// DialogContent owns an absolute close control. Reserve its hit area in
|
|
413
|
+
// every header so trailing actions never render underneath it.
|
|
414
|
+
"flex flex-col space-y-1.5 pr-12 text-center sm:text-left",
|
|
415
|
+
className
|
|
416
|
+
),
|
|
417
|
+
...props
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
DialogHeader.displayName = "DialogHeader";
|
|
421
|
+
var DialogFooter = ({
|
|
422
|
+
className,
|
|
423
|
+
...props
|
|
424
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
425
|
+
"div",
|
|
426
|
+
{
|
|
427
|
+
"data-slot": "dialog-footer",
|
|
428
|
+
className: cn(
|
|
429
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
430
|
+
// Ruling 3/4 — sticky to the card edges so a scrolled body never shows
|
|
431
|
+
// through under the actions, and safe-area padded on a phone.
|
|
432
|
+
//
|
|
433
|
+
// 🚨 THERE IS NO `mb-[…]` HERE, AND THERE MUST NEVER BE ONE AGAIN
|
|
434
|
+
// (0.11.3, feedback bf8fb00b). The bleed over the card's bottom padding
|
|
435
|
+
// used to be a NEGATIVE BLOCK MARGIN, which makes this box taller than
|
|
436
|
+
// the grid area the card allocates it — and `position: sticky` CLAMPS a
|
|
437
|
+
// box to its containing block, so the browser yanked the footer UP by
|
|
438
|
+
// `--dialog-pad` against the card's `gap-4` and painted 8px of opaque
|
|
439
|
+
// footer over the last line of the consequence, at every length. The
|
|
440
|
+
// card now RESERVES this footer's block size instead (`matrx-dialog-card`
|
|
441
|
+
// in styles.css hands over its `padding-bottom`), so the bleed costs no
|
|
442
|
+
// margin at all. Guard: `sticky-footer-geometry.test.tsx`.
|
|
443
|
+
//
|
|
444
|
+
// These stay UTILITIES rather than a shipped rule so a caller's
|
|
445
|
+
// `className` still wins through tailwind-merge — a shipped rule would
|
|
446
|
+
// have to be unlayered to survive Tailwind preflight (§ THE PREFLIGHT
|
|
447
|
+
// RULE in styles.css) and would then override every caller's padding.
|
|
448
|
+
"sticky bottom-0 z-10 bg-background pt-3",
|
|
449
|
+
"mx-[calc(var(--dialog-pad,0px)*-1)] px-[var(--dialog-pad,0px)] pb-[var(--dialog-pad,0px)]",
|
|
450
|
+
className
|
|
451
|
+
),
|
|
452
|
+
...props
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
DialogFooter.displayName = "DialogFooter";
|
|
456
|
+
var DialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
457
|
+
DialogPrimitive.Title,
|
|
458
|
+
{
|
|
459
|
+
ref,
|
|
460
|
+
"data-slot": "dialog-title",
|
|
461
|
+
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
462
|
+
...props
|
|
463
|
+
}
|
|
464
|
+
));
|
|
465
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
466
|
+
var DialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
467
|
+
DialogPrimitive.Description,
|
|
468
|
+
{
|
|
469
|
+
ref,
|
|
470
|
+
"data-slot": "dialog-description",
|
|
471
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
472
|
+
...props
|
|
473
|
+
}
|
|
474
|
+
));
|
|
475
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
476
|
+
|
|
477
|
+
// src/data-table/icons.tsx
|
|
478
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
479
|
+
function Icon({ children, ...props }) {
|
|
480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", ...props, children });
|
|
481
|
+
}
|
|
482
|
+
var Check = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m5 12 4 4L19 6" }) });
|
|
483
|
+
var SlidersHorizontal = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M4 7h16M4 17h16M9 7v0M15 17v0" }) });
|
|
484
|
+
var PanelRight = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Icon, { ...p, children: [
|
|
485
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2" }),
|
|
486
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 4v16" })
|
|
487
|
+
] });
|
|
488
|
+
var ExternalLink = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M14 4h6v6M20 4l-9 9M19 13v6H5V5h6" }) });
|
|
489
|
+
var Copy = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Icon, { ...p, children: [
|
|
490
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "9", y: "9", width: "11", height: "11", rx: "2" }),
|
|
491
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3" })
|
|
492
|
+
] });
|
|
493
|
+
var Lightbulb = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 18h6M10 22h4M8 14a6 6 0 1 1 8 0c-1 1-1 2-1 3H9c0-1 0-2-1-3z" }) });
|
|
494
|
+
var ShieldOff = (p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m3 3 18 18M12 3l7 3v5c0 4-3 7-7 9-4-2-7-5-7-9V6l4-2" }) });
|
|
495
|
+
|
|
496
|
+
// src/data-table/host.tsx
|
|
497
|
+
var import_react = require("react");
|
|
498
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
499
|
+
var HOST_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.table-host-context");
|
|
500
|
+
var hostRegistry = globalThis;
|
|
501
|
+
var HostContext = hostRegistry[HOST_SLOT] ??= (0, import_react.createContext)({});
|
|
502
|
+
function useMatrxDataTableHost() {
|
|
503
|
+
return (0, import_react.useContext)(HostContext);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/data-table/useTableNotice.tsx
|
|
507
|
+
var import_react2 = require("react");
|
|
508
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
509
|
+
function useTableNotice() {
|
|
510
|
+
const host = useMatrxDataTableHost();
|
|
511
|
+
const [message, setMessage] = (0, import_react2.useState)(null);
|
|
512
|
+
const notify = {
|
|
513
|
+
success(text) {
|
|
514
|
+
if (host.notify) host.notify.success(text);
|
|
515
|
+
else setMessage({ text, error: false });
|
|
516
|
+
},
|
|
517
|
+
error(text) {
|
|
518
|
+
if (host.notify) host.notify.error(text);
|
|
519
|
+
else setMessage({ text, error: true });
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
const notice = message ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { role: message.error ? "alert" : "status", className: message.error ? "text-xs text-destructive" : "text-xs text-muted-foreground", children: [
|
|
523
|
+
message.text,
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-label": "Dismiss notification", className: "ml-2 underline", onClick: () => setMessage(null), children: "Dismiss" })
|
|
525
|
+
] }) : null;
|
|
526
|
+
return { notify, notice };
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// src/data-table/copy-payload.ts
|
|
530
|
+
function tableAgentText(value) {
|
|
531
|
+
if (typeof value === "string") return value;
|
|
532
|
+
const attributes = Object.entries(value.attributes ?? {}).filter(([, entry]) => entry !== null && entry !== void 0 && entry !== "").map(([key, entry]) => ` ${key}="${String(entry)}"`).join("");
|
|
533
|
+
const context = Object.entries(value.context ?? {}).filter(([, entry]) => entry !== null && entry !== void 0 && entry !== "").map(([key, entry]) => `<${key}>${String(entry)}</${key}>`).join("\n");
|
|
534
|
+
const url = typeof window === "undefined" ? "" : window.location.href;
|
|
535
|
+
const route = typeof window === "undefined" ? "" : window.location.pathname;
|
|
536
|
+
return `<${value.kind}${attributes}>
|
|
537
|
+
<context>
|
|
538
|
+
<location>${value.location}</location>
|
|
539
|
+
${url ? `<url>${url}</url>` : ""}
|
|
540
|
+
${route ? `<route>${route}</route>` : ""}
|
|
541
|
+
<copied>${value.description}</copied>
|
|
542
|
+
<copied-at>${(/* @__PURE__ */ new Date()).toISOString()}</copied-at>
|
|
543
|
+
${context}
|
|
544
|
+
</context>
|
|
545
|
+
${value.summary ? `<summary>
|
|
546
|
+
${value.summary}
|
|
547
|
+
</summary>
|
|
548
|
+
` : ""}<data format="json">
|
|
549
|
+
\`\`\`json
|
|
550
|
+
${JSON.stringify(value.data, null, 2)}
|
|
551
|
+
\`\`\`
|
|
552
|
+
</data>
|
|
553
|
+
</${value.kind}>`;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/data-table/copy.tsx
|
|
557
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
558
|
+
function resolve(value) {
|
|
559
|
+
return typeof value === "function" ? value() : value;
|
|
560
|
+
}
|
|
561
|
+
function download(item) {
|
|
562
|
+
if (!item.build) throw new Error(`No export action is available for ${item.label}.`);
|
|
563
|
+
const file = item.build();
|
|
564
|
+
const url = URL.createObjectURL(new Blob([file.content], { type: file.mime }));
|
|
565
|
+
try {
|
|
566
|
+
const link = document.createElement("a");
|
|
567
|
+
link.href = url;
|
|
568
|
+
link.download = `${item.label.replace(/[^a-z0-9]+/gi, "-")}.${file.extension}`;
|
|
569
|
+
document.body.append(link);
|
|
570
|
+
link.click();
|
|
571
|
+
link.remove();
|
|
572
|
+
} finally {
|
|
573
|
+
URL.revokeObjectURL(url);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
function CopyButtons(props) {
|
|
577
|
+
const { CopyControls } = useMatrxDataTableHost();
|
|
578
|
+
if (CopyControls) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CopyControls, { ...props });
|
|
579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DefaultCopyButtons, { ...props });
|
|
580
|
+
}
|
|
581
|
+
function DefaultCopyButtons({ human, agent, json, label, size = "icon", appearance = "segmented", disabled = false, stopPropagation = true, className, aiVariants = [], agentVariant, aiCustom, export: exportConfig, hide }) {
|
|
582
|
+
const { notify, notice } = useTableNotice();
|
|
583
|
+
const clipboard = (0, import_clipboard.useClipboard)({ notify: (message, kind) => notify[kind](message) });
|
|
584
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
585
|
+
const [modal, setModal] = (0, import_react3.useState)(null);
|
|
586
|
+
const run = async (operation) => {
|
|
587
|
+
if (busy) return;
|
|
588
|
+
setBusy(true);
|
|
589
|
+
try {
|
|
590
|
+
await operation();
|
|
591
|
+
} catch (error) {
|
|
592
|
+
notify.error(error instanceof Error ? error.message : String(error));
|
|
593
|
+
} finally {
|
|
594
|
+
setBusy(false);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
const faithfulAgent = agent === void 0 ? [] : [{
|
|
598
|
+
id: agentVariant?.id ?? "copy-for-ai",
|
|
599
|
+
label: agentVariant?.label ?? "Copy for AI",
|
|
600
|
+
...agentVariant?.hint === void 0 ? {} : { hint: agentVariant.hint },
|
|
601
|
+
section: "ai",
|
|
602
|
+
build: () => resolve(agent)
|
|
603
|
+
}];
|
|
604
|
+
const orderedAgent = agentVariant?.position === "last" ? [...aiVariants, ...faithfulAgent] : [...faithfulAgent, ...aiVariants];
|
|
605
|
+
const variants = [
|
|
606
|
+
...json === void 0 ? [] : [{ id: "json", label: "Copy JSON", section: "copy", build: () => JSON.stringify(resolve(json), null, 2) }],
|
|
607
|
+
...orderedAgent
|
|
608
|
+
].filter((variant) => !hide?.includes(variant.section ?? "ai"));
|
|
609
|
+
const exports = hide?.includes("export") ? void 0 : exportConfig;
|
|
610
|
+
const showCustom = aiCustom && !hide?.includes("ai");
|
|
611
|
+
const buttonClass = `${size === "xs" ? "h-8 w-8 lg:h-5 lg:w-8" : ""} ${appearance === "bare" ? "border-0 bg-transparent shadow-none" : ""}`;
|
|
612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: `inline-flex flex-wrap items-center gap-0.5 ${className ?? ""}`, onClick: stopPropagation ? (event) => event.stopPropagation() : void 0, children: [
|
|
613
|
+
human !== void 0 && !hide?.includes("copy") ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "icon", className: buttonClass, disabled: disabled || busy, "aria-label": `Copy ${label}`, onClick: () => void run(() => clipboard.copyText(resolve(human), `${label} copied`)), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Copy, { className: "h-3.5 w-3.5" }) }) : null,
|
|
614
|
+
variants.length > 0 || showCustom || exports ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Popover, { children: [
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "icon", className: buttonClass, disabled: disabled || busy, "aria-label": `Copy ${label} for AI or export`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SlidersHorizontal, { className: "h-3.5 w-3.5" }) }) }),
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(PopoverContent, { align: "end", className: "w-64 p-1", children: [
|
|
617
|
+
variants.map((variant) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full justify-start", disabled: busy, onClick: () => void run(async () => {
|
|
618
|
+
if (variant.onSelect) variant.onSelect();
|
|
619
|
+
else if (variant.modal) setModal(variant.id);
|
|
620
|
+
else if (variant.build) await clipboard.copyText(tableAgentText(await variant.build()), variant.successMessage ?? `${label} copied`);
|
|
621
|
+
else throw new Error(`No copy action is available for ${variant.label}.`);
|
|
622
|
+
}), children: variant.label }, variant.id)),
|
|
623
|
+
showCustom ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full justify-start", onClick: () => setModal("custom"), children: aiCustom.label ?? "Custom copy\u2026" }) : null,
|
|
624
|
+
exports?.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full justify-start", disabled: busy, onClick: () => void run(async () => {
|
|
625
|
+
if (item.onSelect) await item.onSelect();
|
|
626
|
+
else download(item);
|
|
627
|
+
}), children: item.label }, item.id)),
|
|
628
|
+
exports?.sheetRows ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full justify-start", onClick: () => void run(async () => {
|
|
629
|
+
const rows = exports.sheetRows?.();
|
|
630
|
+
if (!rows) return;
|
|
631
|
+
const keys = [...new Set(rows.flatMap((row) => Object.keys(row)))];
|
|
632
|
+
const value = (input) => String(input ?? "").replace(/[\t\r\n]+/g, " ");
|
|
633
|
+
await clipboard.copyText([keys.map(value).join(" "), ...rows.map((row) => keys.map((key) => value(row[key])).join(" "))].join("\n"), "Copied for pasting into Google Sheets");
|
|
634
|
+
}), children: "Copy for Google Sheets" }) : null
|
|
635
|
+
] })
|
|
636
|
+
] }) : null,
|
|
637
|
+
variants.map((variant) => variant.modal && modal === variant.id ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: variant.modal({ open: true, onOpenChange: (open) => setModal(open ? variant.id : null) }) }, variant.id) : null),
|
|
638
|
+
modal === "custom" && aiCustom ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CustomCopy, { source: aiCustom, onClose: () => setModal(null) }) : null,
|
|
639
|
+
notice
|
|
640
|
+
] });
|
|
641
|
+
}
|
|
642
|
+
function CustomCopy({ source, onClose }) {
|
|
643
|
+
const [values, setValues] = (0, import_react3.useState)(() => Object.fromEntries(source.options.map((option) => [option.key, option.default])));
|
|
644
|
+
const { notify, notice } = useTableNotice();
|
|
645
|
+
const clipboard = (0, import_clipboard.useClipboard)({ notify: (message, kind) => notify[kind](message) });
|
|
646
|
+
let text = "";
|
|
647
|
+
let error = null;
|
|
648
|
+
try {
|
|
649
|
+
const built = source.build(values);
|
|
650
|
+
text = tableAgentText(source.wrap(built.text, values, built.meta));
|
|
651
|
+
} catch (raw) {
|
|
652
|
+
error = raw instanceof Error ? raw.message : String(raw);
|
|
653
|
+
}
|
|
654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Dialog, { open: true, onOpenChange: (open) => {
|
|
655
|
+
if (!open) onClose();
|
|
656
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(DialogContent, { children: [
|
|
657
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogTitle, { children: source.dialogTitle ?? "Custom copy" }) }),
|
|
658
|
+
source.dialogDescription ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm", children: source.dialogDescription }) : null,
|
|
659
|
+
source.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center justify-between gap-3 text-sm", children: [
|
|
660
|
+
option.label,
|
|
661
|
+
option.kind === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "checkbox", checked: values[option.key] === true, onChange: (e) => setValues({ ...values, [option.key]: e.target.checked }) }) : option.kind === "preset" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": option.label, value: Number(values[option.key]), onChange: (e) => setValues({ ...values, [option.key]: Number(e.target.value) }), children: option.options.map((choice) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: choice.value, children: choice.label }, choice.value)) }) : option.kind === "slider" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { "aria-label": option.label, type: "range", min: 0, max: option.stops.length - 1, step: 1, value: Math.max(0, option.stops.indexOf(Number(values[option.key]))), onChange: (e) => setValues({ ...values, [option.key]: option.stops[Number(e.target.value)] ?? option.default }) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex gap-1", children: [
|
|
662
|
+
option.presets?.map((choice) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", size: "sm", variant: "outline", onClick: () => setValues({ ...values, [option.key]: choice.value }), children: choice.label }, choice.value)),
|
|
663
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { "aria-label": option.label, type: "number", value: Number(values[option.key]), min: option.min, step: option.step, onChange: (e) => {
|
|
664
|
+
if (Number.isFinite(e.target.valueAsNumber)) setValues({ ...values, [option.key]: e.target.valueAsNumber });
|
|
665
|
+
} })
|
|
666
|
+
] })
|
|
667
|
+
] }, option.key)),
|
|
668
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-destructive", children: error }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap text-xs", children: text }),
|
|
669
|
+
notice,
|
|
670
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(DialogFooter, { children: [
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", variant: "outline", onClick: onClose, children: "Close" }),
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { type: "button", disabled: error !== null, onClick: () => void clipboard.copyText(text, "Custom copy copied"), children: "Copy" })
|
|
673
|
+
] })
|
|
674
|
+
] }) });
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/data-table/MatrxUuidCell.tsx
|
|
678
|
+
var import_react4 = require("react");
|
|
679
|
+
|
|
680
|
+
// src/tooltip.tsx
|
|
681
|
+
var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
|
|
682
|
+
var React7 = __toESM(require("react"), 1);
|
|
683
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
684
|
+
var TooltipProvider = TooltipPrimitive.Provider;
|
|
685
|
+
var Tooltip = TooltipPrimitive.Root;
|
|
686
|
+
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
687
|
+
var TooltipContent = React7.forwardRef(({ className, sideOffset = 4, container, animated = true, ...props }, ref) => {
|
|
688
|
+
const resolved = usePortalContainer(container);
|
|
689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TooltipPrimitive.Portal, { container: resolved ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
690
|
+
TooltipPrimitive.Content,
|
|
691
|
+
{
|
|
692
|
+
ref,
|
|
693
|
+
"data-slot": "tooltip-content",
|
|
694
|
+
sideOffset,
|
|
695
|
+
className: cn(
|
|
696
|
+
"z-[10001] overflow-hidden rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md",
|
|
697
|
+
animated && MOTION_POPPER,
|
|
698
|
+
className
|
|
699
|
+
),
|
|
700
|
+
...props
|
|
701
|
+
}
|
|
702
|
+
) });
|
|
703
|
+
});
|
|
704
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
705
|
+
|
|
706
|
+
// src/data-table/MatrxUuidCell.tsx
|
|
707
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
708
|
+
var SHORT_LEN = 8;
|
|
709
|
+
function shortUuid(id, len = SHORT_LEN) {
|
|
710
|
+
return id.slice(0, len);
|
|
711
|
+
}
|
|
712
|
+
async function copyText(text) {
|
|
713
|
+
try {
|
|
714
|
+
if (navigator.clipboard?.writeText) {
|
|
715
|
+
await navigator.clipboard.writeText(text);
|
|
716
|
+
return true;
|
|
717
|
+
}
|
|
718
|
+
} catch {
|
|
719
|
+
}
|
|
720
|
+
try {
|
|
721
|
+
const ta = document.createElement("textarea");
|
|
722
|
+
ta.value = text;
|
|
723
|
+
ta.style.position = "fixed";
|
|
724
|
+
ta.style.opacity = "0";
|
|
725
|
+
document.body.appendChild(ta);
|
|
726
|
+
ta.select();
|
|
727
|
+
const ok = document.execCommand("copy");
|
|
728
|
+
document.body.removeChild(ta);
|
|
729
|
+
return ok;
|
|
730
|
+
} catch {
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
function MatrxUuidCell({
|
|
735
|
+
value,
|
|
736
|
+
label,
|
|
737
|
+
onOpen,
|
|
738
|
+
href,
|
|
739
|
+
token,
|
|
740
|
+
forbidden = false,
|
|
741
|
+
className,
|
|
742
|
+
trailing
|
|
743
|
+
}) {
|
|
744
|
+
const { resolveEntityDoors, ResourcePeek } = useMatrxDataTableHost();
|
|
745
|
+
const { notify, notice } = useTableNotice();
|
|
746
|
+
const [copied, setCopied] = (0, import_react4.useState)(false);
|
|
747
|
+
const [opening, setOpening] = (0, import_react4.useState)(false);
|
|
748
|
+
const [peekOpen, setPeekOpen] = (0, import_react4.useState)(false);
|
|
749
|
+
const timer = (0, import_react4.useRef)(null);
|
|
750
|
+
(0, import_react4.useEffect)(
|
|
751
|
+
() => () => {
|
|
752
|
+
if (timer.current) clearTimeout(timer.current);
|
|
753
|
+
},
|
|
754
|
+
[]
|
|
755
|
+
);
|
|
756
|
+
if (!value) {
|
|
757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-muted-foreground/40", children: "\u2014" });
|
|
758
|
+
}
|
|
759
|
+
const doors = token ? resolveEntityDoors?.(token, value, href) ?? null : null;
|
|
760
|
+
const resolvedHref = doors?.href ?? href ?? null;
|
|
761
|
+
const canPeek = Boolean(doors?.canPeek) && !forbidden;
|
|
762
|
+
const display = shortUuid(value);
|
|
763
|
+
const tip = label ? `${label}: ${value}` : value;
|
|
764
|
+
const stop = (e) => {
|
|
765
|
+
e.stopPropagation();
|
|
766
|
+
};
|
|
767
|
+
const onCopy = (e) => {
|
|
768
|
+
stop(e);
|
|
769
|
+
e.preventDefault();
|
|
770
|
+
void copyText(value).then((ok) => {
|
|
771
|
+
if (!ok) {
|
|
772
|
+
notify?.error("Couldn't copy ID");
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
setCopied(true);
|
|
776
|
+
if (timer.current) clearTimeout(timer.current);
|
|
777
|
+
timer.current = setTimeout(() => setCopied(false), 1500);
|
|
778
|
+
});
|
|
779
|
+
};
|
|
780
|
+
const handleOpen = async (e) => {
|
|
781
|
+
stop(e);
|
|
782
|
+
e.preventDefault();
|
|
783
|
+
if (!onOpen || forbidden || opening) return;
|
|
784
|
+
setOpening(true);
|
|
785
|
+
try {
|
|
786
|
+
const result = await onOpen(value);
|
|
787
|
+
if (result === "forbidden") {
|
|
788
|
+
notify?.error("You don't have access to open this record");
|
|
789
|
+
}
|
|
790
|
+
} catch (err) {
|
|
791
|
+
notify?.error(
|
|
792
|
+
`Couldn't open: ${err instanceof Error ? err.message : String(err)}`
|
|
793
|
+
);
|
|
794
|
+
} finally {
|
|
795
|
+
setOpening(false);
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const idNode = (() => {
|
|
799
|
+
if (forbidden) {
|
|
800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs text-muted-foreground/70 tabular-nums", children: [
|
|
801
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 truncate", children: display }),
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShieldOff, { className: "h-3 w-3 shrink-0 opacity-60", "aria-hidden": true })
|
|
803
|
+
] });
|
|
804
|
+
}
|
|
805
|
+
if (onOpen) {
|
|
806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
807
|
+
"button",
|
|
808
|
+
{
|
|
809
|
+
type: "button",
|
|
810
|
+
"aria-label": `Open ${label ?? "record"} ${display}`,
|
|
811
|
+
onClick: (e) => void handleOpen(e),
|
|
812
|
+
disabled: opening,
|
|
813
|
+
className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs text-sky-600 hover:underline dark:text-sky-400 disabled:opacity-60",
|
|
814
|
+
children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 truncate tabular-nums", children: display }),
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PanelRight, { className: "h-3 w-3 shrink-0 opacity-50" })
|
|
817
|
+
]
|
|
818
|
+
}
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
if (resolvedHref) {
|
|
822
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
823
|
+
"a",
|
|
824
|
+
{
|
|
825
|
+
href: resolvedHref,
|
|
826
|
+
target: "_blank",
|
|
827
|
+
rel: "noopener noreferrer",
|
|
828
|
+
"aria-label": `Open ${label ?? "record"} ${display} in a new tab`,
|
|
829
|
+
onClick: stop,
|
|
830
|
+
className: "inline-flex min-w-0 items-center gap-1 font-mono text-xs text-sky-600 hover:underline dark:text-sky-400",
|
|
831
|
+
children: [
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 truncate tabular-nums", children: display }),
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ExternalLink, { className: "h-3 w-3 shrink-0 opacity-50" })
|
|
834
|
+
]
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 truncate font-mono text-xs text-muted-foreground tabular-nums select-all", children: display });
|
|
839
|
+
})();
|
|
840
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
841
|
+
"span",
|
|
842
|
+
{
|
|
843
|
+
"data-matrx-cell-control": true,
|
|
844
|
+
className: cn(
|
|
845
|
+
"inline-flex min-w-0 max-w-full items-center gap-0.5 whitespace-nowrap",
|
|
846
|
+
className
|
|
847
|
+
),
|
|
848
|
+
onClick: stop,
|
|
849
|
+
children: [
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Tooltip, { children: [
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "inline-flex min-w-0 max-w-full items-center", children: idNode }) }),
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipContent, { side: "top", className: "max-w-sm break-all font-mono", children: forbidden ? `No access \xB7 ${tip}` : tip })
|
|
853
|
+
] }) }),
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
855
|
+
"button",
|
|
856
|
+
{
|
|
857
|
+
type: "button",
|
|
858
|
+
onClick: onCopy,
|
|
859
|
+
"aria-label": copied ? "Copied" : `Copy ${label ?? "id"}`,
|
|
860
|
+
title: `Copy ${label ?? "id"}: ${value}`,
|
|
861
|
+
className: cn(
|
|
862
|
+
"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground focus:outline-none",
|
|
863
|
+
copied && "text-primary"
|
|
864
|
+
),
|
|
865
|
+
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Check, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Copy, { className: "h-3 w-3" })
|
|
866
|
+
}
|
|
867
|
+
),
|
|
868
|
+
canPeek ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
869
|
+
"button",
|
|
870
|
+
{
|
|
871
|
+
type: "button",
|
|
872
|
+
onClick: (e) => {
|
|
873
|
+
stop(e);
|
|
874
|
+
setPeekOpen(true);
|
|
875
|
+
},
|
|
876
|
+
"aria-label": `Quick look at ${label ?? "record"}`,
|
|
877
|
+
title: `Quick look at ${label ?? "record"}`,
|
|
878
|
+
className: "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground focus:outline-none",
|
|
879
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Lightbulb, { className: "h-3 w-3" })
|
|
880
|
+
}
|
|
881
|
+
) : null,
|
|
882
|
+
onOpen && resolvedHref && !forbidden ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
883
|
+
"a",
|
|
884
|
+
{
|
|
885
|
+
href: resolvedHref,
|
|
886
|
+
target: "_blank",
|
|
887
|
+
rel: "noopener noreferrer",
|
|
888
|
+
onClick: stop,
|
|
889
|
+
"aria-label": `Open ${label ?? "record"} in a new tab`,
|
|
890
|
+
title: `Open ${label ?? "record"} in a new tab`,
|
|
891
|
+
className: "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground focus:outline-none",
|
|
892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ExternalLink, { className: "h-3 w-3" })
|
|
893
|
+
}
|
|
894
|
+
) : null,
|
|
895
|
+
trailing,
|
|
896
|
+
notice,
|
|
897
|
+
canPeek && peekOpen && ResourcePeek ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
898
|
+
ResourcePeek,
|
|
899
|
+
{
|
|
900
|
+
kind: doors?.peekKind ?? token ?? "record",
|
|
901
|
+
id: value,
|
|
902
|
+
onClose: () => setPeekOpen(false),
|
|
903
|
+
...href == null ? {} : { href }
|
|
904
|
+
}
|
|
905
|
+
) : null
|
|
906
|
+
]
|
|
907
|
+
}
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/data-table/entity.ts
|
|
912
|
+
function isUuidValue(value) {
|
|
913
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/data-table/DataRowInspector.tsx
|
|
917
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
918
|
+
var noFieldToken = () => null;
|
|
919
|
+
function formatValue(value) {
|
|
920
|
+
if (value == null) return "\u2014";
|
|
921
|
+
if (typeof value === "string") return value || "\u2014";
|
|
922
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
923
|
+
return String(value);
|
|
924
|
+
}
|
|
925
|
+
if (value instanceof Date) return value.toISOString();
|
|
926
|
+
try {
|
|
927
|
+
return JSON.stringify(value, null, 2);
|
|
928
|
+
} catch {
|
|
929
|
+
return String(value);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
function isPlainObject(value) {
|
|
933
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
|
|
934
|
+
}
|
|
935
|
+
function DataRowInspector({
|
|
936
|
+
row,
|
|
937
|
+
title,
|
|
938
|
+
className,
|
|
939
|
+
fieldCopy = true,
|
|
940
|
+
recordKind = "record",
|
|
941
|
+
recordLabel,
|
|
942
|
+
location,
|
|
943
|
+
tokenForField = noFieldToken
|
|
944
|
+
}) {
|
|
945
|
+
const entries = isPlainObject(row) ? Object.entries(row) : [["value", row]];
|
|
946
|
+
const fieldButtons = (key, value) => fieldCopy ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "absolute right-1 top-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/field:opacity-100", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
947
|
+
CopyButtons,
|
|
948
|
+
{
|
|
949
|
+
size: "xs",
|
|
950
|
+
label: recordLabel ? `${recordLabel} \xB7 ${key}` : key,
|
|
951
|
+
human: () => formatValue(value),
|
|
952
|
+
agent: () => ({
|
|
953
|
+
kind: `${recordKind}-field`,
|
|
954
|
+
location: location ?? "Data row inspector",
|
|
955
|
+
description: `The "${key}" field of one ${recordLabel ?? recordKind}.`,
|
|
956
|
+
data: { field: key, value, record: row },
|
|
957
|
+
attributes: { field: key }
|
|
958
|
+
})
|
|
959
|
+
}
|
|
960
|
+
) }) : null;
|
|
961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
962
|
+
"div",
|
|
963
|
+
{
|
|
964
|
+
className: cn("flex h-full min-h-0 flex-col overflow-hidden", className),
|
|
965
|
+
children: [
|
|
966
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "shrink-0 border-b border-border px-3 py-2 text-sm font-medium", children: title }) : null,
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "min-h-0 flex-1 overflow-auto p-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("dl", { className: "space-y-2", children: entries.map(([key, value]) => {
|
|
968
|
+
if (isUuidValue(value)) {
|
|
969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
970
|
+
"div",
|
|
971
|
+
{
|
|
972
|
+
className: "group/field relative grid grid-cols-[minmax(7rem,9rem)_1fr] gap-2 rounded-md border border-border/60 bg-muted/20 px-2.5 py-2",
|
|
973
|
+
children: [
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("dt", { className: "truncate text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: key }),
|
|
975
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("dd", { className: "min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
976
|
+
MatrxUuidCell,
|
|
977
|
+
{
|
|
978
|
+
value,
|
|
979
|
+
label: key,
|
|
980
|
+
token: tokenForField(key, row)
|
|
981
|
+
}
|
|
982
|
+
) })
|
|
983
|
+
]
|
|
984
|
+
},
|
|
985
|
+
key
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
const formatted = formatValue(value);
|
|
989
|
+
const multiline = formatted.includes("\n") || formatted.length > 80;
|
|
990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
991
|
+
"div",
|
|
992
|
+
{
|
|
993
|
+
className: "group/field relative grid grid-cols-[minmax(7rem,9rem)_1fr] gap-2 rounded-md border border-border/60 bg-muted/20 py-2 pl-2.5 pr-12",
|
|
994
|
+
children: [
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("dt", { className: "truncate text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: key }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
997
|
+
"dd",
|
|
998
|
+
{
|
|
999
|
+
className: cn(
|
|
1000
|
+
"min-w-0 text-sm text-foreground break-words",
|
|
1001
|
+
multiline && "whitespace-pre-wrap font-mono text-xs leading-relaxed"
|
|
1002
|
+
),
|
|
1003
|
+
children: formatted
|
|
1004
|
+
}
|
|
1005
|
+
),
|
|
1006
|
+
fieldButtons(key, value)
|
|
1007
|
+
]
|
|
1008
|
+
},
|
|
1009
|
+
key
|
|
1010
|
+
);
|
|
1011
|
+
}) }) })
|
|
1012
|
+
]
|
|
1013
|
+
}
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
//# sourceMappingURL=data-row-inspector.cjs.map
|