@nocoo/basalt 3.0.0 → 3.1.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/ai/DESIGN.md +64 -8
- package/ai/INTEGRATION.md +83 -8
- package/ai/USAGE.md +2 -2
- package/ai/registry.json +198 -17
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/data-table.d.ts +7 -1
- package/dist/components/data-table.js +127 -132
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/dialog.js +2 -2
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/diff-table.js +18 -13
- package/dist/components/diff-table.js.map +1 -1
- package/dist/components/sidebar.js +18 -15
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/table.d.ts +39 -2
- package/dist/components/table.js +48 -17
- package/dist/components/table.js.map +1 -1
- package/dist/styles/standalone.css +29 -7
- package/dist/styles/tailwind.css +1 -0
- package/dist/styles/tokens.css +2 -0
- package/dist/utils/use-hover-highlight.js +38 -36
- package/dist/utils/use-hover-highlight.js.map +1 -1
- package/package.json +28 -28
|
@@ -46,7 +46,7 @@ var g = i.forwardRef(({ className: e, children: t, size: n = "base", disablePoin
|
|
|
46
46
|
g.displayName = s.Content.displayName;
|
|
47
47
|
var _ = i.forwardRef(({ className: t, ...n }, r) => /* @__PURE__ */ a(s.Title, {
|
|
48
48
|
ref: r,
|
|
49
|
-
className: e("text-basalt-3xl font-semibold tracking-tight", t),
|
|
49
|
+
className: e("min-w-0 text-basalt-3xl font-semibold tracking-tight wrap-anywhere", t),
|
|
50
50
|
...n
|
|
51
51
|
}));
|
|
52
52
|
_.displayName = s.Title.displayName;
|
|
@@ -62,7 +62,7 @@ var y = ({ className: t, ...n }) => /* @__PURE__ */ a("div", {
|
|
|
62
62
|
});
|
|
63
63
|
y.displayName = "DialogHeader";
|
|
64
64
|
var b = ({ className: t, ...n }) => /* @__PURE__ */ a("div", {
|
|
65
|
-
className: e("mt-basalt-
|
|
65
|
+
className: e("mt-basalt-layout flex flex-col-reverse gap-basalt-space-lg sm:flex-row sm:justify-end", t),
|
|
66
66
|
...n
|
|
67
67
|
});
|
|
68
68
|
b.displayName = "DialogFooter";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":["React","DialogPrimitive","DIALOG_SIZES","dialogOverlayClass","cn","OVERLAY_LAYER","OVERLAY_MOTION","className","dialogPanelClass","BASALT_UI_CLASS","size","Dialog","DialogTrigger","DialogClose","DialogPortal","DialogOverlay","props","DialogContent","disablePointerDismissal","event","onPointerDownOutside","onInteractOutside","DialogTitle","DialogDescription","DialogHeader","DialogFooter"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-basalt-72\",\n\tbase: \"sm:w-basalt-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-basalt-backdrop/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-basalt-card sm:p-basalt-card-lg text-basalt-foreground shadow-lg ring-1 ring-basalt-border\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out\",\n\t\tOVERLAY_MOTION,\n\t\tDIALOG_SIZES[size],\n\t\tclassName,\n\t);\n}\n\ntype RadixDialogProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;\ntype RadixDialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\ntype RadixDialogPortalProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>;\ntype RadixDialogOverlayProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>;\ntype RadixDialogContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;\ntype RadixDialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\ntype RadixDialogDescriptionProps = React.ComponentPropsWithoutRef<\n\ttypeof DialogPrimitive.Description\n>;\ntype RadixDialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogProps\n\textends Omit<RadixDialogProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"modal\"> {\n\t/**\n\t * Controlled open state of the dialog.\n\t */\n\topen?: RadixDialogProps[\"open\"];\n\t/**\n\t * Uncontrolled default open state of the dialog on initial render.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDialogProps[\"defaultOpen\"];\n\t/**\n\t * Callback invoked when the open state changes.\n\t */\n\tonOpenChange?: RadixDialogProps[\"onOpenChange\"];\n\t/**\n\t * Whether the dialog renders modally, preventing outside interaction and hiding background content from screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDialogProps[\"modal\"];\n}\n\nexport const Dialog: React.FC<DialogProps> = DialogPrimitive.Root;\n\nexport interface DialogTriggerProps extends Omit<RadixDialogTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Trigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTriggerProps[\"asChild\"];\n}\n\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\nexport interface DialogCloseProps extends Omit<RadixDialogCloseProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Close forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogCloseProps[\"asChild\"];\n}\n\nexport const DialogClose = DialogPrimitive.Close;\n\nexport interface DialogPortalProps\n\textends Omit<RadixDialogPortalProps, \"container\" | \"forceMount\"> {\n\t/**\n\t * Target container element where the dialog overlay and content portal should mount.\n\t */\n\tcontainer?: RadixDialogPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogPortalProps[\"forceMount\"];\n}\n\nexport const DialogPortal = DialogPrimitive.Portal;\n\nexport interface DialogOverlayProps\n\textends Omit<RadixDialogOverlayProps, \"asChild\" | \"forceMount\"> {\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Overlay forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogOverlayProps[\"asChild\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogOverlayProps[\"forceMount\"];\n}\n\nexport const DialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Overlay>,\n\tDialogOverlayProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nexport interface DialogContentProps\n\textends Omit<\n\t\tRadixDialogContentProps,\n\t\t| \"size\"\n\t\t| \"disablePointerDismissal\"\n\t\t| \"asChild\"\n\t\t| \"forceMount\"\n\t\t| \"trapFocus\"\n\t\t| \"onOpenAutoFocus\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t> {\n\t/**\n\t * Fixed desktop width preset. Dialog panel scrolls vertically when content overflows available viewport height.\n\t * @default \"base\"\n\t */\n\tsize?: DialogSize;\n\t/**\n\t * When true, pointer interactions outside the dialog panel are prevented from dismissing the dialog.\n\t * @default false\n\t */\n\tdisablePointerDismissal?: boolean;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Content forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogContentProps[\"asChild\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: RadixDialogContentProps[\"forceMount\"];\n\t/**\n\t * Event handler called when auto-focusing the first element on open. Can be prevented with event.preventDefault().\n\t */\n\tonOpenAutoFocus?: RadixDialogContentProps[\"onOpenAutoFocus\"];\n\t/**\n\t * Event handler called when restoring focus on close. Can be prevented with event.preventDefault().\n\t */\n\tonCloseAutoFocus?: RadixDialogContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Event handler called when the Escape key is pressed. Can be prevented with event.preventDefault().\n\t */\n\tonEscapeKeyDown?: RadixDialogContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Event handler called when a pointer event occurs outside the dialog bounds.\n\t */\n\tonPointerDownOutside?: RadixDialogContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Event handler called when focus moves outside the dialog bounds.\n\t */\n\tonFocusOutside?: RadixDialogContentProps[\"onFocusOutside\"];\n\t/**\n\t * Event handler called when any interaction (pointer or focus) occurs outside the dialog bounds.\n\t */\n\tonInteractOutside?: RadixDialogContentProps[\"onInteractOutside\"];\n}\n\nexport const DialogContent = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Content>,\n\tDialogContentProps\n>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tsize = \"base\",\n\t\t\tdisablePointerDismissal = false,\n\t\t\tonPointerDownOutside,\n\t\t\tonInteractOutside,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<DialogPortal forceMount={props.forceMount}>\n\t\t\t<DialogOverlay forceMount={props.forceMount} />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface-root=\"\"\n\t\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t\tonPointerDownOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonPointerDownOutside?.(event);\n\t\t\t\t}}\n\t\t\t\tonInteractOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonInteractOutside?.(event);\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t),\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nexport interface DialogTitleProps extends Omit<RadixDialogTitleProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered heading element to the child element, merging props and behavior.\n\t * Title forwards ref to HTMLHeadingElement and inherits native h2 attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTitleProps[\"asChild\"];\n}\n\nexport const DialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Title>,\n\tDialogTitleProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-basalt-3xl font-semibold tracking-tight\", className)}\n\t\t{...props}\n\t/>\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nexport interface DialogDescriptionProps extends Omit<RadixDialogDescriptionProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered paragraph element to the child element, merging props and behavior.\n\t * Description forwards ref to HTMLParagraphElement and inherits native p attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogDescriptionProps[\"asChild\"];\n}\n\nexport const DialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Description>,\n\tDialogDescriptionProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-basalt-lg text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = ({ className, ...props }: DialogHeaderProps) => (\n\t<div className={cn(\"flex flex-col space-y-basalt-space-md text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = ({ className, ...props }: DialogFooterProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"mt-basalt-space-lg flex flex-col-reverse gap-basalt-space-lg sm:flex-row sm:justify-end\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAaE,IAAe;CAC3B,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;AACL;AAIA,SAAgBC,EAAmB,GAAoB;CACtD,OAAOC,EACN,wDACAC,GACA,8FACAC,GACAC,CACD;AACD;AAEA,SAAgBC,EAAiB,EAChC,UAAO,QACP,iBAIG,CAAC,GAAG;CACP,OAAOJ,EACNK,GACA,kQACAJ,GACA,4FACAC,GACAJ,EAAaQ,IACbH,CACD;AACD;AAmCA,IAAaI,IAAgCV,EAAgB,MAWhDW,IAAgBX,EAAgB,SAWhCY,IAAcZ,EAAgB,OAc9Ba,IAAeb,EAAgB,QAgB/Bc,IAAgBf,EAAM,YAGhC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,SAAjB;CAA8B;CAAK,WAAWE,EAAmBI,CAAS;CAAG,GAAIS;AAAQ,CAAA,CACzF;AACD,EAAc,cAAcf,EAAgB,QAAQ;AAkEpD,IAAagB,IAAgBjB,EAAM,YAKjC,EACC,cACA,aACA,UAAO,QACP,6BAA0B,IAC1B,yBACA,sBACA,GAAGgB,KAEJ,MAEA,kBAACF,GAAD;CAAc,YAAYE,EAAM;CAAhC,UAAA,CACC,kBAACD,GAAD,EAAe,YAAYC,EAAM,WAAa,CAAA,GAC9C,kBAACf,EAAgB,SAAjB;EACM;EACL,4BAAyB;EACzB,WAAWO,EAAiB;GAAE;GAAM;EAAU,CAAC;EAC/C,uBAAuB,MAAU;GAIhC,AAHIU,KACHC,EAAM,eAAe,GAEtBC,IAAuBD,CAAK;EAC7B;EACA,oBAAoB,MAAU;GAI7B,AAHID,KACHC,EAAM,eAAe,GAEtBE,IAAoBF,CAAK;EAC1B;EACA,GAAIH;EAEH;CACuB,CAAA,CACZ;AAEhB,CAAA,CAAA;AACA,EAAc,cAAcf,EAAgB,QAAQ;AAWpD,IAAaqB,IAActB,EAAM,YAG9B,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,OAAjB;CACM;CACL,WAAWG,EAAG,gDAAgDG,CAAS;CACvE,GAAIS;AACJ,CAAA,CACD;AACD,EAAY,cAAcf,EAAgB,MAAM;AAWhD,IAAasB,IAAoBvB,EAAM,YAGpC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,aAAjB;CACM;CACL,WAAWG,EAAG,+CAA+CG,CAAS;CACtE,GAAIS;AACJ,CAAA,CACD;AACD,EAAkB,cAAcf,EAAgB,YAAY;AAI5D,IAAauB,KAAgB,EAAE,cAAW,GAAGR,QAC5C,kBAAC,OAAD;CAAK,WAAWZ,EAAG,mDAAmDG,CAAS;CAAG,GAAIS;AAAQ,CAAA;AAE/F,EAAa,cAAc;AAI3B,IAAaS,KAAgB,EAAE,cAAW,GAAGT,QAC5C,kBAAC,OAAD;CACC,WAAWZ,EACV,2FACAG,CACD;CACA,GAAIS;AACJ,CAAA;AAEF,EAAa,cAAc"}
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["React","DialogPrimitive","DIALOG_SIZES","dialogOverlayClass","cn","OVERLAY_LAYER","OVERLAY_MOTION","className","dialogPanelClass","BASALT_UI_CLASS","size","Dialog","DialogTrigger","DialogClose","DialogPortal","DialogOverlay","props","DialogContent","disablePointerDismissal","event","onPointerDownOutside","onInteractOutside","DialogTitle","DialogDescription","DialogHeader","DialogFooter"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-basalt-72\",\n\tbase: \"sm:w-basalt-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-basalt-backdrop/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-basalt-card sm:p-basalt-card-lg text-basalt-foreground shadow-lg ring-1 ring-basalt-border\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out\",\n\t\tOVERLAY_MOTION,\n\t\tDIALOG_SIZES[size],\n\t\tclassName,\n\t);\n}\n\ntype RadixDialogProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;\ntype RadixDialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\ntype RadixDialogPortalProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>;\ntype RadixDialogOverlayProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>;\ntype RadixDialogContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;\ntype RadixDialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\ntype RadixDialogDescriptionProps = React.ComponentPropsWithoutRef<\n\ttypeof DialogPrimitive.Description\n>;\ntype RadixDialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogProps\n\textends Omit<RadixDialogProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"modal\"> {\n\t/**\n\t * Controlled open state of the dialog.\n\t */\n\topen?: RadixDialogProps[\"open\"];\n\t/**\n\t * Uncontrolled default open state of the dialog on initial render.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDialogProps[\"defaultOpen\"];\n\t/**\n\t * Callback invoked when the open state changes.\n\t */\n\tonOpenChange?: RadixDialogProps[\"onOpenChange\"];\n\t/**\n\t * Whether the dialog renders modally, preventing outside interaction and hiding background content from screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDialogProps[\"modal\"];\n}\n\nexport const Dialog: React.FC<DialogProps> = DialogPrimitive.Root;\n\nexport interface DialogTriggerProps extends Omit<RadixDialogTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Trigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTriggerProps[\"asChild\"];\n}\n\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\nexport interface DialogCloseProps extends Omit<RadixDialogCloseProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * Close forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogCloseProps[\"asChild\"];\n}\n\nexport const DialogClose = DialogPrimitive.Close;\n\nexport interface DialogPortalProps\n\textends Omit<RadixDialogPortalProps, \"container\" | \"forceMount\"> {\n\t/**\n\t * Target container element where the dialog overlay and content portal should mount.\n\t */\n\tcontainer?: RadixDialogPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogPortalProps[\"forceMount\"];\n}\n\nexport const DialogPortal = DialogPrimitive.Portal;\n\nexport interface DialogOverlayProps\n\textends Omit<RadixDialogOverlayProps, \"asChild\" | \"forceMount\"> {\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Overlay forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogOverlayProps[\"asChild\"];\n\t/**\n\t * Used to force mounting when controlling transition animations externally.\n\t */\n\tforceMount?: RadixDialogOverlayProps[\"forceMount\"];\n}\n\nexport const DialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Overlay>,\n\tDialogOverlayProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nexport interface DialogContentProps\n\textends Omit<\n\t\tRadixDialogContentProps,\n\t\t| \"size\"\n\t\t| \"disablePointerDismissal\"\n\t\t| \"asChild\"\n\t\t| \"forceMount\"\n\t\t| \"trapFocus\"\n\t\t| \"onOpenAutoFocus\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t> {\n\t/**\n\t * Fixed desktop width preset. Dialog panel scrolls vertically when content overflows available viewport height.\n\t * @default \"base\"\n\t */\n\tsize?: DialogSize;\n\t/**\n\t * When true, pointer interactions outside the dialog panel are prevented from dismissing the dialog.\n\t * @default false\n\t */\n\tdisablePointerDismissal?: boolean;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * Content forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogContentProps[\"asChild\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: RadixDialogContentProps[\"forceMount\"];\n\t/**\n\t * Event handler called when auto-focusing the first element on open. Can be prevented with event.preventDefault().\n\t */\n\tonOpenAutoFocus?: RadixDialogContentProps[\"onOpenAutoFocus\"];\n\t/**\n\t * Event handler called when restoring focus on close. Can be prevented with event.preventDefault().\n\t */\n\tonCloseAutoFocus?: RadixDialogContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Event handler called when the Escape key is pressed. Can be prevented with event.preventDefault().\n\t */\n\tonEscapeKeyDown?: RadixDialogContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Event handler called when a pointer event occurs outside the dialog bounds.\n\t */\n\tonPointerDownOutside?: RadixDialogContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Event handler called when focus moves outside the dialog bounds.\n\t */\n\tonFocusOutside?: RadixDialogContentProps[\"onFocusOutside\"];\n\t/**\n\t * Event handler called when any interaction (pointer or focus) occurs outside the dialog bounds.\n\t */\n\tonInteractOutside?: RadixDialogContentProps[\"onInteractOutside\"];\n}\n\nexport const DialogContent = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Content>,\n\tDialogContentProps\n>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tsize = \"base\",\n\t\t\tdisablePointerDismissal = false,\n\t\t\tonPointerDownOutside,\n\t\t\tonInteractOutside,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<DialogPortal forceMount={props.forceMount}>\n\t\t\t<DialogOverlay forceMount={props.forceMount} />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface-root=\"\"\n\t\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t\tonPointerDownOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonPointerDownOutside?.(event);\n\t\t\t\t}}\n\t\t\t\tonInteractOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonInteractOutside?.(event);\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t),\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nexport interface DialogTitleProps extends Omit<RadixDialogTitleProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered heading element to the child element, merging props and behavior.\n\t * Title forwards ref to HTMLHeadingElement and inherits native h2 attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogTitleProps[\"asChild\"];\n}\n\nexport const DialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Title>,\n\tDialogTitleProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"min-w-0 text-basalt-3xl font-semibold tracking-tight wrap-anywhere\", className)}\n\t\t{...props}\n\t/>\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nexport interface DialogDescriptionProps extends Omit<RadixDialogDescriptionProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered paragraph element to the child element, merging props and behavior.\n\t * Description forwards ref to HTMLParagraphElement and inherits native p attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDialogDescriptionProps[\"asChild\"];\n}\n\nexport const DialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Description>,\n\tDialogDescriptionProps\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-basalt-lg text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogHeader = ({ className, ...props }: DialogHeaderProps) => (\n\t<div className={cn(\"flex flex-col space-y-basalt-space-md text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DialogFooter = ({ className, ...props }: DialogFooterProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"mt-basalt-layout flex flex-col-reverse gap-basalt-space-lg sm:flex-row sm:justify-end\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAaE,IAAe;CAC3B,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;AACL;AAIA,SAAgBC,EAAmB,GAAoB;CACtD,OAAOC,EACN,wDACAC,GACA,8FACAC,GACAC,CACD;AACD;AAEA,SAAgBC,EAAiB,EAChC,UAAO,QACP,iBAIG,CAAC,GAAG;CACP,OAAOJ,EACNK,GACA,kQACAJ,GACA,4FACAC,GACAJ,EAAaQ,IACbH,CACD;AACD;AAmCA,IAAaI,IAAgCV,EAAgB,MAWhDW,IAAgBX,EAAgB,SAWhCY,IAAcZ,EAAgB,OAc9Ba,IAAeb,EAAgB,QAgB/Bc,IAAgBf,EAAM,YAGhC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,SAAjB;CAA8B;CAAK,WAAWE,EAAmBI,CAAS;CAAG,GAAIS;AAAQ,CAAA,CACzF;AACD,EAAc,cAAcf,EAAgB,QAAQ;AAkEpD,IAAagB,IAAgBjB,EAAM,YAKjC,EACC,cACA,aACA,UAAO,QACP,6BAA0B,IAC1B,yBACA,sBACA,GAAGgB,KAEJ,MAEA,kBAACF,GAAD;CAAc,YAAYE,EAAM;CAAhC,UAAA,CACC,kBAACD,GAAD,EAAe,YAAYC,EAAM,WAAa,CAAA,GAC9C,kBAACf,EAAgB,SAAjB;EACM;EACL,4BAAyB;EACzB,WAAWO,EAAiB;GAAE;GAAM;EAAU,CAAC;EAC/C,uBAAuB,MAAU;GAIhC,AAHIU,KACHC,EAAM,eAAe,GAEtBC,IAAuBD,CAAK;EAC7B;EACA,oBAAoB,MAAU;GAI7B,AAHID,KACHC,EAAM,eAAe,GAEtBE,IAAoBF,CAAK;EAC1B;EACA,GAAIH;EAEH;CACuB,CAAA,CACZ;AAEhB,CAAA,CAAA;AACA,EAAc,cAAcf,EAAgB,QAAQ;AAWpD,IAAaqB,IAActB,EAAM,YAG9B,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,OAAjB;CACM;CACL,WAAWG,EAAG,sEAAsEG,CAAS;CAC7F,GAAIS;AACJ,CAAA,CACD;AACD,EAAY,cAAcf,EAAgB,MAAM;AAWhD,IAAasB,IAAoBvB,EAAM,YAGpC,EAAE,cAAW,GAAGgB,KAAS,MAC3B,kBAACf,EAAgB,aAAjB;CACM;CACL,WAAWG,EAAG,+CAA+CG,CAAS;CACtE,GAAIS;AACJ,CAAA,CACD;AACD,EAAkB,cAAcf,EAAgB,YAAY;AAI5D,IAAauB,KAAgB,EAAE,cAAW,GAAGR,QAC5C,kBAAC,OAAD;CAAK,WAAWZ,EAAG,mDAAmDG,CAAS;CAAG,GAAIS;AAAQ,CAAA;AAE/F,EAAa,cAAc;AAI3B,IAAaS,KAAgB,EAAE,cAAW,GAAGT,QAC5C,kBAAC,OAAD;CACC,WAAWZ,EACV,yFACAG,CACD;CACA,GAAIS;AACJ,CAAA;AAEF,EAAa,cAAc"}
|
|
@@ -38,6 +38,7 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
38
38
|
children: [/* @__PURE__ */ g(l, { children: /* @__PURE__ */ _(u, { children: [
|
|
39
39
|
/* @__PURE__ */ g(c, {
|
|
40
40
|
scope: "col",
|
|
41
|
+
className: "ps-basalt-table-edge",
|
|
41
42
|
children: "Change"
|
|
42
43
|
}),
|
|
43
44
|
y.map((e) => /* @__PURE__ */ g(c, {
|
|
@@ -47,6 +48,7 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
47
48
|
}, e.id)),
|
|
48
49
|
/* @__PURE__ */ g(c, {
|
|
49
50
|
scope: "col",
|
|
51
|
+
className: "pe-basalt-table-edge",
|
|
50
52
|
children: /* @__PURE__ */ g("span", {
|
|
51
53
|
className: "sr-only",
|
|
52
54
|
children: "Include change"
|
|
@@ -64,16 +66,15 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
64
66
|
},
|
|
65
67
|
children: [
|
|
66
68
|
/* @__PURE__ */ g(s, {
|
|
67
|
-
className: "whitespace-nowrap text-basalt-sm",
|
|
69
|
+
className: "whitespace-nowrap ps-basalt-table-edge text-basalt-sm",
|
|
68
70
|
children: /* @__PURE__ */ _("span", {
|
|
69
71
|
className: "inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]",
|
|
70
|
-
children: [
|
|
72
|
+
children: [/* @__PURE__ */ g("span", {
|
|
73
|
+
"data-diff-marker": "",
|
|
71
74
|
"aria-hidden": "true",
|
|
72
|
-
className: "size-basalt-icon-sm"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
className: "size-basalt-icon-sm"
|
|
76
|
-
}) : null, t.change === "unchanged" ? "Keep" : t.change === "add" ? "Add" : "Remove"]
|
|
75
|
+
className: "inline-flex size-basalt-icon-sm shrink-0 items-center justify-center",
|
|
76
|
+
children: t.change === "add" ? /* @__PURE__ */ g(m, { className: "size-basalt-icon-sm" }) : t.change === "remove" ? /* @__PURE__ */ g(p, { className: "size-basalt-icon-sm" }) : null
|
|
77
|
+
}), t.change === "unchanged" ? "Keep" : t.change === "add" ? "Add" : "Remove"]
|
|
77
78
|
})
|
|
78
79
|
}),
|
|
79
80
|
y.map((n) => /* @__PURE__ */ g(s, {
|
|
@@ -81,16 +82,20 @@ function v({ title: v = "Proposed changes", columns: y, className: b, ...x }) {
|
|
|
81
82
|
style: { minWidth: n.width },
|
|
82
83
|
children: t.values[n.id] ?? "—"
|
|
83
84
|
}, n.id)),
|
|
84
|
-
/* @__PURE__ */ g(s, {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
/* @__PURE__ */ g(s, {
|
|
86
|
+
className: "pe-basalt-table-edge",
|
|
87
|
+
children: t.change !== "unchanged" && /* @__PURE__ */ g(n, {
|
|
88
|
+
disabled: S.blocked,
|
|
89
|
+
checked: r,
|
|
90
|
+
"aria-label": `Include ${t.change === "add" ? "addition" : "removal"} ${t.label}`,
|
|
91
|
+
onCheckedChange: () => S.toggle(t.id)
|
|
92
|
+
})
|
|
93
|
+
})
|
|
90
94
|
]
|
|
91
95
|
}, t.id);
|
|
92
96
|
}), x.rows.length === 0 && /* @__PURE__ */ g(u, { children: /* @__PURE__ */ g(s, {
|
|
93
97
|
colSpan: y.length + 2,
|
|
98
|
+
className: "ps-basalt-table-edge pe-basalt-table-edge",
|
|
94
99
|
children: /* @__PURE__ */ g("p", {
|
|
95
100
|
role: "status",
|
|
96
101
|
className: "text-basalt-muted-foreground",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-table.js","names":["_Fragment","Fragment$1","DiffTable","props","vm","useDiffTableViewModel","id","useId","LayerCard","cn","className","title","Table","TableHeader","TableRow","TableHead","columns","column","TableBody","included","row","event","TableCell","Plus","Minus","Checkbox","Check","Button"],"sources":["../../src/components/diff-table.tsx"],"sourcesContent":["import { Check, Minus, Plus } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\nimport { cn } from \"../utils/cn\";\nimport { useDiffTableViewModel } from \"../viewmodels/use-diff-table\";\nimport { Button } from \"./button\";\nimport { Checkbox } from \"./checkbox\";\nimport { LayerCard } from \"./layer-card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\n\nexport interface DiffTableProps {\n\t/** Stable columns and text/number cells. */\n\tcolumns: readonly DiffTableColumn[];\n\t/** Proposed rows; remount with a new key for a different proposal. */\n\trows: readonly DiffTableRow[];\n\t/** Heading and accessible table name. @default \"Proposed changes\" */\n\ttitle?: string;\n\t/** Explicitly apply only selected changes; rejection keeps the selection for retry. */\n\tonApply: (changes: readonly DiffTableRow[]) => void | Promise<void>;\n\tdisabled?: boolean;\n\tclassName?: string;\n}\n\nexport function DiffTable({\n\ttitle = \"Proposed changes\",\n\tcolumns,\n\tclassName,\n\t...props\n}: DiffTableProps) {\n\tconst vm = useDiffTableViewModel(props);\n\tconst id = useId();\n\treturn (\n\t\t<LayerCard\n\t\t\tpadding=\"none\"\n\t\t\taria-labelledby={id}\n\t\t\tclassName={cn(\"min-w-0 overflow-hidden leading-[var(--basalt-line-body)]\", className)}\n\t\t>\n\t\t\t<header className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t<h3 id={id} className=\"text-basalt-code font-medium\">\n\t\t\t\t\t{title}\n\t\t\t\t</h3>\n\t\t\t\t<span className=\"text-basalt-sm text-basalt-muted-foreground\">Select changes to apply</span>\n\t\t\t</header>\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${title} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow region supports keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"overflow-x-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<Table aria-label={title} aria-busy={vm.status === \"applying\" || undefined}>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t<TableHead scope=\"col\">Change</TableHead>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead key={column.id} scope=\"col\" style={{ minWidth: column.width }}>\n\t\t\t\t\t\t\t\t\t{column.label}\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t<TableHead scope=\"col\">\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Include change</span>\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{props.rows.map((row) => {\n\t\t\t\t\t\t\tconst included = row.change !== \"unchanged\" && !vm.excluded.includes(row.id);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-diff-change={row.change}\n\t\t\t\t\t\t\t\t\tdata-included={included}\n\t\t\t\t\t\t\t\t\taria-selected={row.change !== \"unchanged\" ? included : undefined}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"basalt-agent-reveal\",\n\t\t\t\t\t\t\t\t\t\trow.change !== \"unchanged\" && !vm.blocked && \"cursor-pointer\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\tif (event.target instanceof Element && event.target.closest(\"button, a, input\"))\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\tvm.toggle(row.id);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TableCell className=\"whitespace-nowrap text-basalt-sm\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]\">\n\t\t\t\t\t\t\t\t\t\t\t{row.change === \"add\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<Plus aria-hidden=\"true\" className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t) : row.change === \"remove\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<Minus aria-hidden=\"true\" className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t{row.change === \"unchanged\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"Keep\"\n\t\t\t\t\t\t\t\t\t\t\t\t: row.change === \"add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"Add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"Remove\"}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"whitespace-nowrap\",\n\t\t\t\t\t\t\t\t\t\t\t\tincluded && row.change === \"remove\" && \"line-through\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ minWidth: column.width }}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{row.values[column.id] ?? \"—\"}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t<TableCell>\n\t\t\t\t\t\t\t\t\t\t{row.change !== \"unchanged\" && (\n\t\t\t\t\t\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={vm.blocked}\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={included}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Include ${row.change === \"add\" ? \"addition\" : \"removal\"} ${row.label}`}\n\t\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={() => vm.toggle(row.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{props.rows.length === 0 && (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={columns.length + 2}>\n\t\t\t\t\t\t\t\t\t<p role=\"status\" className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\tNo proposed changes\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TableBody>\n\t\t\t\t</Table>\n\t\t\t</div>\n\t\t\t{vm.error && (\n\t\t\t\t<p\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tclassName=\"px-basalt-panel-x py-basalt-panel-y text-basalt-sm text-basalt-danger\"\n\t\t\t\t>\n\t\t\t\t\t{vm.error}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<footer className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-t border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t{vm.status === \"applied\" ? (\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-basalt-space-md text-basalt-base\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check aria-hidden=\"true\" className=\"size-basalt-icon\" />\n\t\t\t\t\t\t{vm.selected.length} changes applied\n\t\t\t\t\t</p>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"text-basalt-sm tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t{vm.removals} removals · {vm.additions} additions\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tloading={vm.status === \"applying\"}\n\t\t\t\t\t\t\tdisabled={vm.blocked || vm.selected.length === 0}\n\t\t\t\t\t\t\tonClick={() => void vm.apply()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tApply {vm.selected.length} changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</footer>\n\t\t</LayerCard>\n\t);\n}\n"],"mappings":";;;;;;;;;;;AAyBA,SAAgBE,EAAU,EACzB,WAAQ,oBACR,YACA,cACA,GAAGC,KACe;CAClB,IAAMC,IAAKC,EAAsBF,CAAK,GAChCG,IAAKC,EAAM;CACjB,OACC,kBAACC,GAAD;EACC,SAAQ;EACR,mBAAiBF;EACjB,WAAWG,EAAG,6DAA6DC,CAAS;EAHrF,UAAA;GAKC,kBAAC,UAAD;IAAQ,WAAU;IAAlB,UAAA,CACC,kBAAC,MAAD;KAAQ;KAAI,WAAU;KACpB,UAAAC;IACE,CAAA,GACJ,kBAAC,QAAD;KAAM,WAAU;KAA8C,UAAA;IAA6B,CAAA,CACpF;;GACR,kBAAC,OAAD;IACC,MAAK;IACL,cAAY,GAAGA,EAAM;IAErB,UAAU;IACV,WAAU;IAEV,UAAA,kBAACC,GAAD;KAAO,cAAYD;KAAO,aAAWP,EAAG,WAAW,cAAc,KAAA;KAAjE,UAAA,CACC,kBAACS,GAAD,EAAA,UACC,kBAACC,GAAD,EAAA,UAAA;MACC,kBAACC,GAAD;OAAW,OAAM;OAAM,UAAA;MAAiB,CAAA;MACvCC,EAAQ,KAAK,MACb,kBAACD,GAAD;OAA2B,OAAM;OAAM,OAAO,EAAE,UAAUE,EAAO,MAAM;OACrE,UAAAA,EAAO;MACE,GAFKA,EAAO,EAEZ,CACX;MACD,kBAACF,GAAD;OAAW,OAAM;OAChB,UAAA,kBAAC,QAAD;QAAM,WAAU;QAAU,UAAA;OAAoB,CAAA;MACpC,CAAA;KACF,EAAA,CAAA,EACE,CAAA,GACb,kBAACG,GAAD,EAAA,UAAA,CACEf,EAAM,KAAK,KAAK,MAAQ;MACxB,IAAMgB,IAAWC,EAAI,WAAW,eAAe,CAAChB,EAAG,SAAS,SAASgB,EAAI,EAAE;MAC3E,OACC,kBAACN,GAAD;OAEC,oBAAkBM,EAAI;OACtB,iBAAeD;OACf,iBAAeC,EAAI,WAAW,cAAyB,KAAA,IAAXD;OAC5C,WAAWV,EACV,uBACAW,EAAI,WAAW,eAAe,CAAChB,EAAG,WAAW,gBAC9C;OACA,UAAU,MAAU;QACnB,AAAIiB,EAAM,kBAAkB,WAAWA,EAAM,OAAO,QAAQ,kBAAkB,KAE9EjB,EAAG,OAAOgB,EAAI,EAAE;OACjB;OAbD,UAAA;QAeC,kBAACE,GAAD;SAAW,WAAU;SACpB,UAAA,kBAAC,QAAD;UAAM,WAAU;UAAhB,UAAA,CACEF,EAAI,WAAW,QACf,kBAACG,GAAD;WAAM,eAAY;WAAO,WAAU;UAAuB,CAAA,IACvDH,EAAI,WAAW,WAClB,kBAACI,GAAD;WAAO,eAAY;WAAO,WAAU;UAAuB,CAAA,IACxD,MACHJ,EAAI,WAAW,cACb,SACAA,EAAI,WAAW,QACd,QACA,QACC;;QACI,CAAA;QACVJ,EAAQ,KAAK,MACb,kBAACM,GAAD;SAEC,WAAWb,EACV,qBACAU,KAAYC,EAAI,WAAW,YAAY,cACxC;SACA,OAAO,EAAE,UAAUH,EAAO,MAAM;SAE/B,UAAAG,EAAI,OAAOH,EAAO,OAAO;QAChB,GARLA,EAAO,EAQF,CACX;QACD,kBAACK,GAAD,EAAA,UACEF,EAAI,WAAW,eACf,kBAACK,GAAD;SACC,UAAUrB,EAAG;SACb,SAASe;SACT,cAAY,WAAWC,EAAI,WAAW,QAAQ,aAAa,UAAU,GAAGA,EAAI;SAC5E,uBAAuBhB,EAAG,OAAOgB,EAAI,EAAE;QACvC,CAAA,EAEQ,CAAA;OACF;MAlDJ,GAAAA,EAAI,EAkDA;KAEZ,CAAC,GACAjB,EAAM,KAAK,WAAW,KACtB,kBAACW,GAAD,EAAA,UACC,kBAACQ,GAAD;MAAW,SAASN,EAAQ,SAAS;MACpC,UAAA,kBAAC,KAAD;OAAG,MAAK;OAAS,WAAU;OAA+B,UAAA;MAEvD,CAAA;KACO,CAAA,EACF,CAAA,CAED,EAAA,CAAA,CACL;;GACH,CAAA;GACJZ,EAAG,SACH,kBAAC,KAAD;IACC,MAAK;IACL,WAAU;IAET,UAAAA,EAAG;GACF,CAAA;GAEJ,kBAAC,UAAD;IAAQ,WAAU;IAChB,UAAAA,EAAG,WAAW,YACd,kBAAC,KAAD;KACC,MAAK;KACL,WAAU;KAFX,UAAA;MAIC,kBAACsB,GAAD;OAAO,eAAY;OAAO,WAAU;MAAoB,CAAA;MACvDtB,EAAG,SAAS;MAAO;KAClB;IAEH,CAAA,IAAA,kBAAAJ,GAAA,EAAA,UAAA,CACC,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACEI,EAAG;MAAS;MAAaA,EAAG;MAAU;KAClC;IACN,CAAA,GAAA,kBAACuB,GAAD;KACC,MAAK;KACL,SAASvB,EAAG,WAAW;KACvB,UAAUA,EAAG,WAAWA,EAAG,SAAS,WAAW;KAC/C,eAAe,KAAKA,EAAG,MAAM;KAJ9B,UAAA;MAKC;MACOA,EAAG,SAAS;MAAO;KACnB;IACP,CAAA,CAAA,EAAA,CAAA;GAEI,CAAA;EACE;;AAEb"}
|
|
1
|
+
{"version":3,"file":"diff-table.js","names":["_Fragment","Fragment$1","DiffTable","props","vm","useDiffTableViewModel","id","useId","LayerCard","cn","className","title","Table","TableHeader","TableRow","TableHead","columns","column","TableBody","included","row","event","TableCell","Plus","Minus","Checkbox","Check","Button"],"sources":["../../src/components/diff-table.tsx"],"sourcesContent":["import { Check, Minus, Plus } from \"lucide-react\";\nimport { useId } from \"react\";\nimport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\nimport { cn } from \"../utils/cn\";\nimport { useDiffTableViewModel } from \"../viewmodels/use-diff-table\";\nimport { Button } from \"./button\";\nimport { Checkbox } from \"./checkbox\";\nimport { LayerCard } from \"./layer-card\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type { DiffTableColumn, DiffTableRow } from \"../models/diff-table\";\n\nexport interface DiffTableProps {\n\t/** Stable columns and text/number cells. */\n\tcolumns: readonly DiffTableColumn[];\n\t/** Proposed rows; remount with a new key for a different proposal. */\n\trows: readonly DiffTableRow[];\n\t/** Heading and accessible table name. @default \"Proposed changes\" */\n\ttitle?: string;\n\t/** Explicitly apply only selected changes; rejection keeps the selection for retry. */\n\tonApply: (changes: readonly DiffTableRow[]) => void | Promise<void>;\n\tdisabled?: boolean;\n\tclassName?: string;\n}\n\nexport function DiffTable({\n\ttitle = \"Proposed changes\",\n\tcolumns,\n\tclassName,\n\t...props\n}: DiffTableProps) {\n\tconst vm = useDiffTableViewModel(props);\n\tconst id = useId();\n\treturn (\n\t\t<LayerCard\n\t\t\tpadding=\"none\"\n\t\t\taria-labelledby={id}\n\t\t\tclassName={cn(\"min-w-0 overflow-hidden leading-[var(--basalt-line-body)]\", className)}\n\t\t>\n\t\t\t<header className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-b border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t<h3 id={id} className=\"text-basalt-code font-medium\">\n\t\t\t\t\t{title}\n\t\t\t\t</h3>\n\t\t\t\t<span className=\"text-basalt-sm text-basalt-muted-foreground\">Select changes to apply</span>\n\t\t\t</header>\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${title} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow region supports keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"overflow-x-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-basalt-ring\"\n\t\t\t>\n\t\t\t\t<Table aria-label={title} aria-busy={vm.status === \"applying\" || undefined}>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"ps-basalt-table-edge\">\n\t\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead key={column.id} scope=\"col\" style={{ minWidth: column.width }}>\n\t\t\t\t\t\t\t\t\t{column.label}\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t<TableHead scope=\"col\" className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Include change</span>\n\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{props.rows.map((row) => {\n\t\t\t\t\t\t\tconst included = row.change !== \"unchanged\" && !vm.excluded.includes(row.id);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-diff-change={row.change}\n\t\t\t\t\t\t\t\t\tdata-included={included}\n\t\t\t\t\t\t\t\t\taria-selected={row.change !== \"unchanged\" ? included : undefined}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"basalt-agent-reveal\",\n\t\t\t\t\t\t\t\t\t\trow.change !== \"unchanged\" && !vm.blocked && \"cursor-pointer\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\tif (event.target instanceof Element && event.target.closest(\"button, a, input\"))\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\tvm.toggle(row.id);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TableCell className=\"whitespace-nowrap ps-basalt-table-edge text-basalt-sm\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-basalt-control-gap leading-[var(--basalt-line-body)]\">\n\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\tdata-diff-marker=\"\"\n\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"inline-flex size-basalt-icon-sm shrink-0 items-center justify-center\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{row.change === \"add\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Plus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : row.change === \"remove\" ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Minus className=\"size-basalt-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t{row.change === \"unchanged\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"Keep\"\n\t\t\t\t\t\t\t\t\t\t\t\t: row.change === \"add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"Add\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"Remove\"}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"whitespace-nowrap\",\n\t\t\t\t\t\t\t\t\t\t\t\tincluded && row.change === \"remove\" && \"line-through\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ minWidth: column.width }}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{row.values[column.id] ?? \"—\"}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t<TableCell className=\"pe-basalt-table-edge\">\n\t\t\t\t\t\t\t\t\t\t{row.change !== \"unchanged\" && (\n\t\t\t\t\t\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={vm.blocked}\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={included}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Include ${row.change === \"add\" ? \"addition\" : \"removal\"} ${row.label}`}\n\t\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={() => vm.toggle(row.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{props.rows.length === 0 && (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\tcolSpan={columns.length + 2}\n\t\t\t\t\t\t\t\t\tclassName=\"ps-basalt-table-edge pe-basalt-table-edge\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<p role=\"status\" className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\tNo proposed changes\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TableBody>\n\t\t\t\t</Table>\n\t\t\t</div>\n\t\t\t{vm.error && (\n\t\t\t\t<p\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tclassName=\"px-basalt-panel-x py-basalt-panel-y text-basalt-sm text-basalt-danger\"\n\t\t\t\t>\n\t\t\t\t\t{vm.error}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<footer className=\"flex flex-wrap items-center justify-between gap-basalt-content-gap border-t border-basalt-border px-basalt-panel-x py-basalt-panel-y\">\n\t\t\t\t{vm.status === \"applied\" ? (\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-basalt-space-md text-basalt-base\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check aria-hidden=\"true\" className=\"size-basalt-icon\" />\n\t\t\t\t\t\t{vm.selected.length} changes applied\n\t\t\t\t\t</p>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<span className=\"text-basalt-sm tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t{vm.removals} removals · {vm.additions} additions\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tloading={vm.status === \"applying\"}\n\t\t\t\t\t\t\tdisabled={vm.blocked || vm.selected.length === 0}\n\t\t\t\t\t\t\tonClick={() => void vm.apply()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tApply {vm.selected.length} changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</footer>\n\t\t</LayerCard>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -140,17 +140,18 @@ function M({ collapsed: n, className: c, children: l, onMouseEnter: u, onMouseLe
|
|
|
140
140
|
children: [x, S]
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
var N = "min-h-[calc(var(--basalt-line-row)+2*var(--basalt-space-lg))] py-basalt-space-lg";
|
|
144
|
+
function P({ className: t, ...n }) {
|
|
144
145
|
return /* @__PURE__ */ w("div", {
|
|
145
146
|
"data-slot": "sidebar-header",
|
|
146
147
|
className: e("flex h-basalt-14 shrink-0 items-center gap-basalt-row-gap px-basalt-nav-inset", t),
|
|
147
148
|
...n
|
|
148
149
|
});
|
|
149
150
|
}
|
|
150
|
-
function
|
|
151
|
+
function F({ shortcut: n = "⌘K", className: r, children: i, ...a }) {
|
|
151
152
|
return /* @__PURE__ */ T("button", {
|
|
152
153
|
type: "button",
|
|
153
|
-
className: e(t, h, "w-full cursor-pointer bg-basalt-secondary transition-colors basalt-motion hover:bg-basalt-hover", r),
|
|
154
|
+
className: e(t, h, N, "w-full cursor-pointer bg-basalt-secondary transition-colors basalt-motion hover:bg-basalt-hover", r),
|
|
154
155
|
...a,
|
|
155
156
|
children: [
|
|
156
157
|
/* @__PURE__ */ w(C, {
|
|
@@ -168,7 +169,7 @@ function P({ shortcut: n = "⌘K", className: r, children: i, ...a }) {
|
|
|
168
169
|
]
|
|
169
170
|
});
|
|
170
171
|
}
|
|
171
|
-
function
|
|
172
|
+
function I({ className: t, ...n }) {
|
|
172
173
|
let r = d(void 0, { restoreOnPointerLeave: !1 });
|
|
173
174
|
return /* @__PURE__ */ w("nav", {
|
|
174
175
|
ref: r,
|
|
@@ -177,34 +178,36 @@ function F({ className: t, ...n }) {
|
|
|
177
178
|
...n
|
|
178
179
|
});
|
|
179
180
|
}
|
|
180
|
-
function
|
|
181
|
+
function L({ className: t, ...n }) {
|
|
181
182
|
return /* @__PURE__ */ w("p", {
|
|
182
183
|
"data-slot": "sidebar-partition",
|
|
183
184
|
className: e("shrink-0 px-basalt-row-x pt-basalt-layout pb-basalt-space-lg text-basalt-sm font-semibold tracking-wide text-basalt-foreground uppercase", t),
|
|
184
185
|
...n
|
|
185
186
|
});
|
|
186
187
|
}
|
|
187
|
-
function
|
|
188
|
+
function R({ active: t = !1, className: n, ...r }) {
|
|
188
189
|
return /* @__PURE__ */ w("button", {
|
|
189
190
|
type: "button",
|
|
190
191
|
"aria-current": t ? "page" : void 0,
|
|
191
192
|
"data-basalt-hover-item": "",
|
|
193
|
+
"data-sidebar-row": "",
|
|
192
194
|
"data-hover-selected": t,
|
|
193
|
-
className: e(p, "w-full", n),
|
|
195
|
+
className: e(p, N, "w-full", n),
|
|
194
196
|
...r
|
|
195
197
|
});
|
|
196
198
|
}
|
|
197
|
-
function
|
|
199
|
+
function z({ active: t = !1, className: n, ...r }) {
|
|
198
200
|
return /* @__PURE__ */ w("button", {
|
|
199
201
|
type: "button",
|
|
200
202
|
"aria-current": t ? "page" : void 0,
|
|
201
203
|
"data-basalt-hover-item": "",
|
|
204
|
+
"data-sidebar-row": "",
|
|
202
205
|
"data-hover-selected": t,
|
|
203
|
-
className: e(p, "relative
|
|
206
|
+
className: e(p, N, "relative w-basalt-control justify-center", n),
|
|
204
207
|
...r
|
|
205
208
|
});
|
|
206
209
|
}
|
|
207
|
-
function
|
|
210
|
+
function B({ label: t, defaultOpen: r = !0, children: a }) {
|
|
208
211
|
let [o, s] = x(r);
|
|
209
212
|
return /* @__PURE__ */ T(c, {
|
|
210
213
|
open: o,
|
|
@@ -216,7 +219,7 @@ function z({ label: t, defaultOpen: r = !0, children: a }) {
|
|
|
216
219
|
children: /* @__PURE__ */ T("button", {
|
|
217
220
|
type: "button",
|
|
218
221
|
"data-slot": "sidebar-group-label",
|
|
219
|
-
className: e("flex w-full cursor-pointer items-center justify-between gap-basalt-row-gap rounded-basalt-md px-basalt-row-x py-basalt-space-lg text-left text-basalt-xs font-semibold leading-
|
|
222
|
+
className: e("flex w-full cursor-pointer items-center justify-between gap-basalt-row-gap rounded-basalt-md px-basalt-row-x py-basalt-space-lg text-left text-basalt-xs font-semibold leading-basalt-row tracking-wide text-basalt-muted-foreground uppercase transition-colors basalt-motion hover:text-basalt-foreground", n),
|
|
220
223
|
children: [/* @__PURE__ */ w("span", {
|
|
221
224
|
className: "min-w-0 truncate",
|
|
222
225
|
children: t
|
|
@@ -234,14 +237,14 @@ function z({ label: t, defaultOpen: r = !0, children: a }) {
|
|
|
234
237
|
})]
|
|
235
238
|
});
|
|
236
239
|
}
|
|
237
|
-
function
|
|
240
|
+
function V({ className: t, ...n }) {
|
|
238
241
|
return /* @__PURE__ */ w("div", {
|
|
239
242
|
"data-slot": "sidebar-footer",
|
|
240
243
|
className: e("flex shrink-0 flex-col gap-basalt-content-gap px-basalt-nav-inset py-basalt-nav-inset", t),
|
|
241
244
|
...n
|
|
242
245
|
});
|
|
243
246
|
}
|
|
244
|
-
function
|
|
247
|
+
function H({ name: t, email: n, avatar: r, action: i, className: a }) {
|
|
245
248
|
return /* @__PURE__ */ T("div", {
|
|
246
249
|
className: e("flex items-center gap-basalt-space-lg", a),
|
|
247
250
|
children: [
|
|
@@ -260,7 +263,7 @@ function V({ name: t, email: n, avatar: r, action: i, className: a }) {
|
|
|
260
263
|
]
|
|
261
264
|
});
|
|
262
265
|
}
|
|
263
|
-
function
|
|
266
|
+
function U({ mobileSurface: t = "inset", className: n, ...r }) {
|
|
264
267
|
return /* @__PURE__ */ w("div", {
|
|
265
268
|
"data-basalt-surface-root": "",
|
|
266
269
|
"data-basalt-island": t,
|
|
@@ -269,6 +272,6 @@ function H({ mobileSurface: t = "inset", className: n, ...r }) {
|
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
//#endregion
|
|
272
|
-
export {
|
|
275
|
+
export { U as ContentIsland, M as Sidebar, V as SidebarFooter, B as SidebarGroup, P as SidebarHeader, z as SidebarIconItem, R as SidebarItem, I as SidebarNav, L as SidebarPartition, k as SidebarProvider, F as SidebarSearch, H as SidebarUser, O as useSidebar };
|
|
273
276
|
|
|
274
277
|
//# sourceMappingURL=sidebar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.js","names":["DialogPrimitive","SidebarContext","createContext","useSidebar","context","useContext","SidebarProvider","uncontrolled","setUncontrolled","useState","defaultCollapsed","peeking","setPeeking","width","setWidthState","clampSidebarWidth","defaultWidth","setWidth","useCallback","next","lastFocusRef","useRef","prevCollapsed","collapsed","prevOverlay","overlay","resolved","setCollapsed","onCollapsedChange","SidebarResize","cn","side","event","startX","startWidth","target","onMove","delta","move","onUp","dir","Sidebar","collapsedProp","props","body","SkeletonLine","children","resize","frameClass","BASALT_UI_CLASS","OVERLAY_MOTION","className","Dialog","open","DialogPortal","DialogOverlay","node","from","OVERLAY_LAYER","style","onMouseEnter","onMouseLeave","SidebarHeader","SidebarSearch","NAV_ROW_CLASS","Search","shortcut","SidebarNav","highlightRef","useHoverHighlight","NAV_LIST_CLASS","SidebarPartition","SidebarItem","active","NAV_ITEM_CLASS","SidebarIconItem","SidebarGroup","setOpen","defaultOpen","Collapsible","CollapsibleTrigger","FOCUS_INSET","label","ChevronUp","CollapsibleContent","SidebarFooter","SidebarUser","avatar","name","email","action","ContentIsland","mobileSurface"],"sources":["../../src/components/sidebar.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { ChevronUp, Search } from \"lucide-react\";\nimport {\n\ttype ButtonHTMLAttributes,\n\tcreateContext,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseContext,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { NAV_ITEM_CLASS, NAV_LIST_CLASS, NAV_ROW_CLASS } from \"../utils/navigation\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"./collapsible\";\nimport { Dialog, DialogOverlay, DialogPortal } from \"./dialog\";\nimport { FOCUS_INSET, OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nexport type SidebarSide = \"left\" | \"right\";\n\nexport interface SidebarContextValue {\n\t/**\n\t * Whether the sidebar is currently collapsed.\n\t */\n\tcollapsed: boolean;\n\t/**\n\t * Callback to update the collapsed state.\n\t */\n\tsetCollapsed: (next: boolean) => void;\n\t/**\n\t * Which edge the sidebar occupies.\n\t */\n\tside: SidebarSide;\n\t/**\n\t * Whether the sidebar is currently displaying a loading skeleton.\n\t */\n\tloading: boolean;\n\t/**\n\t * Whether the sidebar rail expands on pointer hover.\n\t */\n\tpeek: boolean;\n\t/**\n\t * Whether the sidebar is actively hovering in peek preview mode.\n\t */\n\tpeeking: boolean;\n\t/**\n\t * Callback to update the peek preview state.\n\t */\n\tsetPeeking: (next: boolean) => void;\n\t/**\n\t * Whether the sidebar is rendering as a modal overlay drawer instead of in-flow layout chrome.\n\t */\n\toverlay: boolean;\n\t/**\n\t * Current expanded width in pixels, clamped between 180 and 400.\n\t */\n\twidth: number;\n\t/**\n\t * Callback to update the sidebar width. Value is clamped between 180 and 400 pixels.\n\t */\n\tsetWidth: (next: number) => void;\n\t/**\n\t * Reference to the last active element that held focus before opening the sidebar drawer.\n\t */\n\tlastFocusRef: RefObject<HTMLElement | null>;\n}\n\nconst SidebarContext = createContext<SidebarContextValue | null>(null);\n\n/**\n * Accesses the sidebar context value. Must be used within a `SidebarProvider`; throws an error if called outside.\n * Returns the active sidebar state and control callbacks.\n */\nexport function useSidebar(): SidebarContextValue {\n\tconst context = useContext(SidebarContext);\n\tif (!context) {\n\t\tthrow new Error(\"useSidebar must be used within SidebarProvider\");\n\t}\n\treturn context;\n}\n\nexport type SidebarProviderProps = {\n\t/**\n\t * The controlled collapsed state.\n\t */\n\tcollapsed?: boolean;\n\t/**\n\t * The uncontrolled initial collapsed state.\n\t * @default false\n\t */\n\tdefaultCollapsed?: boolean;\n\t/**\n\t * Called when the collapsed state changes.\n\t */\n\tonCollapsedChange?: (collapsed: boolean) => void;\n\t/**\n\t * Which edge the sidebar occupies.\n\t * @default left\n\t */\n\tside?: SidebarSide;\n\t/**\n\t * Replace the nav with a loading skeleton.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Expand the collapsed rail on hover.\n\t * @default false\n\t */\n\tpeek?: boolean;\n\t/**\n\t * Render as an overlay instead of in-flow chrome.\n\t * @default false\n\t */\n\toverlay?: boolean;\n\t/**\n\t * Initial expanded width in pixels, clamped between 180 and 400.\n\t * @default 260\n\t */\n\tdefaultWidth?: number;\n\t/**\n\t * Sidebar chrome and page content.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function SidebarProvider({\n\tcollapsed,\n\tdefaultCollapsed = false,\n\tonCollapsedChange,\n\tside = \"left\",\n\tloading = false,\n\tpeek = false,\n\toverlay = false,\n\tdefaultWidth = 260,\n\tchildren,\n}: SidebarProviderProps) {\n\tconst [uncontrolled, setUncontrolled] = useState(defaultCollapsed);\n\tconst [peeking, setPeeking] = useState(false);\n\tconst [width, setWidthState] = useState(() => clampSidebarWidth(defaultWidth));\n\tconst setWidth = useCallback((next: number) => {\n\t\tsetWidthState(clampSidebarWidth(next));\n\t}, []);\n\tconst lastFocusRef = useRef<HTMLElement | null>(null);\n\tconst prevCollapsed = useRef(collapsed ?? defaultCollapsed);\n\tconst prevOverlay = useRef(overlay);\n\tconst resolved = collapsed ?? uncontrolled;\n\tuseLayoutEffect(() => {\n\t\tif (\n\t\t\toverlay &&\n\t\t\t!resolved &&\n\t\t\t(prevCollapsed.current || !prevOverlay.current) &&\n\t\t\tdocument.activeElement instanceof HTMLElement\n\t\t) {\n\t\t\tlastFocusRef.current = document.activeElement;\n\t\t}\n\t\tprevCollapsed.current = resolved;\n\t\tprevOverlay.current = overlay;\n\t});\n\tconst setCollapsed = useCallback(\n\t\t(next: boolean) => {\n\t\t\tif (!next && document.activeElement instanceof HTMLElement) {\n\t\t\t\tlastFocusRef.current = document.activeElement;\n\t\t\t}\n\t\t\tif (collapsed === undefined) {\n\t\t\t\tsetUncontrolled(next);\n\t\t\t}\n\t\t\tonCollapsedChange?.(next);\n\t\t},\n\t\t[collapsed, onCollapsedChange],\n\t);\n\treturn (\n\t\t<SidebarContext.Provider\n\t\t\tvalue={{\n\t\t\t\tcollapsed: resolved,\n\t\t\t\tsetCollapsed,\n\t\t\t\tside,\n\t\t\t\tloading,\n\t\t\t\tpeek,\n\t\t\t\tpeeking,\n\t\t\t\tsetPeeking,\n\t\t\t\toverlay,\n\t\t\t\twidth,\n\t\t\t\tsetWidth,\n\t\t\t\tlastFocusRef,\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</SidebarContext.Provider>\n\t);\n}\n\nexport type SidebarProps = HTMLAttributes<HTMLElement> & {\n\t/**\n\t * Collapse the rail when no provider is present.\n\t * @default false\n\t */\n\tcollapsed?: boolean;\n};\n\nfunction clampSidebarWidth(next: number) {\n\treturn Math.min(400, Math.max(180, next));\n}\n\nfunction SidebarResize({\n\tside,\n\twidth,\n\tonWidth,\n}: {\n\tside: SidebarSide;\n\twidth: number;\n\tonWidth: (next: number) => void;\n}) {\n\tconst onPointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n\t\tevent.preventDefault();\n\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\tconst startX = event.clientX;\n\t\tconst startWidth = width;\n\t\tconst target = event.currentTarget;\n\t\tconst onMove = (move: PointerEvent) => {\n\t\t\tconst delta = side === \"right\" ? startX - move.clientX : move.clientX - startX;\n\t\t\tonWidth(clampSidebarWidth(startWidth + delta));\n\t\t};\n\t\tconst onUp = () => {\n\t\t\ttarget.removeEventListener(\"pointermove\", onMove);\n\t\t\ttarget.removeEventListener(\"pointerup\", onUp);\n\t\t\ttarget.removeEventListener(\"pointercancel\", onUp);\n\t\t};\n\t\ttarget.addEventListener(\"pointermove\", onMove);\n\t\ttarget.addEventListener(\"pointerup\", onUp);\n\t\ttarget.addEventListener(\"pointercancel\", onUp);\n\t};\n\treturn (\n\t\t<div\n\t\t\trole=\"separator\"\n\t\t\taria-orientation=\"vertical\"\n\t\t\taria-valuenow={width}\n\t\t\taria-valuemin={180}\n\t\t\taria-valuemax={400}\n\t\t\taria-label=\"Resize sidebar\"\n\t\t\ttabIndex={0}\n\t\t\tclassName={cn(\n\t\t\t\t\"absolute top-0 h-full w-basalt-1 cursor-col-resize bg-transparent\",\n\t\t\t\tside === \"right\" ? \"left-0\" : \"right-0\",\n\t\t\t)}\n\t\t\tonPointerDown={onPointerDown}\n\t\t\tonKeyDown={(event) => {\n\t\t\t\tif (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tconst dir = event.key === \"ArrowRight\" ? 1 : -1;\n\t\t\t\tconst delta = side === \"right\" ? -dir * 8 : dir * 8;\n\t\t\t\tonWidth(clampSidebarWidth(width + delta));\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nexport function Sidebar({\n\tcollapsed: collapsedProp,\n\tclassName,\n\tchildren,\n\tonMouseEnter,\n\tonMouseLeave,\n\tstyle,\n\t...props\n}: SidebarProps) {\n\tconst context = useContext(SidebarContext);\n\tconst collapsed = context\n\t\t? context.collapsed && !(context.peek && context.peeking)\n\t\t: (collapsedProp ?? false);\n\tconst side = context?.side ?? \"left\";\n\tconst overlay = context?.overlay ?? false;\n\tconst width = context?.width ?? 260;\n\tconst body = context?.loading ? (\n\t\t<div\n\t\t\tclassName=\"flex flex-col gap-basalt-space-lg p-basalt-space-lg\"\n\t\t\trole=\"status\"\n\t\t\taria-live=\"polite\"\n\t\t>\n\t\t\t<SkeletonLine />\n\t\t\t<SkeletonLine />\n\t\t\t<SkeletonLine />\n\t\t</div>\n\t) : (\n\t\tchildren\n\t);\n\tconst resize =\n\t\tcontext && !collapsed ? (\n\t\t\t<SidebarResize side={side} width={context.width} onWidth={context.setWidth} />\n\t\t) : null;\n\tconst frameClass = cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"relative flex shrink-0 flex-col bg-basalt-background text-basalt-base text-basalt-foreground\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n\tif (overlay && context) {\n\t\treturn (\n\t\t\t<Dialog open={!context.collapsed} onOpenChange={(open) => context.setCollapsed(!open)}>\n\t\t\t\t<DialogPortal>\n\t\t\t\t\t<DialogOverlay />\n\t\t\t\t\t<DialogPrimitive.Content\n\t\t\t\t\t\tdata-basalt-sidebar=\"\"\n\t\t\t\t\t\taria-label=\"Sidebar\"\n\t\t\t\t\t\tdata-overlay=\"\"\n\t\t\t\t\t\tdata-side={side}\n\t\t\t\t\t\taria-busy={context.loading || undefined}\n\t\t\t\t\t\tonMouseEnter={onMouseEnter}\n\t\t\t\t\t\tonMouseLeave={onMouseLeave}\n\t\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tnode &&\n\t\t\t\t\t\t\t\tdocument.activeElement instanceof HTMLElement &&\n\t\t\t\t\t\t\t\t!node.contains(document.activeElement)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcontext.lastFocusRef.current = document.activeElement;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonOpenAutoFocus={(event) => {\n\t\t\t\t\t\t\tconst from = \"relatedTarget\" in event ? event.relatedTarget : null;\n\t\t\t\t\t\t\tif (from instanceof HTMLElement) {\n\t\t\t\t\t\t\t\tcontext.lastFocusRef.current = from;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonCloseAutoFocus={(event) => {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tcontext.lastFocusRef.current?.focus();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tframeClass,\n\t\t\t\t\t\t\tOVERLAY_LAYER,\n\t\t\t\t\t\t\t\"fixed inset-y-0 overflow-hidden shadow-md\",\n\t\t\t\t\t\t\tside === \"right\" ? \"right-0\" : \"left-0\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ width, ...style }}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t>\n\t\t\t\t\t\t{body}\n\t\t\t\t\t\t{resize}\n\t\t\t\t\t</DialogPrimitive.Content>\n\t\t\t\t</DialogPortal>\n\t\t\t</Dialog>\n\t\t);\n\t}\n\treturn (\n\t\t<aside\n\t\t\tdata-basalt-sidebar=\"\"\n\t\t\tdata-collapsed={collapsed ? \"\" : undefined}\n\t\t\tdata-side={side}\n\t\t\taria-busy={context?.loading || undefined}\n\t\t\tonMouseEnter={(event) => {\n\t\t\t\tif (context?.peek && context.collapsed) {\n\t\t\t\t\tcontext.setPeeking(true);\n\t\t\t\t}\n\t\t\t\tonMouseEnter?.(event);\n\t\t\t}}\n\t\t\tonMouseLeave={(event) => {\n\t\t\t\tif (context?.peek) {\n\t\t\t\t\tcontext.setPeeking(false);\n\t\t\t\t}\n\t\t\t\tonMouseLeave?.(event);\n\t\t\t}}\n\t\t\tclassName={cn(\n\t\t\t\tframeClass,\n\t\t\t\t\"sticky overflow-hidden transition-[width] basalt-motion duration-basalt-normal ease-basalt\",\n\t\t\t\tside === \"right\" ? \"order-last\" : undefined,\n\t\t\t\tcollapsed && \"w-basalt-rail\",\n\t\t\t)}\n\t\t\tstyle={!collapsed ? { width, ...style } : style}\n\t\t\t{...props}\n\t\t>\n\t\t\t{body}\n\t\t\t{resize}\n\t\t</aside>\n\t);\n}\n\nexport interface SidebarHeaderProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport function SidebarHeader({ className, ...props }: SidebarHeaderProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-header\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex h-basalt-14 shrink-0 items-center gap-basalt-row-gap px-basalt-nav-inset\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarSearch`. Renders a native `<button>` element and accepts all standard button HTML attributes and click handlers.\n */\nexport interface SidebarSearchProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n\t/**\n\t * Shortcut key display label rendered inside the trailing kbd tag. Note: this is a visual label only and does not register a global keyboard shortcut.\n\t * @default \"⌘K\"\n\t */\n\tshortcut?: string;\n}\n\nexport function SidebarSearch({\n\tshortcut = \"⌘K\",\n\tclassName,\n\tchildren,\n\t...props\n}: SidebarSearchProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\tNAV_ROW_CLASS,\n\t\t\t\t\"w-full cursor-pointer bg-basalt-secondary transition-colors basalt-motion hover:bg-basalt-hover\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<Search className=\"h-basalt-4 w-basalt-4 text-basalt-muted-foreground\" strokeWidth={1.5} />\n\t\t\t<span className=\"flex-1 text-left text-basalt-base text-basalt-muted-foreground\">\n\t\t\t\t{children}\n\t\t\t</span>\n\t\t\t<kbd className=\"pointer-events-none hidden rounded-basalt-sm border border-basalt-border bg-basalt-card px-basalt-space-md py-basalt-space-xs text-basalt-xs font-medium text-basalt-muted-foreground sm:inline-block\">\n\t\t\t\t{shortcut}\n\t\t\t</kbd>\n\t\t</button>\n\t);\n}\n\nexport interface SidebarNavProps extends HTMLAttributes<HTMLElement> {}\n\nexport function SidebarNav({ className, ...props }: SidebarNavProps) {\n\tconst highlightRef = useHoverHighlight(undefined, { restoreOnPointerLeave: false });\n\treturn (\n\t\t<nav\n\t\t\tref={highlightRef}\n\t\t\tdata-slot=\"sidebar-nav\"\n\t\t\tclassName={cn(\n\t\t\t\tNAV_LIST_CLASS,\n\t\t\t\t\"min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface SidebarPartitionProps extends HTMLAttributes<HTMLParagraphElement> {}\n\nexport function SidebarPartition({ className, ...props }: SidebarPartitionProps) {\n\treturn (\n\t\t<p\n\t\t\tdata-slot=\"sidebar-partition\"\n\t\t\tclassName={cn(\n\t\t\t\t\"shrink-0 px-basalt-row-x pt-basalt-layout pb-basalt-space-lg text-basalt-sm font-semibold tracking-wide text-basalt-foreground uppercase\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type SidebarItemProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n\t/**\n\t * Mark the item as the current page.\n\t * @default false\n\t */\n\tactive?: boolean;\n};\n\nexport function SidebarItem({ active = false, className, ...props }: SidebarItemProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\tdata-basalt-hover-item=\"\"\n\t\t\tdata-hover-selected={active}\n\t\t\tclassName={cn(NAV_ITEM_CLASS, \"w-full\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarIconItem`. Accepts standard button HTML attributes. The caller is responsible for providing accessible labeling via `aria-label` or `aria-labelledby` as icon buttons do not automatically generate accessible names.\n */\nexport interface SidebarIconItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n\t/**\n\t * Mark the icon button as active page item.\n\t * @default false\n\t */\n\tactive?: boolean;\n}\n\nexport function SidebarIconItem({ active = false, className, ...props }: SidebarIconItemProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\tdata-basalt-hover-item=\"\"\n\t\t\tdata-hover-selected={active}\n\t\t\tclassName={cn(\n\t\t\t\tNAV_ITEM_CLASS,\n\t\t\t\t\"relative min-h-basalt-control w-basalt-control justify-center\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarGroup`. Uncontrolled collapsible section that accepts only the documented properties. It does not accept controlled open props or arbitrary DOM attributes.\n */\nexport interface SidebarGroupProps {\n\t/**\n\t * Section label displayed on the group trigger.\n\t */\n\tlabel: ReactNode;\n\t/**\n\t * Uncontrolled initial open state for the collapsible group.\n\t * @default true\n\t */\n\tdefaultOpen?: boolean;\n\t/**\n\t * Navigation items rendered inside the group.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function SidebarGroup({ label, defaultOpen = true, children }: SidebarGroupProps) {\n\tconst [open, setOpen] = useState(defaultOpen);\n\treturn (\n\t\t<Collapsible\n\t\t\topen={open}\n\t\t\tonOpenChange={setOpen}\n\t\t\tdata-slot=\"sidebar-group\"\n\t\t\tclassName=\"shrink-0 pt-basalt-layout-sm\"\n\t\t>\n\t\t\t<CollapsibleTrigger asChild>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-slot=\"sidebar-group-label\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex w-full cursor-pointer items-center justify-between gap-basalt-row-gap rounded-basalt-md px-basalt-row-x py-basalt-space-lg text-left text-basalt-xs font-semibold leading-[calc(var(--basalt-size-control)-2*var(--basalt-space-lg))] tracking-wide text-basalt-muted-foreground uppercase transition-colors basalt-motion hover:text-basalt-foreground\",\n\t\t\t\t\t\tFOCUS_INSET,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"min-w-0 truncate\">{label}</span>\n\t\t\t\t\t<ChevronUp\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-basalt-4 w-basalt-4 text-basalt-muted-foreground transition-transform basalt-motion duration-basalt-normal\",\n\t\t\t\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\t\t\t!open && \"rotate-180\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t/>\n\t\t\t\t</button>\n\t\t\t</CollapsibleTrigger>\n\t\t\t<CollapsibleContent unstyled>\n\t\t\t\t<div className=\"flex flex-col gap-basalt-nav-gap pt-basalt-nav-gap\">{children}</div>\n\t\t\t</CollapsibleContent>\n\t\t</Collapsible>\n\t);\n}\n\nexport interface SidebarFooterProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport function SidebarFooter({ className, ...props }: SidebarFooterProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-footer\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex shrink-0 flex-col gap-basalt-content-gap px-basalt-nav-inset py-basalt-nav-inset\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface SidebarUserProps {\n\t/**\n\t * User display name.\n\t */\n\tname: ReactNode;\n\t/**\n\t * Optional user email or secondary text.\n\t */\n\temail?: ReactNode;\n\t/**\n\t * Avatar element slot.\n\t */\n\tavatar?: ReactNode;\n\t/**\n\t * Trailing action slot (e.g. settings or logout button).\n\t */\n\taction?: ReactNode;\n\t/**\n\t * Additional CSS class name.\n\t */\n\tclassName?: string;\n}\n\nexport function SidebarUser({ name, email, avatar, action, className }: SidebarUserProps) {\n\treturn (\n\t\t<div className={cn(\"flex items-center gap-basalt-space-lg\", className)}>\n\t\t\t{avatar}\n\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t<p className=\"truncate text-basalt-base font-medium text-basalt-foreground\">{name}</p>\n\t\t\t\t{email ? (\n\t\t\t\t\t<p className=\"truncate text-basalt-sm text-basalt-muted-foreground\">{email}</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{action}\n\t\t</div>\n\t);\n}\n\nexport interface ContentIslandProps extends HTMLAttributes<HTMLDivElement> {\n\t/** Mobile surface treatment; desktop remains an inset L1 island. @default \"inset\" */\n\tmobileSurface?: \"inset\" | \"edge-to-edge\";\n}\n\nexport function ContentIsland({\n\tmobileSurface = \"inset\",\n\tclassName,\n\t...props\n}: ContentIslandProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-surface-root=\"\"\n\t\t\tdata-basalt-island={mobileSurface}\n\t\t\tclassName={cn(\n\t\t\t\t\"min-h-0 min-w-0 flex-1 bg-basalt-card text-basalt-card-foreground md:rounded-basalt-island md:p-basalt-layout-lg lg:px-basalt-layout-xl\",\n\t\t\t\tmobileSurface === \"inset\"\n\t\t\t\t\t? \"rounded-basalt-lg p-basalt-layout shadow-sm ring-1 ring-basalt-border/40\"\n\t\t\t\t\t: \"md:shadow-sm md:ring-1 md:ring-basalt-border/40\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sidebar.js","names":["DialogPrimitive","SidebarContext","createContext","useSidebar","context","useContext","SidebarProvider","uncontrolled","setUncontrolled","useState","defaultCollapsed","peeking","setPeeking","width","setWidthState","clampSidebarWidth","defaultWidth","setWidth","useCallback","next","lastFocusRef","useRef","prevCollapsed","collapsed","prevOverlay","overlay","resolved","setCollapsed","onCollapsedChange","SidebarResize","cn","side","event","startX","startWidth","target","onMove","delta","move","onUp","dir","Sidebar","collapsedProp","props","body","SkeletonLine","children","resize","frameClass","BASALT_UI_CLASS","OVERLAY_MOTION","className","Dialog","open","DialogPortal","DialogOverlay","node","from","OVERLAY_LAYER","style","onMouseEnter","onMouseLeave","SIDEBAR_ROW_CLASS","SidebarHeader","SidebarSearch","NAV_ROW_CLASS","Search","shortcut","SidebarNav","highlightRef","useHoverHighlight","NAV_LIST_CLASS","SidebarPartition","SidebarItem","active","NAV_ITEM_CLASS","SidebarIconItem","SidebarGroup","setOpen","defaultOpen","Collapsible","CollapsibleTrigger","FOCUS_INSET","label","ChevronUp","CollapsibleContent","SidebarFooter","SidebarUser","avatar","name","email","action","ContentIsland","mobileSurface"],"sources":["../../src/components/sidebar.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { ChevronUp, Search } from \"lucide-react\";\nimport {\n\ttype ButtonHTMLAttributes,\n\tcreateContext,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseContext,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { NAV_ITEM_CLASS, NAV_LIST_CLASS, NAV_ROW_CLASS } from \"../utils/navigation\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"./collapsible\";\nimport { Dialog, DialogOverlay, DialogPortal } from \"./dialog\";\nimport { FOCUS_INSET, OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nexport type SidebarSide = \"left\" | \"right\";\n\nexport interface SidebarContextValue {\n\t/**\n\t * Whether the sidebar is currently collapsed.\n\t */\n\tcollapsed: boolean;\n\t/**\n\t * Callback to update the collapsed state.\n\t */\n\tsetCollapsed: (next: boolean) => void;\n\t/**\n\t * Which edge the sidebar occupies.\n\t */\n\tside: SidebarSide;\n\t/**\n\t * Whether the sidebar is currently displaying a loading skeleton.\n\t */\n\tloading: boolean;\n\t/**\n\t * Whether the sidebar rail expands on pointer hover.\n\t */\n\tpeek: boolean;\n\t/**\n\t * Whether the sidebar is actively hovering in peek preview mode.\n\t */\n\tpeeking: boolean;\n\t/**\n\t * Callback to update the peek preview state.\n\t */\n\tsetPeeking: (next: boolean) => void;\n\t/**\n\t * Whether the sidebar is rendering as a modal overlay drawer instead of in-flow layout chrome.\n\t */\n\toverlay: boolean;\n\t/**\n\t * Current expanded width in pixels, clamped between 180 and 400.\n\t */\n\twidth: number;\n\t/**\n\t * Callback to update the sidebar width. Value is clamped between 180 and 400 pixels.\n\t */\n\tsetWidth: (next: number) => void;\n\t/**\n\t * Reference to the last active element that held focus before opening the sidebar drawer.\n\t */\n\tlastFocusRef: RefObject<HTMLElement | null>;\n}\n\nconst SidebarContext = createContext<SidebarContextValue | null>(null);\n\n/**\n * Accesses the sidebar context value. Must be used within a `SidebarProvider`; throws an error if called outside.\n * Returns the active sidebar state and control callbacks.\n */\nexport function useSidebar(): SidebarContextValue {\n\tconst context = useContext(SidebarContext);\n\tif (!context) {\n\t\tthrow new Error(\"useSidebar must be used within SidebarProvider\");\n\t}\n\treturn context;\n}\n\nexport type SidebarProviderProps = {\n\t/**\n\t * The controlled collapsed state.\n\t */\n\tcollapsed?: boolean;\n\t/**\n\t * The uncontrolled initial collapsed state.\n\t * @default false\n\t */\n\tdefaultCollapsed?: boolean;\n\t/**\n\t * Called when the collapsed state changes.\n\t */\n\tonCollapsedChange?: (collapsed: boolean) => void;\n\t/**\n\t * Which edge the sidebar occupies.\n\t * @default left\n\t */\n\tside?: SidebarSide;\n\t/**\n\t * Replace the nav with a loading skeleton.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Expand the collapsed rail on hover.\n\t * @default false\n\t */\n\tpeek?: boolean;\n\t/**\n\t * Render as an overlay instead of in-flow chrome.\n\t * @default false\n\t */\n\toverlay?: boolean;\n\t/**\n\t * Initial expanded width in pixels, clamped between 180 and 400.\n\t * @default 260\n\t */\n\tdefaultWidth?: number;\n\t/**\n\t * Sidebar chrome and page content.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function SidebarProvider({\n\tcollapsed,\n\tdefaultCollapsed = false,\n\tonCollapsedChange,\n\tside = \"left\",\n\tloading = false,\n\tpeek = false,\n\toverlay = false,\n\tdefaultWidth = 260,\n\tchildren,\n}: SidebarProviderProps) {\n\tconst [uncontrolled, setUncontrolled] = useState(defaultCollapsed);\n\tconst [peeking, setPeeking] = useState(false);\n\tconst [width, setWidthState] = useState(() => clampSidebarWidth(defaultWidth));\n\tconst setWidth = useCallback((next: number) => {\n\t\tsetWidthState(clampSidebarWidth(next));\n\t}, []);\n\tconst lastFocusRef = useRef<HTMLElement | null>(null);\n\tconst prevCollapsed = useRef(collapsed ?? defaultCollapsed);\n\tconst prevOverlay = useRef(overlay);\n\tconst resolved = collapsed ?? uncontrolled;\n\tuseLayoutEffect(() => {\n\t\tif (\n\t\t\toverlay &&\n\t\t\t!resolved &&\n\t\t\t(prevCollapsed.current || !prevOverlay.current) &&\n\t\t\tdocument.activeElement instanceof HTMLElement\n\t\t) {\n\t\t\tlastFocusRef.current = document.activeElement;\n\t\t}\n\t\tprevCollapsed.current = resolved;\n\t\tprevOverlay.current = overlay;\n\t});\n\tconst setCollapsed = useCallback(\n\t\t(next: boolean) => {\n\t\t\tif (!next && document.activeElement instanceof HTMLElement) {\n\t\t\t\tlastFocusRef.current = document.activeElement;\n\t\t\t}\n\t\t\tif (collapsed === undefined) {\n\t\t\t\tsetUncontrolled(next);\n\t\t\t}\n\t\t\tonCollapsedChange?.(next);\n\t\t},\n\t\t[collapsed, onCollapsedChange],\n\t);\n\treturn (\n\t\t<SidebarContext.Provider\n\t\t\tvalue={{\n\t\t\t\tcollapsed: resolved,\n\t\t\t\tsetCollapsed,\n\t\t\t\tside,\n\t\t\t\tloading,\n\t\t\t\tpeek,\n\t\t\t\tpeeking,\n\t\t\t\tsetPeeking,\n\t\t\t\toverlay,\n\t\t\t\twidth,\n\t\t\t\tsetWidth,\n\t\t\t\tlastFocusRef,\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</SidebarContext.Provider>\n\t);\n}\n\nexport type SidebarProps = HTMLAttributes<HTMLElement> & {\n\t/**\n\t * Collapse the rail when no provider is present.\n\t * @default false\n\t */\n\tcollapsed?: boolean;\n};\n\nfunction clampSidebarWidth(next: number) {\n\treturn Math.min(400, Math.max(180, next));\n}\n\nfunction SidebarResize({\n\tside,\n\twidth,\n\tonWidth,\n}: {\n\tside: SidebarSide;\n\twidth: number;\n\tonWidth: (next: number) => void;\n}) {\n\tconst onPointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n\t\tevent.preventDefault();\n\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\tconst startX = event.clientX;\n\t\tconst startWidth = width;\n\t\tconst target = event.currentTarget;\n\t\tconst onMove = (move: PointerEvent) => {\n\t\t\tconst delta = side === \"right\" ? startX - move.clientX : move.clientX - startX;\n\t\t\tonWidth(clampSidebarWidth(startWidth + delta));\n\t\t};\n\t\tconst onUp = () => {\n\t\t\ttarget.removeEventListener(\"pointermove\", onMove);\n\t\t\ttarget.removeEventListener(\"pointerup\", onUp);\n\t\t\ttarget.removeEventListener(\"pointercancel\", onUp);\n\t\t};\n\t\ttarget.addEventListener(\"pointermove\", onMove);\n\t\ttarget.addEventListener(\"pointerup\", onUp);\n\t\ttarget.addEventListener(\"pointercancel\", onUp);\n\t};\n\treturn (\n\t\t<div\n\t\t\trole=\"separator\"\n\t\t\taria-orientation=\"vertical\"\n\t\t\taria-valuenow={width}\n\t\t\taria-valuemin={180}\n\t\t\taria-valuemax={400}\n\t\t\taria-label=\"Resize sidebar\"\n\t\t\ttabIndex={0}\n\t\t\tclassName={cn(\n\t\t\t\t\"absolute top-0 h-full w-basalt-1 cursor-col-resize bg-transparent\",\n\t\t\t\tside === \"right\" ? \"left-0\" : \"right-0\",\n\t\t\t)}\n\t\t\tonPointerDown={onPointerDown}\n\t\t\tonKeyDown={(event) => {\n\t\t\t\tif (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tconst dir = event.key === \"ArrowRight\" ? 1 : -1;\n\t\t\t\tconst delta = side === \"right\" ? -dir * 8 : dir * 8;\n\t\t\t\tonWidth(clampSidebarWidth(width + delta));\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nexport function Sidebar({\n\tcollapsed: collapsedProp,\n\tclassName,\n\tchildren,\n\tonMouseEnter,\n\tonMouseLeave,\n\tstyle,\n\t...props\n}: SidebarProps) {\n\tconst context = useContext(SidebarContext);\n\tconst collapsed = context\n\t\t? context.collapsed && !(context.peek && context.peeking)\n\t\t: (collapsedProp ?? false);\n\tconst side = context?.side ?? \"left\";\n\tconst overlay = context?.overlay ?? false;\n\tconst width = context?.width ?? 260;\n\tconst body = context?.loading ? (\n\t\t<div\n\t\t\tclassName=\"flex flex-col gap-basalt-space-lg p-basalt-space-lg\"\n\t\t\trole=\"status\"\n\t\t\taria-live=\"polite\"\n\t\t>\n\t\t\t<SkeletonLine />\n\t\t\t<SkeletonLine />\n\t\t\t<SkeletonLine />\n\t\t</div>\n\t) : (\n\t\tchildren\n\t);\n\tconst resize =\n\t\tcontext && !collapsed ? (\n\t\t\t<SidebarResize side={side} width={context.width} onWidth={context.setWidth} />\n\t\t) : null;\n\tconst frameClass = cn(\n\t\tBASALT_UI_CLASS,\n\t\t\"relative flex shrink-0 flex-col bg-basalt-background text-basalt-base text-basalt-foreground\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n\tif (overlay && context) {\n\t\treturn (\n\t\t\t<Dialog open={!context.collapsed} onOpenChange={(open) => context.setCollapsed(!open)}>\n\t\t\t\t<DialogPortal>\n\t\t\t\t\t<DialogOverlay />\n\t\t\t\t\t<DialogPrimitive.Content\n\t\t\t\t\t\tdata-basalt-sidebar=\"\"\n\t\t\t\t\t\taria-label=\"Sidebar\"\n\t\t\t\t\t\tdata-overlay=\"\"\n\t\t\t\t\t\tdata-side={side}\n\t\t\t\t\t\taria-busy={context.loading || undefined}\n\t\t\t\t\t\tonMouseEnter={onMouseEnter}\n\t\t\t\t\t\tonMouseLeave={onMouseLeave}\n\t\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tnode &&\n\t\t\t\t\t\t\t\tdocument.activeElement instanceof HTMLElement &&\n\t\t\t\t\t\t\t\t!node.contains(document.activeElement)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcontext.lastFocusRef.current = document.activeElement;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonOpenAutoFocus={(event) => {\n\t\t\t\t\t\t\tconst from = \"relatedTarget\" in event ? event.relatedTarget : null;\n\t\t\t\t\t\t\tif (from instanceof HTMLElement) {\n\t\t\t\t\t\t\t\tcontext.lastFocusRef.current = from;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonCloseAutoFocus={(event) => {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tcontext.lastFocusRef.current?.focus();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tframeClass,\n\t\t\t\t\t\t\tOVERLAY_LAYER,\n\t\t\t\t\t\t\t\"fixed inset-y-0 overflow-hidden shadow-md\",\n\t\t\t\t\t\t\tside === \"right\" ? \"right-0\" : \"left-0\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ width, ...style }}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t>\n\t\t\t\t\t\t{body}\n\t\t\t\t\t\t{resize}\n\t\t\t\t\t</DialogPrimitive.Content>\n\t\t\t\t</DialogPortal>\n\t\t\t</Dialog>\n\t\t);\n\t}\n\treturn (\n\t\t<aside\n\t\t\tdata-basalt-sidebar=\"\"\n\t\t\tdata-collapsed={collapsed ? \"\" : undefined}\n\t\t\tdata-side={side}\n\t\t\taria-busy={context?.loading || undefined}\n\t\t\tonMouseEnter={(event) => {\n\t\t\t\tif (context?.peek && context.collapsed) {\n\t\t\t\t\tcontext.setPeeking(true);\n\t\t\t\t}\n\t\t\t\tonMouseEnter?.(event);\n\t\t\t}}\n\t\t\tonMouseLeave={(event) => {\n\t\t\t\tif (context?.peek) {\n\t\t\t\t\tcontext.setPeeking(false);\n\t\t\t\t}\n\t\t\t\tonMouseLeave?.(event);\n\t\t\t}}\n\t\t\tclassName={cn(\n\t\t\t\tframeClass,\n\t\t\t\t\"sticky overflow-hidden transition-[width] basalt-motion duration-basalt-normal ease-basalt\",\n\t\t\t\tside === \"right\" ? \"order-last\" : undefined,\n\t\t\t\tcollapsed && \"w-basalt-rail\",\n\t\t\t)}\n\t\t\tstyle={!collapsed ? { width, ...style } : style}\n\t\t\t{...props}\n\t\t>\n\t\t\t{body}\n\t\t\t{resize}\n\t\t</aside>\n\t);\n}\n\nconst SIDEBAR_ROW_CLASS =\n\t\"min-h-[calc(var(--basalt-line-row)+2*var(--basalt-space-lg))] py-basalt-space-lg\";\n\nexport interface SidebarHeaderProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport function SidebarHeader({ className, ...props }: SidebarHeaderProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-header\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex h-basalt-14 shrink-0 items-center gap-basalt-row-gap px-basalt-nav-inset\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarSearch`. Renders a native `<button>` element and accepts all standard button HTML attributes and click handlers.\n */\nexport interface SidebarSearchProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n\t/**\n\t * Shortcut key display label rendered inside the trailing kbd tag. Note: this is a visual label only and does not register a global keyboard shortcut.\n\t * @default \"⌘K\"\n\t */\n\tshortcut?: string;\n}\n\nexport function SidebarSearch({\n\tshortcut = \"⌘K\",\n\tclassName,\n\tchildren,\n\t...props\n}: SidebarSearchProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\tNAV_ROW_CLASS,\n\t\t\t\tSIDEBAR_ROW_CLASS,\n\t\t\t\t\"w-full cursor-pointer bg-basalt-secondary transition-colors basalt-motion hover:bg-basalt-hover\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<Search className=\"h-basalt-4 w-basalt-4 text-basalt-muted-foreground\" strokeWidth={1.5} />\n\t\t\t<span className=\"flex-1 text-left text-basalt-base text-basalt-muted-foreground\">\n\t\t\t\t{children}\n\t\t\t</span>\n\t\t\t<kbd className=\"pointer-events-none hidden rounded-basalt-sm border border-basalt-border bg-basalt-card px-basalt-space-md py-basalt-space-xs text-basalt-xs font-medium text-basalt-muted-foreground sm:inline-block\">\n\t\t\t\t{shortcut}\n\t\t\t</kbd>\n\t\t</button>\n\t);\n}\n\nexport interface SidebarNavProps extends HTMLAttributes<HTMLElement> {}\n\nexport function SidebarNav({ className, ...props }: SidebarNavProps) {\n\tconst highlightRef = useHoverHighlight(undefined, { restoreOnPointerLeave: false });\n\treturn (\n\t\t<nav\n\t\t\tref={highlightRef}\n\t\t\tdata-slot=\"sidebar-nav\"\n\t\t\tclassName={cn(\n\t\t\t\tNAV_LIST_CLASS,\n\t\t\t\t\"min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface SidebarPartitionProps extends HTMLAttributes<HTMLParagraphElement> {}\n\nexport function SidebarPartition({ className, ...props }: SidebarPartitionProps) {\n\treturn (\n\t\t<p\n\t\t\tdata-slot=\"sidebar-partition\"\n\t\t\tclassName={cn(\n\t\t\t\t\"shrink-0 px-basalt-row-x pt-basalt-layout pb-basalt-space-lg text-basalt-sm font-semibold tracking-wide text-basalt-foreground uppercase\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type SidebarItemProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n\t/**\n\t * Mark the item as the current page.\n\t * @default false\n\t */\n\tactive?: boolean;\n};\n\nexport function SidebarItem({ active = false, className, ...props }: SidebarItemProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\tdata-basalt-hover-item=\"\"\n\t\t\tdata-sidebar-row=\"\"\n\t\t\tdata-hover-selected={active}\n\t\t\tclassName={cn(NAV_ITEM_CLASS, SIDEBAR_ROW_CLASS, \"w-full\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarIconItem`. Accepts standard button HTML attributes. The caller is responsible for providing accessible labeling via `aria-label` or `aria-labelledby` as icon buttons do not automatically generate accessible names.\n */\nexport interface SidebarIconItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n\t/**\n\t * Mark the icon button as active page item.\n\t * @default false\n\t */\n\tactive?: boolean;\n}\n\nexport function SidebarIconItem({ active = false, className, ...props }: SidebarIconItemProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\tdata-basalt-hover-item=\"\"\n\t\t\tdata-sidebar-row=\"\"\n\t\t\tdata-hover-selected={active}\n\t\t\tclassName={cn(\n\t\t\t\tNAV_ITEM_CLASS,\n\t\t\t\tSIDEBAR_ROW_CLASS,\n\t\t\t\t\"relative w-basalt-control justify-center\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Props for `SidebarGroup`. Uncontrolled collapsible section that accepts only the documented properties. It does not accept controlled open props or arbitrary DOM attributes.\n */\nexport interface SidebarGroupProps {\n\t/**\n\t * Section label displayed on the group trigger.\n\t */\n\tlabel: ReactNode;\n\t/**\n\t * Uncontrolled initial open state for the collapsible group.\n\t * @default true\n\t */\n\tdefaultOpen?: boolean;\n\t/**\n\t * Navigation items rendered inside the group.\n\t */\n\tchildren: ReactNode;\n}\n\nexport function SidebarGroup({ label, defaultOpen = true, children }: SidebarGroupProps) {\n\tconst [open, setOpen] = useState(defaultOpen);\n\treturn (\n\t\t<Collapsible\n\t\t\topen={open}\n\t\t\tonOpenChange={setOpen}\n\t\t\tdata-slot=\"sidebar-group\"\n\t\t\tclassName=\"shrink-0 pt-basalt-layout-sm\"\n\t\t>\n\t\t\t<CollapsibleTrigger asChild>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-slot=\"sidebar-group-label\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex w-full cursor-pointer items-center justify-between gap-basalt-row-gap rounded-basalt-md px-basalt-row-x py-basalt-space-lg text-left text-basalt-xs font-semibold leading-basalt-row tracking-wide text-basalt-muted-foreground uppercase transition-colors basalt-motion hover:text-basalt-foreground\",\n\t\t\t\t\t\tFOCUS_INSET,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"min-w-0 truncate\">{label}</span>\n\t\t\t\t\t<ChevronUp\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-basalt-4 w-basalt-4 text-basalt-muted-foreground transition-transform basalt-motion duration-basalt-normal\",\n\t\t\t\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\t\t\t!open && \"rotate-180\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t/>\n\t\t\t\t</button>\n\t\t\t</CollapsibleTrigger>\n\t\t\t<CollapsibleContent unstyled>\n\t\t\t\t<div className=\"flex flex-col gap-basalt-nav-gap pt-basalt-nav-gap\">{children}</div>\n\t\t\t</CollapsibleContent>\n\t\t</Collapsible>\n\t);\n}\n\nexport interface SidebarFooterProps extends HTMLAttributes<HTMLDivElement> {}\n\nexport function SidebarFooter({ className, ...props }: SidebarFooterProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-footer\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex shrink-0 flex-col gap-basalt-content-gap px-basalt-nav-inset py-basalt-nav-inset\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport interface SidebarUserProps {\n\t/**\n\t * User display name.\n\t */\n\tname: ReactNode;\n\t/**\n\t * Optional user email or secondary text.\n\t */\n\temail?: ReactNode;\n\t/**\n\t * Avatar element slot.\n\t */\n\tavatar?: ReactNode;\n\t/**\n\t * Trailing action slot (e.g. settings or logout button).\n\t */\n\taction?: ReactNode;\n\t/**\n\t * Additional CSS class name.\n\t */\n\tclassName?: string;\n}\n\nexport function SidebarUser({ name, email, avatar, action, className }: SidebarUserProps) {\n\treturn (\n\t\t<div className={cn(\"flex items-center gap-basalt-space-lg\", className)}>\n\t\t\t{avatar}\n\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t<p className=\"truncate text-basalt-base font-medium text-basalt-foreground\">{name}</p>\n\t\t\t\t{email ? (\n\t\t\t\t\t<p className=\"truncate text-basalt-sm text-basalt-muted-foreground\">{email}</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{action}\n\t\t</div>\n\t);\n}\n\nexport interface ContentIslandProps extends HTMLAttributes<HTMLDivElement> {\n\t/** Mobile surface treatment; desktop remains an inset L1 island. @default \"inset\" */\n\tmobileSurface?: \"inset\" | \"edge-to-edge\";\n}\n\nexport function ContentIsland({\n\tmobileSurface = \"inset\",\n\tclassName,\n\t...props\n}: ContentIslandProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-surface-root=\"\"\n\t\t\tdata-basalt-island={mobileSurface}\n\t\t\tclassName={cn(\n\t\t\t\t\"min-h-0 min-w-0 flex-1 bg-basalt-card text-basalt-card-foreground md:rounded-basalt-island md:p-basalt-layout-lg lg:px-basalt-layout-xl\",\n\t\t\t\tmobileSurface === \"inset\"\n\t\t\t\t\t? \"rounded-basalt-lg p-basalt-layout shadow-sm ring-1 ring-basalt-border/40\"\n\t\t\t\t\t: \"md:shadow-sm md:ring-1 md:ring-basalt-border/40\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
/** Logical inline alignment. Maps to CSS `text-align: start | end`. */
|
|
3
|
+
export type TableTextAlign = "start" | "end";
|
|
4
|
+
export type TableSortDirection = "asc" | "desc";
|
|
2
5
|
export type TableProps = {
|
|
3
6
|
/**
|
|
4
7
|
* Additional classes for the table.
|
|
@@ -33,15 +36,23 @@ export type TableHeadProps = {
|
|
|
33
36
|
* Additional classes for the header cell.
|
|
34
37
|
*/
|
|
35
38
|
className?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Logical inline alignment. Omitted headers keep `text-start` unless native `align` is set.
|
|
41
|
+
*/
|
|
42
|
+
textAlign?: TableTextAlign;
|
|
36
43
|
};
|
|
37
|
-
export declare const TableHead: ({ className, ...props }: TableHeadProps & React.ThHTMLAttributes<HTMLTableCellElement>) => React.JSX.Element;
|
|
44
|
+
export declare const TableHead: ({ className, textAlign, align, ...props }: TableHeadProps & React.ThHTMLAttributes<HTMLTableCellElement>) => React.JSX.Element;
|
|
38
45
|
export type TableCellProps = {
|
|
39
46
|
/**
|
|
40
47
|
* Additional classes for the cell.
|
|
41
48
|
*/
|
|
42
49
|
className?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Logical inline alignment. Omitted cells inherit from the table or row. Native HTML `align` is unchanged.
|
|
52
|
+
*/
|
|
53
|
+
textAlign?: TableTextAlign;
|
|
43
54
|
};
|
|
44
|
-
export declare const TableCell: ({ className, ...props }: TableCellProps & React.TdHTMLAttributes<HTMLTableCellElement>) => React.JSX.Element;
|
|
55
|
+
export declare const TableCell: ({ className, textAlign, ...props }: TableCellProps & React.TdHTMLAttributes<HTMLTableCellElement>) => React.JSX.Element;
|
|
45
56
|
export type TableCaptionProps = {
|
|
46
57
|
/**
|
|
47
58
|
* Additional classes for the caption.
|
|
@@ -49,3 +60,29 @@ export type TableCaptionProps = {
|
|
|
49
60
|
className?: string;
|
|
50
61
|
};
|
|
51
62
|
export declare function TableCaption({ className, ...props }: TableCaptionProps & React.HTMLAttributes<HTMLTableCaptionElement>): React.JSX.Element;
|
|
63
|
+
export type TableSortableHeaderProps = {
|
|
64
|
+
children: React.ReactNode;
|
|
65
|
+
/**
|
|
66
|
+
* Logical control layout. `end` places the sort icon inward of the label.
|
|
67
|
+
* @default "start"
|
|
68
|
+
*/
|
|
69
|
+
textAlign?: TableTextAlign;
|
|
70
|
+
/**
|
|
71
|
+
* Current sort direction when this column is sorted.
|
|
72
|
+
*/
|
|
73
|
+
sorted?: TableSortDirection;
|
|
74
|
+
className?: string;
|
|
75
|
+
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" | "children" | "className">;
|
|
76
|
+
export declare const TableSortableHeader: React.ForwardRefExoticComponent<{
|
|
77
|
+
children: React.ReactNode;
|
|
78
|
+
/**
|
|
79
|
+
* Logical control layout. `end` places the sort icon inward of the label.
|
|
80
|
+
* @default "start"
|
|
81
|
+
*/
|
|
82
|
+
textAlign?: TableTextAlign;
|
|
83
|
+
/**
|
|
84
|
+
* Current sort direction when this column is sorted.
|
|
85
|
+
*/
|
|
86
|
+
sorted?: TableSortDirection;
|
|
87
|
+
className?: string;
|
|
88
|
+
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children" | "className" | "type"> & React.RefAttributes<HTMLButtonElement>>;
|
package/dist/components/table.js
CHANGED
|
@@ -2,33 +2,64 @@
|
|
|
2
2
|
import { cn as e } from "../utils/cn.js";
|
|
3
3
|
import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
|
|
4
4
|
import * as n from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { ArrowDown as r, ArrowUp as i, ArrowUpDown as a } from "lucide-react";
|
|
6
|
+
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
7
|
//#region src/components/table.tsx
|
|
7
|
-
var
|
|
8
|
-
ref:
|
|
8
|
+
var l = n.forwardRef(({ className: n, ...r }, i) => /* @__PURE__ */ s("table", {
|
|
9
|
+
ref: i,
|
|
9
10
|
"data-basalt-table": "",
|
|
10
|
-
className: e(t, "w-full border-separate border-spacing-0 caption-bottom text-
|
|
11
|
-
...
|
|
11
|
+
className: e(t, "w-full border-separate border-spacing-0 caption-bottom text-start text-basalt-code leading-[var(--basalt-line-body)] text-basalt-foreground", n),
|
|
12
|
+
...r
|
|
12
13
|
}));
|
|
13
|
-
|
|
14
|
-
var
|
|
14
|
+
l.displayName = "Table";
|
|
15
|
+
var u = (e) => /* @__PURE__ */ s("thead", { ...e }), d = (e) => /* @__PURE__ */ s("tbody", { ...e }), f = (e) => /* @__PURE__ */ s("tfoot", { ...e }), p = ({ className: e, variant: t = "default", ...n }) => /* @__PURE__ */ s("tr", {
|
|
15
16
|
...n,
|
|
16
17
|
"aria-selected": t === "selected" || n["aria-selected"],
|
|
17
18
|
className: e
|
|
18
|
-
}), l = ({ className: t, ...n }) => /* @__PURE__ */ r("th", {
|
|
19
|
-
className: e("relative h-basalt-table-row whitespace-nowrap border-b border-basalt-border px-basalt-table-x py-basalt-table-y text-left align-middle text-basalt-sm font-medium text-basalt-muted-foreground", t),
|
|
20
|
-
...n
|
|
21
|
-
}), u = ({ className: t, ...n }) => /* @__PURE__ */ r("td", {
|
|
22
|
-
className: e("relative h-basalt-table-row px-basalt-table-x py-basalt-table-y align-middle", t),
|
|
23
|
-
...n
|
|
24
19
|
});
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
function m(e) {
|
|
21
|
+
if (e === "end") return "text-end tabular-nums";
|
|
22
|
+
if (e === "start") return "text-start";
|
|
23
|
+
}
|
|
24
|
+
var h = ({ className: t, textAlign: n, align: r, ...i }) => /* @__PURE__ */ s("th", {
|
|
25
|
+
className: e("relative h-basalt-table-row whitespace-nowrap border-b border-basalt-border ps-basalt-table-x pe-basalt-table-x py-basalt-table-y align-middle text-basalt-sm font-medium text-basalt-muted-foreground", m(n) ?? (r == null ? "text-start" : void 0), t),
|
|
26
|
+
align: r,
|
|
27
|
+
...i
|
|
28
|
+
}), g = ({ className: t, textAlign: n, ...r }) => /* @__PURE__ */ s("td", {
|
|
29
|
+
className: e("relative h-basalt-table-row ps-basalt-table-x pe-basalt-table-x py-basalt-table-y align-middle", m(n), t),
|
|
30
|
+
...r
|
|
31
|
+
});
|
|
32
|
+
function _({ className: t, ...n }) {
|
|
33
|
+
return /* @__PURE__ */ s("caption", {
|
|
34
|
+
className: e("px-basalt-panel-x py-basalt-panel-y text-basalt-base text-basalt-muted-foreground", t),
|
|
28
35
|
...n
|
|
29
36
|
});
|
|
30
37
|
}
|
|
38
|
+
function v({ sorted: t, trailing: n }) {
|
|
39
|
+
return /* @__PURE__ */ s(t === "asc" ? i : t === "desc" ? r : a, {
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
className: e("size-basalt-icon-sm shrink-0", n && "ms-auto", !t && "opacity-0 transition-opacity basalt-motion group-hover:opacity-60 group-focus-visible:opacity-60 motion-reduce:transition-none"),
|
|
42
|
+
strokeWidth: 1.5
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
var y = n.forwardRef(({ children: t, textAlign: n = "start", sorted: r, className: i, ...a }, l) => {
|
|
46
|
+
let u = /* @__PURE__ */ s("span", {
|
|
47
|
+
className: "flex min-w-0 items-center gap-basalt-control-gap truncate",
|
|
48
|
+
children: t
|
|
49
|
+
}), d = /* @__PURE__ */ s(v, {
|
|
50
|
+
sorted: r,
|
|
51
|
+
trailing: n !== "end"
|
|
52
|
+
});
|
|
53
|
+
return /* @__PURE__ */ s("button", {
|
|
54
|
+
type: "button",
|
|
55
|
+
ref: l,
|
|
56
|
+
className: e("group flex w-full cursor-pointer items-center gap-basalt-control-gap rounded-basalt-sm border-0 bg-transparent p-0 font-inherit text-inherit font-medium focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-primary", n === "end" ? "justify-end text-end" : "text-start", i),
|
|
57
|
+
...a,
|
|
58
|
+
children: n === "end" ? /* @__PURE__ */ c(o, { children: [d, u] }) : /* @__PURE__ */ c(o, { children: [u, d] })
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
y.displayName = "TableSortableHeader";
|
|
31
62
|
//#endregion
|
|
32
|
-
export {
|
|
63
|
+
export { l as Table, d as TableBody, _ as TableCaption, g as TableCell, f as TableFooter, h as TableHead, u as TableHeader, p as TableRow, y as TableSortableHeader };
|
|
33
64
|
|
|
34
65
|
//# sourceMappingURL=table.js.map
|