@apotech-os/ui-sdk 0.9.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 +173 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -6
- package/dist/index.d.ts +51 -6
- package/dist/index.js +167 -141
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
3
4
|
import { AppErrorCode, AppRunRecord, AppRunStatus } from '@apotech-os/app-kit';
|
|
4
5
|
export { AppRunRecord, AppRunStatus } from '@apotech-os/app-kit';
|
|
5
6
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
@@ -159,7 +160,9 @@ declare function Badge({ className, variant, dot, children, ...props }: BadgePro
|
|
|
159
160
|
declare function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
160
161
|
declare function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
161
162
|
declare function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): React.JSX.Element;
|
|
163
|
+
declare function CardDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>): React.JSX.Element;
|
|
162
164
|
declare function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
165
|
+
declare function CardFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
163
166
|
declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement>>;
|
|
164
167
|
declare function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>): React.JSX.Element;
|
|
165
168
|
declare function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
|
|
@@ -191,7 +194,7 @@ declare function TabsContent({ value, className, children, }: {
|
|
|
191
194
|
value: string;
|
|
192
195
|
className?: string;
|
|
193
196
|
children: React.ReactNode;
|
|
194
|
-
}): React.JSX.Element
|
|
197
|
+
}): React.JSX.Element;
|
|
195
198
|
interface ModalProps {
|
|
196
199
|
open: boolean;
|
|
197
200
|
onClose: () => void;
|
|
@@ -199,7 +202,8 @@ interface ModalProps {
|
|
|
199
202
|
children: React.ReactNode;
|
|
200
203
|
className?: string;
|
|
201
204
|
}
|
|
202
|
-
|
|
205
|
+
/** Centred blocking dialog. Base UI owns the focus trap, focus restore and Escape. */
|
|
206
|
+
declare function Modal({ open, onClose, title, children, className }: ModalProps): React.JSX.Element;
|
|
203
207
|
interface SpinnerProps {
|
|
204
208
|
className?: string;
|
|
205
209
|
size?: 'sm' | 'md' | 'lg';
|
|
@@ -209,6 +213,10 @@ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
|
209
213
|
variant?: 'default' | 'muted';
|
|
210
214
|
}
|
|
211
215
|
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
|
+
*/
|
|
212
220
|
interface SwitchProps {
|
|
213
221
|
checked?: boolean;
|
|
214
222
|
onCheckedChange?: (checked: boolean) => void;
|
|
@@ -254,9 +262,10 @@ interface SidePanelProps {
|
|
|
254
262
|
* Children are laid out in a flex column filling the panel: put the scrollable
|
|
255
263
|
* region in a `min-h-0 flex-1 overflow-y-auto` child and the footer after it.
|
|
256
264
|
*
|
|
257
|
-
*
|
|
265
|
+
* Focus is trapped inside while open and restored to the opener on close — Base
|
|
266
|
+
* UI's dialog does both, which is what the hand-rolled version never did.
|
|
258
267
|
*/
|
|
259
|
-
declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element
|
|
268
|
+
declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element;
|
|
260
269
|
interface CopyButtonProps {
|
|
261
270
|
value: string;
|
|
262
271
|
label?: string;
|
|
@@ -294,9 +303,45 @@ interface DropdownMenuProps {
|
|
|
294
303
|
align?: 'start' | 'end';
|
|
295
304
|
className?: string;
|
|
296
305
|
}
|
|
297
|
-
/** Uncontrolled menu
|
|
306
|
+
/** Uncontrolled menu. Selecting an item closes it; arrow keys move between them. */
|
|
298
307
|
declare function DropdownMenu({ trigger, items, align, className }: DropdownMenuProps): React.JSX.Element;
|
|
299
308
|
|
|
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
|
+
|
|
300
345
|
/**
|
|
301
346
|
* Browser helpers for app pages.
|
|
302
347
|
*
|
|
@@ -326,4 +371,4 @@ declare function toCsv(rows: string[][]): string;
|
|
|
326
371
|
*/
|
|
327
372
|
declare function downloadCsv(rows: string[][], filename: string): void;
|
|
328
373
|
|
|
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 };
|
|
374
|
+
export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, AppInvokeError, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, 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, type ToastInput, ToastProvider, Tooltip, type TooltipProps, badgeVariants, buttonVariants, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings, useToast };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,11 @@ 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';
|
|
5
10
|
import { cva } from 'class-variance-authority';
|
|
6
11
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
12
|
|
|
@@ -289,6 +294,12 @@ function downloadCsv(rows, filename) {
|
|
|
289
294
|
const blob = new Blob([`${BOM}${toCsv(rows)}`], { type: "text/csv;charset=utf-8" });
|
|
290
295
|
downloadBlob(blob, filename);
|
|
291
296
|
}
|
|
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
|
+
}
|
|
292
303
|
var buttonVariants = cva(
|
|
293
304
|
"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",
|
|
294
305
|
{
|
|
@@ -352,9 +363,18 @@ function CardHeader({ className, ...props }) {
|
|
|
352
363
|
function CardTitle({ className, ...props }) {
|
|
353
364
|
return /* @__PURE__ */ jsx("h3", { className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props });
|
|
354
365
|
}
|
|
366
|
+
function CardDescription({
|
|
367
|
+
className,
|
|
368
|
+
...props
|
|
369
|
+
}) {
|
|
370
|
+
return /* @__PURE__ */ jsx("p", { className: cn("text-sm text-muted-foreground", className), ...props });
|
|
371
|
+
}
|
|
355
372
|
function CardContent({ className, ...props }) {
|
|
356
373
|
return /* @__PURE__ */ jsx("div", { className: cn("p-6 pt-0", className), ...props });
|
|
357
374
|
}
|
|
375
|
+
function CardFooter({ className, ...props }) {
|
|
376
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center p-6 pt-0", className), ...props });
|
|
377
|
+
}
|
|
358
378
|
var Input = React.forwardRef(({ className, type, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
359
379
|
"input",
|
|
360
380
|
{
|
|
@@ -375,7 +395,13 @@ function TableHeader({
|
|
|
375
395
|
className,
|
|
376
396
|
...props
|
|
377
397
|
}) {
|
|
378
|
-
return /* @__PURE__ */ jsx(
|
|
398
|
+
return /* @__PURE__ */ jsx(
|
|
399
|
+
"thead",
|
|
400
|
+
{
|
|
401
|
+
className: cn("[&_tr]:border-b [&_tr]:hover:bg-transparent", className),
|
|
402
|
+
...props
|
|
403
|
+
}
|
|
404
|
+
);
|
|
379
405
|
}
|
|
380
406
|
function TableBody({ className, ...props }) {
|
|
381
407
|
return /* @__PURE__ */ jsx("tbody", { className: cn("[&_tr:last-child]:border-0", className), ...props });
|
|
@@ -397,7 +423,7 @@ function TableHead({ className, ...props }) {
|
|
|
397
423
|
"th",
|
|
398
424
|
{
|
|
399
425
|
className: cn(
|
|
400
|
-
"h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground",
|
|
426
|
+
"h-10 px-4 text-left align-middle text-xs font-medium uppercase tracking-wide text-muted-foreground",
|
|
401
427
|
className
|
|
402
428
|
),
|
|
403
429
|
...props
|
|
@@ -422,42 +448,43 @@ var Select = React.forwardRef(
|
|
|
422
448
|
)
|
|
423
449
|
);
|
|
424
450
|
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
|
-
}
|
|
431
451
|
function Tabs({ defaultValue, value, onValueChange, className, children }) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
452
|
+
return /* @__PURE__ */ jsx(
|
|
453
|
+
Tabs$1.Root,
|
|
454
|
+
{
|
|
455
|
+
className,
|
|
456
|
+
defaultValue,
|
|
457
|
+
value,
|
|
458
|
+
onValueChange: (next) => onValueChange?.(String(next)),
|
|
459
|
+
children
|
|
460
|
+
}
|
|
461
|
+
);
|
|
439
462
|
}
|
|
440
463
|
function TabsList({
|
|
441
464
|
className,
|
|
442
465
|
children
|
|
443
466
|
}) {
|
|
444
|
-
return /* @__PURE__ */ jsx(
|
|
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
|
+
);
|
|
445
474
|
}
|
|
446
475
|
function TabsTrigger({
|
|
447
476
|
value,
|
|
448
477
|
className,
|
|
449
478
|
children
|
|
450
479
|
}) {
|
|
451
|
-
const { value: current, setValue } = useTabsContext();
|
|
452
|
-
const active = current === value;
|
|
453
480
|
return /* @__PURE__ */ jsx(
|
|
454
|
-
|
|
481
|
+
Tabs$1.Tab,
|
|
455
482
|
{
|
|
456
|
-
|
|
457
|
-
onClick: () => setValue(value),
|
|
483
|
+
value,
|
|
458
484
|
className: cn(
|
|
459
485
|
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
460
|
-
|
|
486
|
+
"text-muted-foreground hover:text-foreground",
|
|
487
|
+
"data-[active]:bg-card data-[active]:text-foreground data-[active]:shadow-sm",
|
|
461
488
|
className
|
|
462
489
|
),
|
|
463
490
|
children
|
|
@@ -469,38 +496,25 @@ function TabsContent({
|
|
|
469
496
|
className,
|
|
470
497
|
children
|
|
471
498
|
}) {
|
|
472
|
-
|
|
473
|
-
if (current !== value) return null;
|
|
474
|
-
return /* @__PURE__ */ jsx("div", { className, children });
|
|
499
|
+
return /* @__PURE__ */ jsx(Tabs$1.Panel, { value, className, children });
|
|
475
500
|
}
|
|
476
501
|
function Modal({ open, onClose, title, children, className }) {
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
),
|
|
502
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
|
|
503
|
+
/* @__PURE__ */ jsx(Dialog.Backdrop, { "aria-label": "Close", className: "fixed inset-0 z-50 bg-foreground/40" }),
|
|
488
504
|
/* @__PURE__ */ jsxs(
|
|
489
|
-
|
|
505
|
+
Dialog.Popup,
|
|
490
506
|
{
|
|
491
|
-
role: "dialog",
|
|
492
|
-
"aria-modal": true,
|
|
493
507
|
className: cn(
|
|
494
|
-
"
|
|
508
|
+
"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",
|
|
495
509
|
className
|
|
496
510
|
),
|
|
497
511
|
children: [
|
|
498
|
-
title && /* @__PURE__ */ jsx(
|
|
512
|
+
title && /* @__PURE__ */ jsx(Dialog.Title, { className: "mb-3 text-base font-semibold", children: title }),
|
|
499
513
|
children
|
|
500
514
|
]
|
|
501
515
|
}
|
|
502
516
|
)
|
|
503
|
-
] });
|
|
517
|
+
] }) });
|
|
504
518
|
}
|
|
505
519
|
var spinnerSizes = { sm: "size-4", md: "size-6", lg: "size-8" };
|
|
506
520
|
function Spinner({ className, size = "md" }) {
|
|
@@ -550,28 +564,19 @@ function Switch({
|
|
|
550
564
|
...props
|
|
551
565
|
}) {
|
|
552
566
|
return /* @__PURE__ */ jsx(
|
|
553
|
-
|
|
567
|
+
Switch$1.Root,
|
|
554
568
|
{
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
"aria-checked": checked,
|
|
569
|
+
checked,
|
|
570
|
+
onCheckedChange: (next) => onCheckedChange?.(next),
|
|
558
571
|
disabled,
|
|
559
|
-
onClick: () => onCheckedChange?.(!checked),
|
|
560
572
|
className: cn(
|
|
561
|
-
|
|
562
|
-
|
|
573
|
+
// `data-[disabled]`, not `disabled:` — the root is a span, so `:disabled`
|
|
574
|
+
// never matches it and the dimming would silently stop happening.
|
|
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",
|
|
563
576
|
className
|
|
564
577
|
),
|
|
565
578
|
...props,
|
|
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
|
-
)
|
|
579
|
+
children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: "inline-block size-4 translate-x-0.5 rounded-full bg-white shadow transition-transform data-[checked]:translate-x-4" })
|
|
575
580
|
}
|
|
576
581
|
);
|
|
577
582
|
}
|
|
@@ -700,47 +705,26 @@ function SidePanel({
|
|
|
700
705
|
children,
|
|
701
706
|
className
|
|
702
707
|
}) {
|
|
703
|
-
|
|
704
|
-
|
|
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
|
-
),
|
|
708
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
|
|
709
|
+
/* @__PURE__ */ jsx(Dialog.Backdrop, { "aria-label": "Fermer", className: "fixed inset-0 z-50 bg-foreground/40" }),
|
|
722
710
|
/* @__PURE__ */ jsxs(
|
|
723
|
-
|
|
711
|
+
Dialog.Popup,
|
|
724
712
|
{
|
|
725
|
-
role: "dialog",
|
|
726
|
-
"aria-modal": true,
|
|
727
713
|
className: cn(
|
|
728
|
-
"
|
|
714
|
+
"fixed inset-y-0 right-0 z-50 flex w-full max-w-lg flex-col border-l bg-card shadow-xl",
|
|
729
715
|
className
|
|
730
716
|
),
|
|
731
717
|
children: [
|
|
732
718
|
/* @__PURE__ */ jsxs("header", { className: "flex shrink-0 items-start gap-3 border-b px-5 py-4", children: [
|
|
733
719
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
734
|
-
title && /* @__PURE__ */ jsx(
|
|
735
|
-
description && /* @__PURE__ */ jsx(
|
|
720
|
+
title && /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold", children: title }),
|
|
721
|
+
description && /* @__PURE__ */ jsx(Dialog.Description, { className: "mt-0.5 text-xs text-muted-foreground", children: description })
|
|
736
722
|
] }),
|
|
737
723
|
/* @__PURE__ */ jsx(
|
|
738
|
-
|
|
724
|
+
Dialog.Close,
|
|
739
725
|
{
|
|
740
|
-
type: "button",
|
|
741
726
|
"aria-label": "Fermer",
|
|
742
727
|
className: "-mr-1 shrink-0 rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
743
|
-
onClick: onClose,
|
|
744
728
|
children: /* @__PURE__ */ jsx(IconX, { className: "size-4" })
|
|
745
729
|
}
|
|
746
730
|
)
|
|
@@ -749,7 +733,7 @@ function SidePanel({
|
|
|
749
733
|
]
|
|
750
734
|
}
|
|
751
735
|
)
|
|
752
|
-
] });
|
|
736
|
+
] }) });
|
|
753
737
|
}
|
|
754
738
|
var COPY_FEEDBACK_MS = 2e3;
|
|
755
739
|
function CopyButton({
|
|
@@ -792,69 +776,111 @@ function Popover({
|
|
|
792
776
|
align = "start",
|
|
793
777
|
className
|
|
794
778
|
}) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
return /* @__PURE__ */ jsxs(
|
|
812
|
-
/* @__PURE__ */ jsx("
|
|
813
|
-
|
|
779
|
+
return (
|
|
780
|
+
// The callback is re-wrapped so Base UI's event-details argument stops at the
|
|
781
|
+
// SDK boundary: the engine is an implementation detail, not part of the API.
|
|
782
|
+
/* @__PURE__ */ jsxs(Popover$1.Root, { open, onOpenChange: (next) => onOpenChange(next), children: [
|
|
783
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block", children: /* @__PURE__ */ jsx(Popover$1.Trigger, { ...triggerProps(trigger) }) }),
|
|
784
|
+
/* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Positioner, { side: "bottom", align, sideOffset: 4, className: "z-50", children: /* @__PURE__ */ jsx(
|
|
785
|
+
Popover$1.Popup,
|
|
786
|
+
{
|
|
787
|
+
className: cn("min-w-48 rounded-md border bg-card p-2 shadow-lg", className),
|
|
788
|
+
children
|
|
789
|
+
}
|
|
790
|
+
) }) })
|
|
791
|
+
] })
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
function DropdownMenu({ trigger, items, align = "end", className }) {
|
|
795
|
+
return /* @__PURE__ */ jsxs(Menu.Root, { children: [
|
|
796
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block", children: /* @__PURE__ */ jsx(Menu.Trigger, { ...triggerProps(trigger) }) }),
|
|
797
|
+
/* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { side: "bottom", align, sideOffset: 4, className: "z-50", children: /* @__PURE__ */ jsx(
|
|
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(
|
|
814
844
|
"div",
|
|
815
845
|
{
|
|
846
|
+
role: "status",
|
|
816
847
|
className: cn(
|
|
817
|
-
"
|
|
818
|
-
|
|
848
|
+
"pointer-events-auto rounded-lg border border-l-4 bg-card px-4 py-3 text-foreground shadow-md",
|
|
849
|
+
TONE[t.variant ?? "success"]
|
|
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],
|
|
819
876
|
className
|
|
820
877
|
),
|
|
821
|
-
children
|
|
878
|
+
children: label
|
|
822
879
|
}
|
|
823
880
|
)
|
|
824
881
|
] });
|
|
825
882
|
}
|
|
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
|
-
}
|
|
857
883
|
|
|
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 };
|
|
884
|
+
export { AppApiProvider, AppContextProvider, AppInvokeError, Badge, Button, Card, CardContent, CardDescription, CardFooter, 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, ToastProvider, Tooltip, badgeVariants, buttonVariants, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings, useToast };
|
|
859
885
|
//# sourceMappingURL=index.js.map
|
|
860
886
|
//# sourceMappingURL=index.js.map
|