@apotech-os/ui-sdk 0.8.0 → 0.10.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/dist/index.cjs +344 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -8
- package/dist/index.d.ts +94 -8
- package/dist/index.js +336 -141
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
var clsx = require('clsx');
|
|
4
4
|
var tailwindMerge = require('tailwind-merge');
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var dialog = require('@base-ui/react/dialog');
|
|
7
|
+
var menu = require('@base-ui/react/menu');
|
|
8
|
+
var popover = require('@base-ui/react/popover');
|
|
9
|
+
var _switch = require('@base-ui/react/switch');
|
|
10
|
+
var tabs = require('@base-ui/react/tabs');
|
|
6
11
|
var classVarianceAuthority = require('class-variance-authority');
|
|
7
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
13
|
|
|
@@ -109,6 +114,175 @@ function useAppSettings() {
|
|
|
109
114
|
);
|
|
110
115
|
return { settings, isLoading, error, save, isSaving, saveError };
|
|
111
116
|
}
|
|
117
|
+
var DEFAULT_RUN_POLL_INTERVAL_MS = 1e3;
|
|
118
|
+
var MAX_RUN_POLL_INTERVAL_MS = 5e3;
|
|
119
|
+
var RUN_POLL_BACKOFF = 1.5;
|
|
120
|
+
var RUNS_FOLLOW_POLL_INTERVAL_MS = 3e3;
|
|
121
|
+
function runProgressSignature(run) {
|
|
122
|
+
return `${run.progress ?? ""}|${run.message ?? ""}`;
|
|
123
|
+
}
|
|
124
|
+
function isTerminalRunError(err) {
|
|
125
|
+
const status = extractHttpStatus(err);
|
|
126
|
+
return status === 403 || status === 404;
|
|
127
|
+
}
|
|
128
|
+
function extractHttpStatus(err) {
|
|
129
|
+
if (typeof err !== "object" || err === null) return void 0;
|
|
130
|
+
const direct = err.status;
|
|
131
|
+
if (typeof direct === "number") return direct;
|
|
132
|
+
const response = err.response;
|
|
133
|
+
if (typeof response !== "object" || response === null) return void 0;
|
|
134
|
+
const nested = response.status;
|
|
135
|
+
return typeof nested === "number" ? nested : void 0;
|
|
136
|
+
}
|
|
137
|
+
function useAppRun(runId, opts = {}) {
|
|
138
|
+
const { appSlug } = useAppContext();
|
|
139
|
+
const api = useAppApi();
|
|
140
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_RUN_POLL_INTERVAL_MS;
|
|
141
|
+
const maxIntervalMs = opts.maxIntervalMs ?? MAX_RUN_POLL_INTERVAL_MS;
|
|
142
|
+
const [run, setRun] = React.useState(void 0);
|
|
143
|
+
const [isPolling, setIsPolling] = React.useState(false);
|
|
144
|
+
const [error, setError] = React.useState(void 0);
|
|
145
|
+
const clientRef = React.useRef(api);
|
|
146
|
+
clientRef.current = api;
|
|
147
|
+
const requestIdRef = React.useRef(0);
|
|
148
|
+
const isMountedRef = React.useRef(true);
|
|
149
|
+
const path = runId !== null ? `/data/apps/${appSlug}/runs/${encodeURIComponent(runId)}` : null;
|
|
150
|
+
const fetchOnce = React.useCallback(async () => {
|
|
151
|
+
if (path === null) return { kind: "no-path" };
|
|
152
|
+
const requestId = ++requestIdRef.current;
|
|
153
|
+
try {
|
|
154
|
+
const loaded = await clientRef.current.get(path);
|
|
155
|
+
if (requestId !== requestIdRef.current || !isMountedRef.current) return { kind: "superseded" };
|
|
156
|
+
setRun(loaded);
|
|
157
|
+
setError(void 0);
|
|
158
|
+
return { kind: "success", run: loaded };
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (requestId !== requestIdRef.current || !isMountedRef.current) return { kind: "superseded" };
|
|
161
|
+
setError(err);
|
|
162
|
+
return { kind: "error", err };
|
|
163
|
+
}
|
|
164
|
+
}, [path]);
|
|
165
|
+
React.useEffect(() => {
|
|
166
|
+
isMountedRef.current = true;
|
|
167
|
+
requestIdRef.current += 1;
|
|
168
|
+
setRun(void 0);
|
|
169
|
+
setError(void 0);
|
|
170
|
+
if (path === null) {
|
|
171
|
+
setIsPolling(false);
|
|
172
|
+
return () => {
|
|
173
|
+
isMountedRef.current = false;
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
let timeoutHandle;
|
|
177
|
+
let interval = intervalMs;
|
|
178
|
+
let lastSignature;
|
|
179
|
+
let cancelled = false;
|
|
180
|
+
const tick = async () => {
|
|
181
|
+
const outcome = await fetchOnce();
|
|
182
|
+
if (cancelled || !isMountedRef.current) return;
|
|
183
|
+
if (outcome.kind === "no-path") {
|
|
184
|
+
setIsPolling(false);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (outcome.kind === "superseded") {
|
|
188
|
+
timeoutHandle = setTimeout(() => void tick(), interval);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (outcome.kind === "error") {
|
|
192
|
+
if (isTerminalRunError(outcome.err)) {
|
|
193
|
+
setIsPolling(false);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
timeoutHandle = setTimeout(() => void tick(), interval);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const loaded = outcome.run;
|
|
200
|
+
const signature = runProgressSignature(loaded);
|
|
201
|
+
interval = signature === lastSignature ? Math.min(interval * RUN_POLL_BACKOFF, maxIntervalMs) : intervalMs;
|
|
202
|
+
lastSignature = signature;
|
|
203
|
+
if (loaded.status !== "running") {
|
|
204
|
+
setIsPolling(false);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
timeoutHandle = setTimeout(() => void tick(), interval);
|
|
208
|
+
};
|
|
209
|
+
setIsPolling(true);
|
|
210
|
+
void tick();
|
|
211
|
+
return () => {
|
|
212
|
+
cancelled = true;
|
|
213
|
+
isMountedRef.current = false;
|
|
214
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
215
|
+
};
|
|
216
|
+
}, [path, fetchOnce, intervalMs, maxIntervalMs]);
|
|
217
|
+
const refresh = React.useCallback(async () => {
|
|
218
|
+
await fetchOnce();
|
|
219
|
+
}, [fetchOnce]);
|
|
220
|
+
return { run, isPolling, error, refresh };
|
|
221
|
+
}
|
|
222
|
+
function useAppRuns(opts) {
|
|
223
|
+
const { appSlug } = useAppContext();
|
|
224
|
+
const api = useAppApi();
|
|
225
|
+
const follow = opts.follow ?? true;
|
|
226
|
+
const [runs, setRuns] = React.useState([]);
|
|
227
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
228
|
+
const [error, setError] = React.useState(void 0);
|
|
229
|
+
const clientRef = React.useRef(api);
|
|
230
|
+
clientRef.current = api;
|
|
231
|
+
const requestIdRef = React.useRef(0);
|
|
232
|
+
const isMountedRef = React.useRef(true);
|
|
233
|
+
const params = {};
|
|
234
|
+
if (opts.kind) params["kind"] = opts.kind;
|
|
235
|
+
if (opts.key) params["key"] = opts.key;
|
|
236
|
+
if (opts.status?.length) params["status"] = opts.status.join(",");
|
|
237
|
+
if (opts.limit) params["limit"] = String(opts.limit);
|
|
238
|
+
const paramsKey = JSON.stringify(params);
|
|
239
|
+
const path = `/data/apps/${appSlug}/runs`;
|
|
240
|
+
const fetchOnce = React.useCallback(
|
|
241
|
+
async ({ silent } = {}) => {
|
|
242
|
+
const requestId = ++requestIdRef.current;
|
|
243
|
+
if (!silent) setIsLoading(true);
|
|
244
|
+
try {
|
|
245
|
+
const page = await clientRef.current.get(
|
|
246
|
+
path,
|
|
247
|
+
JSON.parse(paramsKey)
|
|
248
|
+
);
|
|
249
|
+
if (requestId !== requestIdRef.current || !isMountedRef.current) return { kind: "superseded" };
|
|
250
|
+
setRuns(page.items);
|
|
251
|
+
setError(void 0);
|
|
252
|
+
return { kind: "success", items: page.items };
|
|
253
|
+
} catch (err) {
|
|
254
|
+
if (requestId !== requestIdRef.current || !isMountedRef.current) return { kind: "superseded" };
|
|
255
|
+
setError(err);
|
|
256
|
+
return { kind: "error", err };
|
|
257
|
+
} finally {
|
|
258
|
+
if (requestId === requestIdRef.current) setIsLoading(false);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
[path, paramsKey]
|
|
262
|
+
);
|
|
263
|
+
React.useEffect(() => {
|
|
264
|
+
isMountedRef.current = true;
|
|
265
|
+
let timeoutHandle;
|
|
266
|
+
let cancelled = false;
|
|
267
|
+
const tick = async (silent) => {
|
|
268
|
+
const outcome = await fetchOnce({ silent });
|
|
269
|
+
if (cancelled || !isMountedRef.current || !follow) return;
|
|
270
|
+
if (outcome.kind !== "success" || outcome.items.some((r) => r.status === "running")) {
|
|
271
|
+
timeoutHandle = setTimeout(() => void tick(true), RUNS_FOLLOW_POLL_INTERVAL_MS);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
void tick(false);
|
|
275
|
+
return () => {
|
|
276
|
+
cancelled = true;
|
|
277
|
+
isMountedRef.current = false;
|
|
278
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
279
|
+
};
|
|
280
|
+
}, [fetchOnce, follow]);
|
|
281
|
+
const refresh = React.useCallback(async () => {
|
|
282
|
+
await fetchOnce({ silent: true });
|
|
283
|
+
}, [fetchOnce]);
|
|
284
|
+
return { runs, isLoading, error, refresh };
|
|
285
|
+
}
|
|
112
286
|
|
|
113
287
|
// src/utils.ts
|
|
114
288
|
async function copyToClipboard(text) {
|
|
@@ -141,6 +315,12 @@ function downloadCsv(rows, filename) {
|
|
|
141
315
|
const blob = new Blob([`${BOM}${toCsv(rows)}`], { type: "text/csv;charset=utf-8" });
|
|
142
316
|
downloadBlob(blob, filename);
|
|
143
317
|
}
|
|
318
|
+
function triggerProps(trigger) {
|
|
319
|
+
if (React__namespace.isValidElement(trigger)) {
|
|
320
|
+
return { render: trigger, nativeButton: trigger.type === "button" || trigger.type === Button };
|
|
321
|
+
}
|
|
322
|
+
return { render: /* @__PURE__ */ jsxRuntime.jsx("span", { children: trigger }), nativeButton: false };
|
|
323
|
+
}
|
|
144
324
|
var buttonVariants = classVarianceAuthority.cva(
|
|
145
325
|
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
|
146
326
|
{
|
|
@@ -204,9 +384,18 @@ function CardHeader({ className, ...props }) {
|
|
|
204
384
|
function CardTitle({ className, ...props }) {
|
|
205
385
|
return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props });
|
|
206
386
|
}
|
|
387
|
+
function CardDescription({
|
|
388
|
+
className,
|
|
389
|
+
...props
|
|
390
|
+
}) {
|
|
391
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm text-muted-foreground", className), ...props });
|
|
392
|
+
}
|
|
207
393
|
function CardContent({ className, ...props }) {
|
|
208
394
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 pt-0", className), ...props });
|
|
209
395
|
}
|
|
396
|
+
function CardFooter({ className, ...props }) {
|
|
397
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center p-6 pt-0", className), ...props });
|
|
398
|
+
}
|
|
210
399
|
var Input = React__namespace.forwardRef(({ className, type, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
211
400
|
"input",
|
|
212
401
|
{
|
|
@@ -227,7 +416,13 @@ function TableHeader({
|
|
|
227
416
|
className,
|
|
228
417
|
...props
|
|
229
418
|
}) {
|
|
230
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
419
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
420
|
+
"thead",
|
|
421
|
+
{
|
|
422
|
+
className: cn("[&_tr]:border-b [&_tr]:hover:bg-transparent", className),
|
|
423
|
+
...props
|
|
424
|
+
}
|
|
425
|
+
);
|
|
231
426
|
}
|
|
232
427
|
function TableBody({ className, ...props }) {
|
|
233
428
|
return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: cn("[&_tr:last-child]:border-0", className), ...props });
|
|
@@ -249,7 +444,7 @@ function TableHead({ className, ...props }) {
|
|
|
249
444
|
"th",
|
|
250
445
|
{
|
|
251
446
|
className: cn(
|
|
252
|
-
"h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground",
|
|
447
|
+
"h-10 px-4 text-left align-middle text-xs font-medium uppercase tracking-wide text-muted-foreground",
|
|
253
448
|
className
|
|
254
449
|
),
|
|
255
450
|
...props
|
|
@@ -274,42 +469,43 @@ var Select = React__namespace.forwardRef(
|
|
|
274
469
|
)
|
|
275
470
|
);
|
|
276
471
|
Select.displayName = "Select";
|
|
277
|
-
var TabsContext = React__namespace.createContext(null);
|
|
278
|
-
function useTabsContext() {
|
|
279
|
-
const ctx = React__namespace.useContext(TabsContext);
|
|
280
|
-
if (!ctx) throw new Error("Tabs sub-component must be used within <Tabs>");
|
|
281
|
-
return ctx;
|
|
282
|
-
}
|
|
283
472
|
function Tabs({ defaultValue, value, onValueChange, className, children }) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
473
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
474
|
+
tabs.Tabs.Root,
|
|
475
|
+
{
|
|
476
|
+
className,
|
|
477
|
+
defaultValue,
|
|
478
|
+
value,
|
|
479
|
+
onValueChange: (next) => onValueChange?.(String(next)),
|
|
480
|
+
children
|
|
481
|
+
}
|
|
482
|
+
);
|
|
291
483
|
}
|
|
292
484
|
function TabsList({
|
|
293
485
|
className,
|
|
294
486
|
children
|
|
295
487
|
}) {
|
|
296
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
488
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
489
|
+
tabs.Tabs.List,
|
|
490
|
+
{
|
|
491
|
+
className: cn("inline-flex items-center gap-1 rounded-lg bg-muted p-1", className),
|
|
492
|
+
children
|
|
493
|
+
}
|
|
494
|
+
);
|
|
297
495
|
}
|
|
298
496
|
function TabsTrigger({
|
|
299
497
|
value,
|
|
300
498
|
className,
|
|
301
499
|
children
|
|
302
500
|
}) {
|
|
303
|
-
const { value: current, setValue } = useTabsContext();
|
|
304
|
-
const active = current === value;
|
|
305
501
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
306
|
-
|
|
502
|
+
tabs.Tabs.Tab,
|
|
307
503
|
{
|
|
308
|
-
|
|
309
|
-
onClick: () => setValue(value),
|
|
504
|
+
value,
|
|
310
505
|
className: cn(
|
|
311
506
|
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
312
|
-
|
|
507
|
+
"text-muted-foreground hover:text-foreground",
|
|
508
|
+
"data-[active]:bg-card data-[active]:text-foreground data-[active]:shadow-sm",
|
|
313
509
|
className
|
|
314
510
|
),
|
|
315
511
|
children
|
|
@@ -321,38 +517,25 @@ function TabsContent({
|
|
|
321
517
|
className,
|
|
322
518
|
children
|
|
323
519
|
}) {
|
|
324
|
-
|
|
325
|
-
if (current !== value) return null;
|
|
326
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children });
|
|
520
|
+
return /* @__PURE__ */ jsxRuntime.jsx(tabs.Tabs.Panel, { value, className, children });
|
|
327
521
|
}
|
|
328
522
|
function Modal({ open, onClose, title, children, className }) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
332
|
-
"button",
|
|
333
|
-
{
|
|
334
|
-
type: "button",
|
|
335
|
-
"aria-label": "Close",
|
|
336
|
-
className: "absolute inset-0 cursor-default bg-foreground/40",
|
|
337
|
-
onClick: onClose
|
|
338
|
-
}
|
|
339
|
-
),
|
|
523
|
+
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Root, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.Dialog.Portal, { children: [
|
|
524
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Backdrop, { "aria-label": "Close", className: "fixed inset-0 z-50 bg-foreground/40" }),
|
|
340
525
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
341
|
-
|
|
526
|
+
dialog.Dialog.Popup,
|
|
342
527
|
{
|
|
343
|
-
role: "dialog",
|
|
344
|
-
"aria-modal": true,
|
|
345
528
|
className: cn(
|
|
346
|
-
"
|
|
529
|
+
"fixed left-1/2 top-1/2 z-50 w-[calc(100%-2rem)] max-w-md -translate-x-1/2 -translate-y-1/2 rounded-xl border bg-card p-5 shadow-lg",
|
|
347
530
|
className
|
|
348
531
|
),
|
|
349
532
|
children: [
|
|
350
|
-
title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
533
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Title, { className: "mb-3 text-base font-semibold", children: title }),
|
|
351
534
|
children
|
|
352
535
|
]
|
|
353
536
|
}
|
|
354
537
|
)
|
|
355
|
-
] });
|
|
538
|
+
] }) });
|
|
356
539
|
}
|
|
357
540
|
var spinnerSizes = { sm: "size-4", md: "size-6", lg: "size-8" };
|
|
358
541
|
function Spinner({ className, size = "md" }) {
|
|
@@ -402,28 +585,19 @@ function Switch({
|
|
|
402
585
|
...props
|
|
403
586
|
}) {
|
|
404
587
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
405
|
-
|
|
588
|
+
_switch.Switch.Root,
|
|
406
589
|
{
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
"aria-checked": checked,
|
|
590
|
+
checked,
|
|
591
|
+
onCheckedChange: (next) => onCheckedChange?.(next),
|
|
410
592
|
disabled,
|
|
411
|
-
onClick: () => onCheckedChange?.(!checked),
|
|
412
593
|
className: cn(
|
|
413
|
-
|
|
414
|
-
|
|
594
|
+
// `data-[disabled]`, not `disabled:` — the root is a span, so `:disabled`
|
|
595
|
+
// never matches it and the dimming would silently stop happening.
|
|
596
|
+
"relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full bg-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[checked]:bg-primary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
415
597
|
className
|
|
416
598
|
),
|
|
417
599
|
...props,
|
|
418
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
419
|
-
"span",
|
|
420
|
-
{
|
|
421
|
-
className: cn(
|
|
422
|
-
"inline-block size-4 transform rounded-full bg-white shadow transition-transform",
|
|
423
|
-
checked ? "translate-x-4" : "translate-x-0.5"
|
|
424
|
-
)
|
|
425
|
-
}
|
|
426
|
-
)
|
|
600
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(_switch.Switch.Thumb, { className: "inline-block size-4 translate-x-0.5 rounded-full bg-white shadow transition-transform data-[checked]:translate-x-4" })
|
|
427
601
|
}
|
|
428
602
|
);
|
|
429
603
|
}
|
|
@@ -552,47 +726,26 @@ function SidePanel({
|
|
|
552
726
|
children,
|
|
553
727
|
className
|
|
554
728
|
}) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const onKeyDown = (e) => {
|
|
558
|
-
if (e.key === "Escape") onClose();
|
|
559
|
-
};
|
|
560
|
-
window.addEventListener("keydown", onKeyDown);
|
|
561
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
562
|
-
}, [open, onClose]);
|
|
563
|
-
if (!open) return null;
|
|
564
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50", children: [
|
|
565
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
566
|
-
"button",
|
|
567
|
-
{
|
|
568
|
-
type: "button",
|
|
569
|
-
"aria-label": "Fermer",
|
|
570
|
-
className: "absolute inset-0 cursor-default bg-foreground/40",
|
|
571
|
-
onClick: onClose
|
|
572
|
-
}
|
|
573
|
-
),
|
|
729
|
+
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Root, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.Dialog.Portal, { children: [
|
|
730
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Backdrop, { "aria-label": "Fermer", className: "fixed inset-0 z-50 bg-foreground/40" }),
|
|
574
731
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
575
|
-
|
|
732
|
+
dialog.Dialog.Popup,
|
|
576
733
|
{
|
|
577
|
-
role: "dialog",
|
|
578
|
-
"aria-modal": true,
|
|
579
734
|
className: cn(
|
|
580
|
-
"
|
|
735
|
+
"fixed inset-y-0 right-0 z-50 flex w-full max-w-lg flex-col border-l bg-card shadow-xl",
|
|
581
736
|
className
|
|
582
737
|
),
|
|
583
738
|
children: [
|
|
584
739
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex shrink-0 items-start gap-3 border-b px-5 py-4", children: [
|
|
585
740
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
586
|
-
title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
587
|
-
description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
741
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Title, { className: "text-base font-semibold", children: title }),
|
|
742
|
+
description && /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Description, { className: "mt-0.5 text-xs text-muted-foreground", children: description })
|
|
588
743
|
] }),
|
|
589
744
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
590
|
-
|
|
745
|
+
dialog.Dialog.Close,
|
|
591
746
|
{
|
|
592
|
-
type: "button",
|
|
593
747
|
"aria-label": "Fermer",
|
|
594
748
|
className: "-mr-1 shrink-0 rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
595
|
-
onClick: onClose,
|
|
596
749
|
children: /* @__PURE__ */ jsxRuntime.jsx(IconX, { className: "size-4" })
|
|
597
750
|
}
|
|
598
751
|
)
|
|
@@ -601,7 +754,7 @@ function SidePanel({
|
|
|
601
754
|
]
|
|
602
755
|
}
|
|
603
756
|
)
|
|
604
|
-
] });
|
|
757
|
+
] }) });
|
|
605
758
|
}
|
|
606
759
|
var COPY_FEEDBACK_MS = 2e3;
|
|
607
760
|
function CopyButton({
|
|
@@ -644,68 +797,110 @@ function Popover({
|
|
|
644
797
|
align = "start",
|
|
645
798
|
className
|
|
646
799
|
}) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
664
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
665
|
-
|
|
800
|
+
return (
|
|
801
|
+
// The callback is re-wrapped so Base UI's event-details argument stops at the
|
|
802
|
+
// SDK boundary: the engine is an implementation detail, not part of the API.
|
|
803
|
+
/* @__PURE__ */ jsxRuntime.jsxs(popover.Popover.Root, { open, onOpenChange: (next) => onOpenChange(next), children: [
|
|
804
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block", children: /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { ...triggerProps(trigger) }) }),
|
|
805
|
+
/* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { side: "bottom", align, sideOffset: 4, className: "z-50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
806
|
+
popover.Popover.Popup,
|
|
807
|
+
{
|
|
808
|
+
className: cn("min-w-48 rounded-md border bg-card p-2 shadow-lg", className),
|
|
809
|
+
children
|
|
810
|
+
}
|
|
811
|
+
) }) })
|
|
812
|
+
] })
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
function DropdownMenu({ trigger, items, align = "end", className }) {
|
|
816
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(menu.Menu.Root, { children: [
|
|
817
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block", children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { ...triggerProps(trigger) }) }),
|
|
818
|
+
/* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Positioner, { side: "bottom", align, sideOffset: 4, className: "z-50", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
819
|
+
menu.Menu.Popup,
|
|
820
|
+
{
|
|
821
|
+
className: cn(
|
|
822
|
+
"flex min-w-48 flex-col rounded-md border bg-card p-1 shadow-lg",
|
|
823
|
+
className
|
|
824
|
+
),
|
|
825
|
+
children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
826
|
+
menu.Menu.Item,
|
|
827
|
+
{
|
|
828
|
+
disabled: item.disabled,
|
|
829
|
+
onClick: item.onSelect,
|
|
830
|
+
className: cn(
|
|
831
|
+
"cursor-pointer rounded px-2 py-1.5 text-left text-sm outline-none data-[highlighted]:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
832
|
+
item.destructive && "text-destructive"
|
|
833
|
+
),
|
|
834
|
+
children: item.label
|
|
835
|
+
},
|
|
836
|
+
i
|
|
837
|
+
))
|
|
838
|
+
}
|
|
839
|
+
) }) })
|
|
840
|
+
] });
|
|
841
|
+
}
|
|
842
|
+
var ToastContext = React.createContext(null);
|
|
843
|
+
function useToast() {
|
|
844
|
+
const toast = React.useContext(ToastContext);
|
|
845
|
+
if (!toast) throw new Error("useToast must be used within ToastProvider");
|
|
846
|
+
return toast;
|
|
847
|
+
}
|
|
848
|
+
var TOAST_TTL_MS = 4e3;
|
|
849
|
+
var TONE = {
|
|
850
|
+
success: "border-l-status-success",
|
|
851
|
+
error: "border-l-status-blocked",
|
|
852
|
+
info: "border-l-status-info"
|
|
853
|
+
};
|
|
854
|
+
function ToastProvider({ children }) {
|
|
855
|
+
const [toasts, setToasts] = React.useState([]);
|
|
856
|
+
const nextId = React.useRef(0);
|
|
857
|
+
const toast = React.useCallback((input) => {
|
|
858
|
+
const id = nextId.current++;
|
|
859
|
+
setToasts((prev) => [...prev, { id, ...input }]);
|
|
860
|
+
setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), TOAST_TTL_MS);
|
|
861
|
+
}, []);
|
|
862
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: toast, children: [
|
|
863
|
+
children,
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none fixed bottom-4 right-4 z-[60] flex w-80 flex-col gap-2", children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
666
865
|
"div",
|
|
667
866
|
{
|
|
867
|
+
role: "status",
|
|
868
|
+
className: cn(
|
|
869
|
+
"pointer-events-auto rounded-lg border border-l-4 bg-card px-4 py-3 text-foreground shadow-md",
|
|
870
|
+
TONE[t.variant ?? "success"]
|
|
871
|
+
),
|
|
872
|
+
children: [
|
|
873
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: t.title }),
|
|
874
|
+
t.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 break-all text-xs text-muted-foreground", children: t.description })
|
|
875
|
+
]
|
|
876
|
+
},
|
|
877
|
+
t.id
|
|
878
|
+
)) })
|
|
879
|
+
] });
|
|
880
|
+
}
|
|
881
|
+
var SIDES = {
|
|
882
|
+
top: "bottom-full left-1/2 -translate-x-1/2 mb-1.5",
|
|
883
|
+
right: "left-full top-1/2 -translate-y-1/2 ml-1.5",
|
|
884
|
+
bottom: "top-full left-1/2 -translate-x-1/2 mt-1.5",
|
|
885
|
+
left: "right-full top-1/2 -translate-y-1/2 mr-1.5"
|
|
886
|
+
};
|
|
887
|
+
function Tooltip({ label, children, side = "top", className }) {
|
|
888
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "group/tt relative inline-flex", children: [
|
|
889
|
+
children,
|
|
890
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
891
|
+
"span",
|
|
892
|
+
{
|
|
893
|
+
role: "tooltip",
|
|
668
894
|
className: cn(
|
|
669
|
-
"absolute z-
|
|
670
|
-
|
|
895
|
+
"pointer-events-none absolute z-50 whitespace-nowrap rounded-md bg-foreground px-2 py-1 text-xs font-medium text-background opacity-0 shadow-md transition-opacity group-hover/tt:opacity-100",
|
|
896
|
+
SIDES[side],
|
|
671
897
|
className
|
|
672
898
|
),
|
|
673
|
-
children
|
|
899
|
+
children: label
|
|
674
900
|
}
|
|
675
901
|
)
|
|
676
902
|
] });
|
|
677
903
|
}
|
|
678
|
-
function DropdownMenu({ trigger, items, align = "end", className }) {
|
|
679
|
-
const [open, setOpen] = React__namespace.useState(false);
|
|
680
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
681
|
-
Popover,
|
|
682
|
-
{
|
|
683
|
-
open,
|
|
684
|
-
onOpenChange: setOpen,
|
|
685
|
-
trigger,
|
|
686
|
-
align,
|
|
687
|
-
className: cn("p-1", className),
|
|
688
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "menu", className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
689
|
-
"button",
|
|
690
|
-
{
|
|
691
|
-
type: "button",
|
|
692
|
-
role: "menuitem",
|
|
693
|
-
disabled: item.disabled,
|
|
694
|
-
className: cn(
|
|
695
|
-
"cursor-pointer rounded px-2 py-1.5 text-left text-sm hover:bg-accent disabled:pointer-events-none disabled:opacity-50",
|
|
696
|
-
item.destructive && "text-destructive"
|
|
697
|
-
),
|
|
698
|
-
onClick: () => {
|
|
699
|
-
setOpen(false);
|
|
700
|
-
item.onSelect();
|
|
701
|
-
},
|
|
702
|
-
children: item.label
|
|
703
|
-
},
|
|
704
|
-
i
|
|
705
|
-
)) })
|
|
706
|
-
}
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
904
|
|
|
710
905
|
exports.AppApiProvider = AppApiProvider;
|
|
711
906
|
exports.AppContextProvider = AppContextProvider;
|
|
@@ -714,6 +909,8 @@ exports.Badge = Badge;
|
|
|
714
909
|
exports.Button = Button;
|
|
715
910
|
exports.Card = Card;
|
|
716
911
|
exports.CardContent = CardContent;
|
|
912
|
+
exports.CardDescription = CardDescription;
|
|
913
|
+
exports.CardFooter = CardFooter;
|
|
717
914
|
exports.CardHeader = CardHeader;
|
|
718
915
|
exports.CardTitle = CardTitle;
|
|
719
916
|
exports.Checkbox = Checkbox;
|
|
@@ -739,6 +936,10 @@ exports.TabsContent = TabsContent;
|
|
|
739
936
|
exports.TabsList = TabsList;
|
|
740
937
|
exports.TabsTrigger = TabsTrigger;
|
|
741
938
|
exports.Textarea = Textarea;
|
|
939
|
+
exports.ToastProvider = ToastProvider;
|
|
940
|
+
exports.Tooltip = Tooltip;
|
|
941
|
+
exports.badgeVariants = badgeVariants;
|
|
942
|
+
exports.buttonVariants = buttonVariants;
|
|
742
943
|
exports.cn = cn;
|
|
743
944
|
exports.copyToClipboard = copyToClipboard;
|
|
744
945
|
exports.downloadBlob = downloadBlob;
|
|
@@ -746,6 +947,9 @@ exports.downloadCsv = downloadCsv;
|
|
|
746
947
|
exports.toCsv = toCsv;
|
|
747
948
|
exports.useAppApi = useAppApi;
|
|
748
949
|
exports.useAppContext = useAppContext;
|
|
950
|
+
exports.useAppRun = useAppRun;
|
|
951
|
+
exports.useAppRuns = useAppRuns;
|
|
749
952
|
exports.useAppSettings = useAppSettings;
|
|
953
|
+
exports.useToast = useToast;
|
|
750
954
|
//# sourceMappingURL=index.cjs.map
|
|
751
955
|
//# sourceMappingURL=index.cjs.map
|