@apotech-os/ui-sdk 0.10.0 → 1.0.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 +140 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -51
- package/dist/index.d.ts +6 -51
- package/dist/index.js +141 -167
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { ReactNode } from 'react';
|
|
4
3
|
import { AppErrorCode, AppRunRecord, AppRunStatus } from '@apotech-os/app-kit';
|
|
5
4
|
export { AppRunRecord, AppRunStatus } from '@apotech-os/app-kit';
|
|
6
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
@@ -160,9 +159,7 @@ declare function Badge({ className, variant, dot, children, ...props }: BadgePro
|
|
|
160
159
|
declare function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
161
160
|
declare function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
162
161
|
declare function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): React.JSX.Element;
|
|
163
|
-
declare function CardDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>): React.JSX.Element;
|
|
164
162
|
declare function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
165
|
-
declare function CardFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
166
163
|
declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement>>;
|
|
167
164
|
declare function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>): React.JSX.Element;
|
|
168
165
|
declare function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
|
|
@@ -194,7 +191,7 @@ declare function TabsContent({ value, className, children, }: {
|
|
|
194
191
|
value: string;
|
|
195
192
|
className?: string;
|
|
196
193
|
children: React.ReactNode;
|
|
197
|
-
}): React.JSX.Element;
|
|
194
|
+
}): React.JSX.Element | null;
|
|
198
195
|
interface ModalProps {
|
|
199
196
|
open: boolean;
|
|
200
197
|
onClose: () => void;
|
|
@@ -202,8 +199,7 @@ interface ModalProps {
|
|
|
202
199
|
children: React.ReactNode;
|
|
203
200
|
className?: string;
|
|
204
201
|
}
|
|
205
|
-
|
|
206
|
-
declare function Modal({ open, onClose, title, children, className }: ModalProps): React.JSX.Element;
|
|
202
|
+
declare function Modal({ open, onClose, title, children, className }: ModalProps): React.JSX.Element | null;
|
|
207
203
|
interface SpinnerProps {
|
|
208
204
|
className?: string;
|
|
209
205
|
size?: 'sm' | 'md' | 'lg';
|
|
@@ -213,10 +209,6 @@ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
|
213
209
|
variant?: 'default' | 'muted';
|
|
214
210
|
}
|
|
215
211
|
declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
216
|
-
/**
|
|
217
|
-
* Do not pass `aria-label` when the switch sits inside a `<label>`: the label
|
|
218
|
-
* already names it, and the two naming sources cancel out into no name at all.
|
|
219
|
-
*/
|
|
220
212
|
interface SwitchProps {
|
|
221
213
|
checked?: boolean;
|
|
222
214
|
onCheckedChange?: (checked: boolean) => void;
|
|
@@ -262,10 +254,9 @@ interface SidePanelProps {
|
|
|
262
254
|
* Children are laid out in a flex column filling the panel: put the scrollable
|
|
263
255
|
* region in a `min-h-0 flex-1 overflow-y-auto` child and the footer after it.
|
|
264
256
|
*
|
|
265
|
-
*
|
|
266
|
-
* UI's dialog does both, which is what the hand-rolled version never did.
|
|
257
|
+
* NOTE: no focus management. Autofocus the primary action yourself.
|
|
267
258
|
*/
|
|
268
|
-
declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element;
|
|
259
|
+
declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element | null;
|
|
269
260
|
interface CopyButtonProps {
|
|
270
261
|
value: string;
|
|
271
262
|
label?: string;
|
|
@@ -303,45 +294,9 @@ interface DropdownMenuProps {
|
|
|
303
294
|
align?: 'start' | 'end';
|
|
304
295
|
className?: string;
|
|
305
296
|
}
|
|
306
|
-
/** Uncontrolled menu. Selecting an item closes it
|
|
297
|
+
/** Uncontrolled menu built on Popover. Selecting an item closes it. */
|
|
307
298
|
declare function DropdownMenu({ trigger, items, align, className }: DropdownMenuProps): React.JSX.Element;
|
|
308
299
|
|
|
309
|
-
interface ToastInput {
|
|
310
|
-
title: string;
|
|
311
|
-
description?: string;
|
|
312
|
-
/** `info` exists because Pilotage's own stack had it — a neutral outcome is not a success. */
|
|
313
|
-
variant?: 'success' | 'error' | 'info';
|
|
314
|
-
}
|
|
315
|
-
/** Returns a `toast({ title, description?, variant? })` function. */
|
|
316
|
-
declare function useToast(): (toast: ToastInput) => void;
|
|
317
|
-
/** Fixed bottom-right stack, auto-dismissing. */
|
|
318
|
-
declare function ToastProvider({ children }: {
|
|
319
|
-
children: ReactNode;
|
|
320
|
-
}): React.JSX.Element;
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Hover tooltip, lifted from the shell.
|
|
324
|
-
*
|
|
325
|
-
* Deliberately CSS-only (`group-hover`) rather than another Base UI surface: it
|
|
326
|
-
* carries no focus, no dismissal and no state, so a portal and a positioner would
|
|
327
|
-
* be weight for nothing. If a tooltip ever needs to be keyboard-reachable or to
|
|
328
|
-
* survive a scroll container, that is the moment to move it onto Base UI's.
|
|
329
|
-
*/
|
|
330
|
-
|
|
331
|
-
declare const SIDES: {
|
|
332
|
-
readonly top: "bottom-full left-1/2 -translate-x-1/2 mb-1.5";
|
|
333
|
-
readonly right: "left-full top-1/2 -translate-y-1/2 ml-1.5";
|
|
334
|
-
readonly bottom: "top-full left-1/2 -translate-x-1/2 mt-1.5";
|
|
335
|
-
readonly left: "right-full top-1/2 -translate-y-1/2 mr-1.5";
|
|
336
|
-
};
|
|
337
|
-
interface TooltipProps {
|
|
338
|
-
label: React.ReactNode;
|
|
339
|
-
children: React.ReactNode;
|
|
340
|
-
side?: keyof typeof SIDES;
|
|
341
|
-
className?: string;
|
|
342
|
-
}
|
|
343
|
-
declare function Tooltip({ label, children, side, className }: TooltipProps): React.JSX.Element;
|
|
344
|
-
|
|
345
300
|
/**
|
|
346
301
|
* Browser helpers for app pages.
|
|
347
302
|
*
|
|
@@ -371,4 +326,4 @@ declare function toCsv(rows: string[][]): string;
|
|
|
371
326
|
*/
|
|
372
327
|
declare function downloadCsv(rows: string[][], filename: string): void;
|
|
373
328
|
|
|
374
|
-
export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, AppInvokeError, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent,
|
|
329
|
+
export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, AppInvokeError, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, Checkbox, type CheckboxProps, CopyButton, type CopyButtonProps, type DateRange, DateRangePicker, type DateRangePickerProps, DropdownMenu, type DropdownMenuItem, type DropdownMenuProps, Input, Link, type LinkProps, Modal, type ModalProps, Popover, type PopoverProps, Select, type SelectProps, SidePanel, type SidePanelProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, type TextareaProps, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings };
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,6 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { createContext, useContext, useState, useRef, useCallback, useEffect } from 'react';
|
|
5
|
-
import { Dialog } from '@base-ui/react/dialog';
|
|
6
|
-
import { Menu } from '@base-ui/react/menu';
|
|
7
|
-
import { Popover as Popover$1 } from '@base-ui/react/popover';
|
|
8
|
-
import { Switch as Switch$1 } from '@base-ui/react/switch';
|
|
9
|
-
import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
|
|
10
5
|
import { cva } from 'class-variance-authority';
|
|
11
6
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
7
|
|
|
@@ -294,12 +289,6 @@ function downloadCsv(rows, filename) {
|
|
|
294
289
|
const blob = new Blob([`${BOM}${toCsv(rows)}`], { type: "text/csv;charset=utf-8" });
|
|
295
290
|
downloadBlob(blob, filename);
|
|
296
291
|
}
|
|
297
|
-
function triggerProps(trigger) {
|
|
298
|
-
if (React.isValidElement(trigger)) {
|
|
299
|
-
return { render: trigger, nativeButton: trigger.type === "button" || trigger.type === Button };
|
|
300
|
-
}
|
|
301
|
-
return { render: /* @__PURE__ */ jsx("span", { children: trigger }), nativeButton: false };
|
|
302
|
-
}
|
|
303
292
|
var buttonVariants = cva(
|
|
304
293
|
"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",
|
|
305
294
|
{
|
|
@@ -363,18 +352,9 @@ function CardHeader({ className, ...props }) {
|
|
|
363
352
|
function CardTitle({ className, ...props }) {
|
|
364
353
|
return /* @__PURE__ */ jsx("h3", { className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props });
|
|
365
354
|
}
|
|
366
|
-
function CardDescription({
|
|
367
|
-
className,
|
|
368
|
-
...props
|
|
369
|
-
}) {
|
|
370
|
-
return /* @__PURE__ */ jsx("p", { className: cn("text-sm text-muted-foreground", className), ...props });
|
|
371
|
-
}
|
|
372
355
|
function CardContent({ className, ...props }) {
|
|
373
356
|
return /* @__PURE__ */ jsx("div", { className: cn("p-6 pt-0", className), ...props });
|
|
374
357
|
}
|
|
375
|
-
function CardFooter({ className, ...props }) {
|
|
376
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center p-6 pt-0", className), ...props });
|
|
377
|
-
}
|
|
378
358
|
var Input = React.forwardRef(({ className, type, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
379
359
|
"input",
|
|
380
360
|
{
|
|
@@ -395,13 +375,7 @@ function TableHeader({
|
|
|
395
375
|
className,
|
|
396
376
|
...props
|
|
397
377
|
}) {
|
|
398
|
-
return /* @__PURE__ */ jsx(
|
|
399
|
-
"thead",
|
|
400
|
-
{
|
|
401
|
-
className: cn("[&_tr]:border-b [&_tr]:hover:bg-transparent", className),
|
|
402
|
-
...props
|
|
403
|
-
}
|
|
404
|
-
);
|
|
378
|
+
return /* @__PURE__ */ jsx("thead", { className: cn("[&_tr]:border-b", className), ...props });
|
|
405
379
|
}
|
|
406
380
|
function TableBody({ className, ...props }) {
|
|
407
381
|
return /* @__PURE__ */ jsx("tbody", { className: cn("[&_tr:last-child]:border-0", className), ...props });
|
|
@@ -423,7 +397,7 @@ function TableHead({ className, ...props }) {
|
|
|
423
397
|
"th",
|
|
424
398
|
{
|
|
425
399
|
className: cn(
|
|
426
|
-
"h-10 px-4 text-left align-middle text-xs font-medium
|
|
400
|
+
"h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground",
|
|
427
401
|
className
|
|
428
402
|
),
|
|
429
403
|
...props
|
|
@@ -448,43 +422,42 @@ var Select = React.forwardRef(
|
|
|
448
422
|
)
|
|
449
423
|
);
|
|
450
424
|
Select.displayName = "Select";
|
|
425
|
+
var TabsContext = React.createContext(null);
|
|
426
|
+
function useTabsContext() {
|
|
427
|
+
const ctx = React.useContext(TabsContext);
|
|
428
|
+
if (!ctx) throw new Error("Tabs sub-component must be used within <Tabs>");
|
|
429
|
+
return ctx;
|
|
430
|
+
}
|
|
451
431
|
function Tabs({ defaultValue, value, onValueChange, className, children }) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
children
|
|
460
|
-
}
|
|
461
|
-
);
|
|
432
|
+
const [internal, setInternal] = React.useState(defaultValue ?? "");
|
|
433
|
+
const current = value ?? internal;
|
|
434
|
+
const setValue = (v) => {
|
|
435
|
+
setInternal(v);
|
|
436
|
+
onValueChange?.(v);
|
|
437
|
+
};
|
|
438
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className, children }) });
|
|
462
439
|
}
|
|
463
440
|
function TabsList({
|
|
464
441
|
className,
|
|
465
442
|
children
|
|
466
443
|
}) {
|
|
467
|
-
return /* @__PURE__ */ jsx(
|
|
468
|
-
Tabs$1.List,
|
|
469
|
-
{
|
|
470
|
-
className: cn("inline-flex items-center gap-1 rounded-lg bg-muted p-1", className),
|
|
471
|
-
children
|
|
472
|
-
}
|
|
473
|
-
);
|
|
444
|
+
return /* @__PURE__ */ jsx("div", { className: cn("inline-flex items-center gap-1 rounded-lg bg-muted p-1", className), children });
|
|
474
445
|
}
|
|
475
446
|
function TabsTrigger({
|
|
476
447
|
value,
|
|
477
448
|
className,
|
|
478
449
|
children
|
|
479
450
|
}) {
|
|
451
|
+
const { value: current, setValue } = useTabsContext();
|
|
452
|
+
const active = current === value;
|
|
480
453
|
return /* @__PURE__ */ jsx(
|
|
481
|
-
|
|
454
|
+
"button",
|
|
482
455
|
{
|
|
483
|
-
|
|
456
|
+
type: "button",
|
|
457
|
+
onClick: () => setValue(value),
|
|
484
458
|
className: cn(
|
|
485
459
|
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
486
|
-
"text-muted-foreground hover:text-foreground",
|
|
487
|
-
"data-[active]:bg-card data-[active]:text-foreground data-[active]:shadow-sm",
|
|
460
|
+
active ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
|
|
488
461
|
className
|
|
489
462
|
),
|
|
490
463
|
children
|
|
@@ -496,25 +469,38 @@ function TabsContent({
|
|
|
496
469
|
className,
|
|
497
470
|
children
|
|
498
471
|
}) {
|
|
499
|
-
|
|
472
|
+
const { value: current } = useTabsContext();
|
|
473
|
+
if (current !== value) return null;
|
|
474
|
+
return /* @__PURE__ */ jsx("div", { className, children });
|
|
500
475
|
}
|
|
501
476
|
function Modal({ open, onClose, title, children, className }) {
|
|
502
|
-
|
|
503
|
-
|
|
477
|
+
if (!open) return null;
|
|
478
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
479
|
+
/* @__PURE__ */ jsx(
|
|
480
|
+
"button",
|
|
481
|
+
{
|
|
482
|
+
type: "button",
|
|
483
|
+
"aria-label": "Close",
|
|
484
|
+
className: "absolute inset-0 cursor-default bg-foreground/40",
|
|
485
|
+
onClick: onClose
|
|
486
|
+
}
|
|
487
|
+
),
|
|
504
488
|
/* @__PURE__ */ jsxs(
|
|
505
|
-
|
|
489
|
+
"div",
|
|
506
490
|
{
|
|
491
|
+
role: "dialog",
|
|
492
|
+
"aria-modal": true,
|
|
507
493
|
className: cn(
|
|
508
|
-
"
|
|
494
|
+
"relative z-10 w-full max-w-md rounded-xl border bg-card p-5 shadow-lg",
|
|
509
495
|
className
|
|
510
496
|
),
|
|
511
497
|
children: [
|
|
512
|
-
title && /* @__PURE__ */ jsx(
|
|
498
|
+
title && /* @__PURE__ */ jsx("h2", { className: "mb-3 text-base font-semibold", children: title }),
|
|
513
499
|
children
|
|
514
500
|
]
|
|
515
501
|
}
|
|
516
502
|
)
|
|
517
|
-
] })
|
|
503
|
+
] });
|
|
518
504
|
}
|
|
519
505
|
var spinnerSizes = { sm: "size-4", md: "size-6", lg: "size-8" };
|
|
520
506
|
function Spinner({ className, size = "md" }) {
|
|
@@ -564,19 +550,28 @@ function Switch({
|
|
|
564
550
|
...props
|
|
565
551
|
}) {
|
|
566
552
|
return /* @__PURE__ */ jsx(
|
|
567
|
-
|
|
553
|
+
"button",
|
|
568
554
|
{
|
|
569
|
-
|
|
570
|
-
|
|
555
|
+
type: "button",
|
|
556
|
+
role: "switch",
|
|
557
|
+
"aria-checked": checked,
|
|
571
558
|
disabled,
|
|
559
|
+
onClick: () => onCheckedChange?.(!checked),
|
|
572
560
|
className: cn(
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
"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",
|
|
561
|
+
"relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
562
|
+
checked ? "bg-primary" : "bg-input",
|
|
576
563
|
className
|
|
577
564
|
),
|
|
578
565
|
...props,
|
|
579
|
-
children: /* @__PURE__ */ jsx(
|
|
566
|
+
children: /* @__PURE__ */ jsx(
|
|
567
|
+
"span",
|
|
568
|
+
{
|
|
569
|
+
className: cn(
|
|
570
|
+
"inline-block size-4 transform rounded-full bg-white shadow transition-transform",
|
|
571
|
+
checked ? "translate-x-4" : "translate-x-0.5"
|
|
572
|
+
)
|
|
573
|
+
}
|
|
574
|
+
)
|
|
580
575
|
}
|
|
581
576
|
);
|
|
582
577
|
}
|
|
@@ -705,26 +700,47 @@ function SidePanel({
|
|
|
705
700
|
children,
|
|
706
701
|
className
|
|
707
702
|
}) {
|
|
708
|
-
|
|
709
|
-
|
|
703
|
+
React.useEffect(() => {
|
|
704
|
+
if (!open) return;
|
|
705
|
+
const onKeyDown = (e) => {
|
|
706
|
+
if (e.key === "Escape") onClose();
|
|
707
|
+
};
|
|
708
|
+
window.addEventListener("keydown", onKeyDown);
|
|
709
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
710
|
+
}, [open, onClose]);
|
|
711
|
+
if (!open) return null;
|
|
712
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", children: [
|
|
713
|
+
/* @__PURE__ */ jsx(
|
|
714
|
+
"button",
|
|
715
|
+
{
|
|
716
|
+
type: "button",
|
|
717
|
+
"aria-label": "Fermer",
|
|
718
|
+
className: "absolute inset-0 cursor-default bg-foreground/40",
|
|
719
|
+
onClick: onClose
|
|
720
|
+
}
|
|
721
|
+
),
|
|
710
722
|
/* @__PURE__ */ jsxs(
|
|
711
|
-
|
|
723
|
+
"aside",
|
|
712
724
|
{
|
|
725
|
+
role: "dialog",
|
|
726
|
+
"aria-modal": true,
|
|
713
727
|
className: cn(
|
|
714
|
-
"
|
|
728
|
+
"absolute inset-y-0 right-0 flex w-full max-w-lg flex-col border-l bg-card shadow-xl",
|
|
715
729
|
className
|
|
716
730
|
),
|
|
717
731
|
children: [
|
|
718
732
|
/* @__PURE__ */ jsxs("header", { className: "flex shrink-0 items-start gap-3 border-b px-5 py-4", children: [
|
|
719
733
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
720
|
-
title && /* @__PURE__ */ jsx(
|
|
721
|
-
description && /* @__PURE__ */ jsx(
|
|
734
|
+
title && /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold", children: title }),
|
|
735
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
|
|
722
736
|
] }),
|
|
723
737
|
/* @__PURE__ */ jsx(
|
|
724
|
-
|
|
738
|
+
"button",
|
|
725
739
|
{
|
|
740
|
+
type: "button",
|
|
726
741
|
"aria-label": "Fermer",
|
|
727
742
|
className: "-mr-1 shrink-0 rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
743
|
+
onClick: onClose,
|
|
728
744
|
children: /* @__PURE__ */ jsx(IconX, { className: "size-4" })
|
|
729
745
|
}
|
|
730
746
|
)
|
|
@@ -733,7 +749,7 @@ function SidePanel({
|
|
|
733
749
|
]
|
|
734
750
|
}
|
|
735
751
|
)
|
|
736
|
-
] })
|
|
752
|
+
] });
|
|
737
753
|
}
|
|
738
754
|
var COPY_FEEDBACK_MS = 2e3;
|
|
739
755
|
function CopyButton({
|
|
@@ -776,111 +792,69 @@ function Popover({
|
|
|
776
792
|
align = "start",
|
|
777
793
|
className
|
|
778
794
|
}) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
return /* @__PURE__ */ jsxs(
|
|
796
|
-
/* @__PURE__ */ jsx("
|
|
797
|
-
|
|
798
|
-
Menu.Popup,
|
|
799
|
-
{
|
|
800
|
-
className: cn(
|
|
801
|
-
"flex min-w-48 flex-col rounded-md border bg-card p-1 shadow-lg",
|
|
802
|
-
className
|
|
803
|
-
),
|
|
804
|
-
children: items.map((item, i) => /* @__PURE__ */ jsx(
|
|
805
|
-
Menu.Item,
|
|
806
|
-
{
|
|
807
|
-
disabled: item.disabled,
|
|
808
|
-
onClick: item.onSelect,
|
|
809
|
-
className: cn(
|
|
810
|
-
"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",
|
|
811
|
-
item.destructive && "text-destructive"
|
|
812
|
-
),
|
|
813
|
-
children: item.label
|
|
814
|
-
},
|
|
815
|
-
i
|
|
816
|
-
))
|
|
817
|
-
}
|
|
818
|
-
) }) })
|
|
819
|
-
] });
|
|
820
|
-
}
|
|
821
|
-
var ToastContext = createContext(null);
|
|
822
|
-
function useToast() {
|
|
823
|
-
const toast = useContext(ToastContext);
|
|
824
|
-
if (!toast) throw new Error("useToast must be used within ToastProvider");
|
|
825
|
-
return toast;
|
|
826
|
-
}
|
|
827
|
-
var TOAST_TTL_MS = 4e3;
|
|
828
|
-
var TONE = {
|
|
829
|
-
success: "border-l-status-success",
|
|
830
|
-
error: "border-l-status-blocked",
|
|
831
|
-
info: "border-l-status-info"
|
|
832
|
-
};
|
|
833
|
-
function ToastProvider({ children }) {
|
|
834
|
-
const [toasts, setToasts] = useState([]);
|
|
835
|
-
const nextId = useRef(0);
|
|
836
|
-
const toast = useCallback((input) => {
|
|
837
|
-
const id = nextId.current++;
|
|
838
|
-
setToasts((prev) => [...prev, { id, ...input }]);
|
|
839
|
-
setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), TOAST_TTL_MS);
|
|
840
|
-
}, []);
|
|
841
|
-
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: toast, children: [
|
|
842
|
-
children,
|
|
843
|
-
/* @__PURE__ */ 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__ */ jsxs(
|
|
795
|
+
const root = React.useRef(null);
|
|
796
|
+
React.useEffect(() => {
|
|
797
|
+
if (!open) return;
|
|
798
|
+
const onPointerDown = (e) => {
|
|
799
|
+
if (!root.current?.contains(e.target)) onOpenChange(false);
|
|
800
|
+
};
|
|
801
|
+
const onKeyDown = (e) => {
|
|
802
|
+
if (e.key === "Escape") onOpenChange(false);
|
|
803
|
+
};
|
|
804
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
805
|
+
document.addEventListener("keydown", onKeyDown);
|
|
806
|
+
return () => {
|
|
807
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
808
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
809
|
+
};
|
|
810
|
+
}, [open, onOpenChange]);
|
|
811
|
+
return /* @__PURE__ */ jsxs("div", { ref: root, className: "relative inline-block", children: [
|
|
812
|
+
/* @__PURE__ */ jsx("button", { type: "button", "aria-expanded": open, onClick: () => onOpenChange(!open), children: trigger }),
|
|
813
|
+
open && /* @__PURE__ */ jsx(
|
|
844
814
|
"div",
|
|
845
815
|
{
|
|
846
|
-
role: "status",
|
|
847
816
|
className: cn(
|
|
848
|
-
"
|
|
849
|
-
|
|
850
|
-
),
|
|
851
|
-
children: [
|
|
852
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: t.title }),
|
|
853
|
-
t.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 break-all text-xs text-muted-foreground", children: t.description })
|
|
854
|
-
]
|
|
855
|
-
},
|
|
856
|
-
t.id
|
|
857
|
-
)) })
|
|
858
|
-
] });
|
|
859
|
-
}
|
|
860
|
-
var SIDES = {
|
|
861
|
-
top: "bottom-full left-1/2 -translate-x-1/2 mb-1.5",
|
|
862
|
-
right: "left-full top-1/2 -translate-y-1/2 ml-1.5",
|
|
863
|
-
bottom: "top-full left-1/2 -translate-x-1/2 mt-1.5",
|
|
864
|
-
left: "right-full top-1/2 -translate-y-1/2 mr-1.5"
|
|
865
|
-
};
|
|
866
|
-
function Tooltip({ label, children, side = "top", className }) {
|
|
867
|
-
return /* @__PURE__ */ jsxs("span", { className: "group/tt relative inline-flex", children: [
|
|
868
|
-
children,
|
|
869
|
-
/* @__PURE__ */ jsx(
|
|
870
|
-
"span",
|
|
871
|
-
{
|
|
872
|
-
role: "tooltip",
|
|
873
|
-
className: cn(
|
|
874
|
-
"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",
|
|
875
|
-
SIDES[side],
|
|
817
|
+
"absolute z-40 mt-1 min-w-48 rounded-md border bg-card p-2 shadow-lg",
|
|
818
|
+
align === "end" ? "right-0" : "left-0",
|
|
876
819
|
className
|
|
877
820
|
),
|
|
878
|
-
children
|
|
821
|
+
children
|
|
879
822
|
}
|
|
880
823
|
)
|
|
881
824
|
] });
|
|
882
825
|
}
|
|
826
|
+
function DropdownMenu({ trigger, items, align = "end", className }) {
|
|
827
|
+
const [open, setOpen] = React.useState(false);
|
|
828
|
+
return /* @__PURE__ */ jsx(
|
|
829
|
+
Popover,
|
|
830
|
+
{
|
|
831
|
+
open,
|
|
832
|
+
onOpenChange: setOpen,
|
|
833
|
+
trigger,
|
|
834
|
+
align,
|
|
835
|
+
className: cn("p-1", className),
|
|
836
|
+
children: /* @__PURE__ */ jsx("div", { role: "menu", className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ jsx(
|
|
837
|
+
"button",
|
|
838
|
+
{
|
|
839
|
+
type: "button",
|
|
840
|
+
role: "menuitem",
|
|
841
|
+
disabled: item.disabled,
|
|
842
|
+
className: cn(
|
|
843
|
+
"cursor-pointer rounded px-2 py-1.5 text-left text-sm hover:bg-accent disabled:pointer-events-none disabled:opacity-50",
|
|
844
|
+
item.destructive && "text-destructive"
|
|
845
|
+
),
|
|
846
|
+
onClick: () => {
|
|
847
|
+
setOpen(false);
|
|
848
|
+
item.onSelect();
|
|
849
|
+
},
|
|
850
|
+
children: item.label
|
|
851
|
+
},
|
|
852
|
+
i
|
|
853
|
+
)) })
|
|
854
|
+
}
|
|
855
|
+
);
|
|
856
|
+
}
|
|
883
857
|
|
|
884
|
-
export { AppApiProvider, AppContextProvider, AppInvokeError, Badge, Button, Card, CardContent,
|
|
858
|
+
export { AppApiProvider, AppContextProvider, AppInvokeError, Badge, Button, Card, CardContent, CardHeader, CardTitle, Checkbox, CopyButton, DateRangePicker, DropdownMenu, Input, Link, Modal, Popover, Select, SidePanel, Spinner, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings };
|
|
885
859
|
//# sourceMappingURL=index.js.map
|
|
886
860
|
//# sourceMappingURL=index.js.map
|