@nocoo/basalt 2.1.7 → 2.1.8
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/INTEGRATION.md +2 -0
- package/ai/USAGE.md +1 -1
- package/ai/registry.json +10 -10
- package/dist/components/button.js +2 -2
- package/dist/components/button.js.map +1 -1
- package/dist/components/confirm-dialog.js +1 -1
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/data-table.js +1 -1
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/delete-resource.js +1 -1
- package/dist/components/delete-resource.js.map +1 -1
- package/dist/components/toggle-group.js +2 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.js +1 -1
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.js +14 -13
- package/dist/components/tooltip.js.map +1 -1
- package/dist/styles/standalone.css +37 -13
- package/dist/utils/selection-indicator.js +1 -1
- package/dist/utils/selection-indicator.js.map +1 -1
- package/package.json +2 -2
package/ai/INTEGRATION.md
CHANGED
|
@@ -583,6 +583,8 @@ Breakpoint: `768px`. Below that, the in-flow rail is omitted. The same sidebar c
|
|
|
583
583
|
|
|
584
584
|
`AppHeader` `leading` is the menu button on mobile only (`Button variant="ghost" size="icon" className="h-8 w-8"`).
|
|
585
585
|
|
|
586
|
+
Header actions use a stable hand cursor and compact 12px `TooltipContent`. `Button`, `LinkButton`, `Toggle`, and `ToggleGroupItem` keep their full rectangular pointer target with a transparent `::before`, including rounded corners. Wrap the actual button or link in `TooltipTrigger asChild` so the trigger retains one focusable hit target. `Toggle` and `ToggleGroupItem` selection styling follows `aria-pressed` / `aria-checked`, independently of the tooltip's `data-state`. Icon-only links must include a screen-reader label inside the link as well as an accessible name.
|
|
587
|
+
|
|
586
588
|
Local hook (not in the package):
|
|
587
589
|
|
|
588
590
|
```tsx excerpt:use-is-mobile-hook
|
package/ai/USAGE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Basalt AI & Machine Usage Guide
|
|
2
2
|
|
|
3
|
-
This document describes how AI code assistants, automated agents, and developers can consume `@nocoo/basalt` (v2.1.
|
|
3
|
+
This document describes how AI code assistants, automated agents, and developers can consume `@nocoo/basalt` (v2.1.8).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
package/ai/registry.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@nocoo/basalt",
|
|
3
|
-
"packageVersion": "2.1.
|
|
3
|
+
"packageVersion": "2.1.8",
|
|
4
4
|
"totalModules": 122,
|
|
5
5
|
"totalSymbols": 741,
|
|
6
6
|
"totalValues": 395,
|
|
@@ -8126,7 +8126,7 @@
|
|
|
8126
8126
|
"importPath": "@nocoo/basalt/components/button",
|
|
8127
8127
|
"subpath": "./components/button",
|
|
8128
8128
|
"sourceFile": "packages/basalt/src/components/button.tsx",
|
|
8129
|
-
"sourceHash": "
|
|
8129
|
+
"sourceHash": "fd3e84a54d2f6f61",
|
|
8130
8130
|
"rootAvailable": true,
|
|
8131
8131
|
"maturity": "ready",
|
|
8132
8132
|
"kind": "catalog-component",
|
|
@@ -25878,7 +25878,7 @@
|
|
|
25878
25878
|
"importPath": "@nocoo/basalt/components/toggle",
|
|
25879
25879
|
"subpath": "./components/toggle",
|
|
25880
25880
|
"sourceFile": "packages/basalt/src/components/toggle.tsx",
|
|
25881
|
-
"sourceHash": "
|
|
25881
|
+
"sourceHash": "c507d31badda1b2d",
|
|
25882
25882
|
"rootAvailable": false,
|
|
25883
25883
|
"maturity": "ready",
|
|
25884
25884
|
"kind": "catalog-component",
|
|
@@ -26016,7 +26016,7 @@
|
|
|
26016
26016
|
"importPath": "@nocoo/basalt/components/toggle-group",
|
|
26017
26017
|
"subpath": "./components/toggle-group",
|
|
26018
26018
|
"sourceFile": "packages/basalt/src/components/toggle-group.tsx",
|
|
26019
|
-
"sourceHash": "
|
|
26019
|
+
"sourceHash": "d213fc765fff2b03",
|
|
26020
26020
|
"rootAvailable": false,
|
|
26021
26021
|
"maturity": "ready",
|
|
26022
26022
|
"kind": "catalog-component",
|
|
@@ -26482,7 +26482,7 @@
|
|
|
26482
26482
|
"importPath": "@nocoo/basalt/components/tooltip",
|
|
26483
26483
|
"subpath": "./components/tooltip",
|
|
26484
26484
|
"sourceFile": "packages/basalt/src/components/tooltip.tsx",
|
|
26485
|
-
"sourceHash": "
|
|
26485
|
+
"sourceHash": "ad4e479b428769f8",
|
|
26486
26486
|
"rootAvailable": true,
|
|
26487
26487
|
"maturity": "ready",
|
|
26488
26488
|
"kind": "catalog-component",
|
|
@@ -27636,7 +27636,7 @@
|
|
|
27636
27636
|
"exportName": "Button",
|
|
27637
27637
|
"importPath": "@nocoo/basalt/components/button",
|
|
27638
27638
|
"sourceFile": "packages/basalt/src/components/button.tsx",
|
|
27639
|
-
"sourceHash": "
|
|
27639
|
+
"sourceHash": "fd3e84a54d2f6f61",
|
|
27640
27640
|
"rootAvailable": true,
|
|
27641
27641
|
"maturity": "ready",
|
|
27642
27642
|
"packageDoc": "ai/registry.json#button",
|
|
@@ -27695,7 +27695,7 @@
|
|
|
27695
27695
|
"exportName": "LinkButton",
|
|
27696
27696
|
"importPath": "@nocoo/basalt/components/button",
|
|
27697
27697
|
"sourceFile": "packages/basalt/src/components/button.tsx",
|
|
27698
|
-
"sourceHash": "
|
|
27698
|
+
"sourceHash": "fd3e84a54d2f6f61",
|
|
27699
27699
|
"rootAvailable": false,
|
|
27700
27700
|
"maturity": "ready",
|
|
27701
27701
|
"packageDoc": "ai/registry.json#link-button",
|
|
@@ -27915,7 +27915,7 @@
|
|
|
27915
27915
|
"exportName": "Tooltip",
|
|
27916
27916
|
"importPath": "@nocoo/basalt/components/tooltip",
|
|
27917
27917
|
"sourceFile": "packages/basalt/src/components/tooltip.tsx",
|
|
27918
|
-
"sourceHash": "
|
|
27918
|
+
"sourceHash": "ad4e479b428769f8",
|
|
27919
27919
|
"rootAvailable": true,
|
|
27920
27920
|
"maturity": "ready",
|
|
27921
27921
|
"packageDoc": "ai/registry.json#tooltip",
|
|
@@ -29385,7 +29385,7 @@
|
|
|
29385
29385
|
"exportName": "Toggle",
|
|
29386
29386
|
"importPath": "@nocoo/basalt/components/toggle",
|
|
29387
29387
|
"sourceFile": "packages/basalt/src/components/toggle.tsx",
|
|
29388
|
-
"sourceHash": "
|
|
29388
|
+
"sourceHash": "c507d31badda1b2d",
|
|
29389
29389
|
"rootAvailable": false,
|
|
29390
29390
|
"maturity": "ready",
|
|
29391
29391
|
"packageDoc": "ai/registry.json#toggle",
|
|
@@ -29443,7 +29443,7 @@
|
|
|
29443
29443
|
"exportName": "ToggleGroup",
|
|
29444
29444
|
"importPath": "@nocoo/basalt/components/toggle-group",
|
|
29445
29445
|
"sourceFile": "packages/basalt/src/components/toggle-group.tsx",
|
|
29446
|
-
"sourceHash": "
|
|
29446
|
+
"sourceHash": "d213fc765fff2b03",
|
|
29447
29447
|
"rootAvailable": false,
|
|
29448
29448
|
"maturity": "ready",
|
|
29449
29449
|
"packageDoc": "ai/registry.json#toggle-group",
|
|
@@ -8,7 +8,7 @@ import { cva as a } from "class-variance-authority";
|
|
|
8
8
|
import { Loader2 as o } from "lucide-react";
|
|
9
9
|
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/button.tsx
|
|
11
|
-
var l = a(`${t} inline-flex items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors ${n} disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`, {
|
|
11
|
+
var l = a(`${t} relative inline-flex cursor-pointer items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors before:absolute before:inset-0 ${n} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`, {
|
|
12
12
|
variants: {
|
|
13
13
|
variant: {
|
|
14
14
|
default: "bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90",
|
|
@@ -22,7 +22,7 @@ var l = a(`${t} inline-flex items-center justify-center gap-2 rounded-basalt-md
|
|
|
22
22
|
default: "h-9 px-4 py-2",
|
|
23
23
|
sm: "h-8 rounded-basalt-md px-3 text-xs",
|
|
24
24
|
lg: "h-10 rounded-basalt-md px-6",
|
|
25
|
-
icon: "h-9 w-9"
|
|
25
|
+
icon: "h-9 w-9 shrink-0"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
defaultVariants: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} inline-flex items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90\",\n\t\t\t\tsecondary: \"bg-basalt-control text-basalt-foreground hover:bg-basalt-accent\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive/90\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border border-basalt-border bg-basalt-control hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-9 px-4 py-2\",\n\t\t\t\tsm: \"h-8 rounded-basalt-md px-3 text-xs\",\n\t\t\t\tlg: \"h-10 rounded-basalt-md px-6\",\n\t\t\t\ticon: \"h-9 w-9\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\n// Keep rounded corners inside the button's rectangular pointer target.\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} relative inline-flex cursor-pointer items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors before:absolute before:inset-0 ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90\",\n\t\t\t\tsecondary: \"bg-basalt-control text-basalt-foreground hover:bg-basalt-accent\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive/90\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border border-basalt-border bg-basalt-control hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-9 px-4 py-2\",\n\t\t\t\tsm: \"h-8 rounded-basalt-md px-3 text-xs\",\n\t\t\t\tlg: \"h-10 rounded-basalt-md px-6\",\n\t\t\t\ticon: \"h-9 w-9 shrink-0\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":";;;;;;;;;;AASA,IAAM,IAAiB,EACtB,GAAG,EAAgB,gKAAgK,EAAW,0KAC9L;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,WAAW;GACX,aACC;GACD,SACC;GACD,OAAO;GACP,MAAM;EACP;EACA,MAAM;GACL,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;EACP;CACD;CACA,iBAAiB;EAChB,SAAS;EACT,MAAM;CACP;AACD,CACD,GA2Ca,IAAS,EAAM,YAE1B,EACC,cACA,YACA,SACA,aAAU,IACV,UAAO,UACP,aAAU,IACV,SACA,aACA,aACA,GAAG,KAEJ,MACI;CACJ,IAAM,IAAa,GAAQ,KAAY;CAEvC,IAAI,GAAS;EACZ,IAAI,KAAc,EAAM,eAAe,CAAQ,GAAG;GACjD,IAAM,IAAe,GACf,IACL,OAAO,EAAa,QAAS,YAAY,EAAa,KAAK,YAAY,MAAM,UAExE,KAAwB,MAAwC;IAGrE,AAFA,EAAM,eAAe,GACrB,EAAM,gBAAgB,GAErB,8BAA8B,KAC9B,OAAO,EAAM,4BAA6B,cAE1C,EAAM,yBAAyB;GAEjC,GAEM,KAAkB,MAA+B;IAKtD,CAJI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OAAO,EAAM,QAAQ,eAC/D,EAAM,eAAe,GAEtB,EAAM,gBAAgB,GAClB,OAAO,EAAM,aAAa,4BAA6B,cAC1D,EAAM,YAAY,yBAAyB;GAE7C,GAEM,IAAkB;IACvB,SAAS;IACT,gBAAgB;IAChB,WAAW;IACX,kBAAkB;IAClB,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,mBAAmB;IACnB,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,kBAAkB;IAClB,eAAe;IACf,sBAAsB;IACtB,aAAa;IACb,oBAAoB;IACpB,YAAY;IACZ,mBAAmB;GACpB,GAEM,IAAiB,EAAM,aAAa,GAAc;IACvD,GAAG;IACH,GAAI,IAAiB,EAAE,UAAU,GAAK,IAAI,CAAC;IAC3C,iBAAiB;IACjB,aAAa,IAAU,KAAO,KAAA;IAC9B,UAAU;GACX,CAAC,GAEK,IAAqC;IAC1C,GAAG;IACH,GAAG;IACH,iBAAiB;IACjB,aAAa,IAAU,SAAS,KAAA;IAChC,UAAU;GACX;GAKA,OAJI,MACH,EAAU,WAAW,KAIrB,kBAAC,GAAD;IACC,WAAW,EAAG,EAAe;KAAE;KAAS;IAAK,CAAC,GAAG,CAAS;IACrD;IACL,GAAI;IAEH,UAAA;GACI,CAAA;EAER;EAEA,OACC,kBAAC,GAAD;GAAM,WAAW,EAAG,EAAe;IAAE;IAAS;GAAK,CAAC,GAAG,CAAS;GAAQ;GAAK,GAAI;GAC/E;EACI,CAAA;CAER;CAEA,IAAM,IAAW,IAChB,kBAAC,GAAD;EAAS,WAAU;EAAiD,eAAY;CAAQ,CAAA,IAExF;CAED,OACC,kBAAC,UAAD;EACC,WAAW,EAAG,EAAe;GAAE;GAAS;EAAK,CAAC,GAAG,CAAS;EACrD;EACC;EACN,UAAU;EACV,aAAW,KAAW,KAAA;EACtB,GAAI;EANL,UAAA,CAQE,GACA,CACM;;AAEV,CACD;AACA,EAAO,cAAc;AAqBrB,IAAa,IAAa,EAAM,YAC9B,EAAE,cAAW,YAAS,SAAM,SAAM,aAAU,GAAG,KAAS,MACxD,kBAAC,KAAD;CAAQ;CAAK,WAAW,EAAG,EAAe;EAAE;EAAS;CAAK,CAAC,GAAG,CAAS;CAAG,GAAI;CAA9E,UAAA,CACE,GACA,CACC;AAEL,CAAA,CAAA;AACA,EAAW,cAAc"}
|
|
@@ -14,7 +14,7 @@ function f({ cancelLabel: f = "Cancel", confirmLabel: p = "Confirm", description
|
|
|
14
14
|
}, [v]), /* @__PURE__ */ d(t, {
|
|
15
15
|
open: v,
|
|
16
16
|
onOpenChange: (e) => {
|
|
17
|
-
h
|
|
17
|
+
(!h || e) && _(e);
|
|
18
18
|
},
|
|
19
19
|
children: [l.isValidElement(b) ? /* @__PURE__ */ u(s, {
|
|
20
20
|
ref: S,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm-dialog.js","names":[],"sources":["../../src/components/confirm-dialog.tsx"],"sourcesContent":["import * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\nimport {\n\tAlertDialog,\n\tAlertDialogContent,\n\tAlertDialogDescription,\n\tAlertDialogFooter,\n\tAlertDialogHeader,\n\tAlertDialogTitle,\n\tAlertDialogTrigger,\n} from \"./alert-dialog\";\nimport { Button } from \"./button\";\n\nexport type ConfirmDialogVariant = \"default\" | \"destructive\";\n\nexport interface ConfirmDialogProps {\n\t/** Whether the confirmation dialog is shown. */\n\topen: boolean;\n\t/** Called when the dialog requests to open or close. */\n\tonOpenChange: (open: boolean) => void;\n\t/** Called once when the user confirms. The dialog does not close itself; caller manages loading and asynchronous errors. */\n\tonConfirm: () => void | Promise<void>;\n\t/** The dialog title. */\n\ttitle: React.ReactNode;\n\t/** Supporting copy that describes the action. */\n\tdescription: React.ReactNode;\n\t/**\n\t * Label for the confirm button.\n\t * @default \"Confirm\"\n\t */\n\tconfirmLabel?: React.ReactNode;\n\t/**\n\t * Label for the cancel button.\n\t * @default \"Cancel\"\n\t */\n\tcancelLabel?: React.ReactNode;\n\t/**\n\t * Appearance of the confirm button.\n\t * @default \"default\"\n\t */\n\tvariant?: ConfirmDialogVariant;\n\t/**\n\t * Disable both actions and ignore close requests while work is pending.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Control that opens the dialog. When set, closing restores focus to it.\n\t */\n\ttrigger?: React.ReactElement;\n}\n\nexport interface UseConfirmOptions {\n\t/** The dialog title. */\n\ttitle: React.ReactNode;\n\t/** Supporting copy that describes the action. */\n\tdescription: React.ReactNode;\n\t/** Label for the confirm button. */\n\tconfirmLabel?: React.ReactNode;\n\t/** Label for the cancel button. */\n\tcancelLabel?: React.ReactNode;\n\t/** Appearance of the confirm button. */\n\tvariant?: ConfirmDialogVariant;\n}\n\nexport interface UseConfirmResult {\n\tconfirm: (options: UseConfirmOptions) => Promise<boolean>;\n\tdialogProps: ConfirmDialogProps;\n}\n\nexport function ConfirmDialog({\n\tcancelLabel = \"Cancel\",\n\tconfirmLabel = \"Confirm\",\n\tdescription,\n\tloading = false,\n\tonConfirm,\n\tonOpenChange,\n\topen,\n\ttitle,\n\ttrigger,\n\tvariant = \"default\",\n}: ConfirmDialogProps) {\n\tconst triggerRef = React.useRef<HTMLButtonElement>(null);\n\tconst panelRef = React.useRef<HTMLDivElement>(null);\n\tconst cancelRef = React.useRef<HTMLButtonElement>(null);\n\tconst wasOpenRef = React.useRef(open);\n\tconst openerRef = React.useRef<HTMLElement | null>(null);\n\n\tconst restoreFocus = React.useCallback(() => {\n\t\tif (triggerRef.current?.isConnected) {\n\t\t\ttriggerRef.current.focus();\n\t\t} else if (openerRef.current?.isConnected) {\n\t\t\topenerRef.current.focus();\n\t\t}\n\t\topenerRef.current = null;\n\t}, []);\n\n\tReact.useEffect(() => {\n\t\tif (wasOpenRef.current && !open) {\n\t\t\tif (triggerRef.current?.isConnected) {\n\t\t\t\ttriggerRef.current.focus();\n\t\t\t}\n\t\t}\n\t\twasOpenRef.current = open;\n\t}, [open]);\n\n\treturn (\n\t\t<AlertDialog\n\t\t\topen={open}\n\t\t\tonOpenChange={(next) => {\n\t\t\t\tif (loading && !next) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonOpenChange(next);\n\t\t\t}}\n\t\t>\n\t\t\t{React.isValidElement(trigger) ? (\n\t\t\t\t<AlertDialogTrigger ref={triggerRef} asChild>\n\t\t\t\t\t{trigger}\n\t\t\t\t</AlertDialogTrigger>\n\t\t\t) : null}\n\t\t\t<AlertDialogContent\n\t\t\t\tref={panelRef}\n\t\t\t\tonOpenAutoFocus={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (\n\t\t\t\t\t\t!openerRef.current?.isConnected &&\n\t\t\t\t\t\tdocument.activeElement instanceof HTMLElement &&\n\t\t\t\t\t\t!panelRef.current?.contains(document.activeElement)\n\t\t\t\t\t) {\n\t\t\t\t\t\topenerRef.current = document.activeElement;\n\t\t\t\t\t}\n\t\t\t\t\tif (cancelRef.current && !cancelRef.current.disabled) {\n\t\t\t\t\t\tcancelRef.current.focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tpanelRef.current?.focus();\n\t\t\t\t}}\n\t\t\t\tonCloseAutoFocus={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\trestoreFocus();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<AlertDialogHeader>\n\t\t\t\t\t<AlertDialogTitle>{title}</AlertDialogTitle>\n\t\t\t\t\t<AlertDialogDescription>{description}</AlertDialogDescription>\n\t\t\t\t</AlertDialogHeader>\n\t\t\t\t<AlertDialogFooter>\n\t\t\t\t\t<AlertDialogPrimitive.Cancel asChild>\n\t\t\t\t\t\t<Button ref={cancelRef} disabled={loading} variant=\"outline\">\n\t\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</AlertDialogPrimitive.Cancel>\n\t\t\t\t\t<AlertDialogPrimitive.Action asChild>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tloading={loading}\n\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tif (!loading) {\n\t\t\t\t\t\t\t\t\tvoid onConfirm();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</AlertDialogPrimitive.Action>\n\t\t\t\t</AlertDialogFooter>\n\t\t\t</AlertDialogContent>\n\t\t</AlertDialog>\n\t);\n}\n\nexport function useConfirm(): UseConfirmResult {\n\tconst [open, setOpen] = React.useState(false);\n\tconst [options, setOptions] = React.useState<UseConfirmOptions>({\n\t\ttitle: \"\",\n\t\tdescription: \"\",\n\t});\n\tconst resolverRef = React.useRef<((value: boolean) => void) | null>(null);\n\n\tconst settle = React.useCallback((value: boolean) => {\n\t\tconst resolve = resolverRef.current;\n\t\tresolverRef.current = null;\n\t\tresolve?.(value);\n\t}, []);\n\n\tReact.useEffect(() => {\n\t\treturn () => {\n\t\t\tsettle(false);\n\t\t};\n\t}, [settle]);\n\n\tconst confirm = React.useCallback(\n\t\t(next: UseConfirmOptions) => {\n\t\t\tsettle(false);\n\t\t\tsetOptions(next);\n\t\t\tsetOpen(true);\n\t\t\treturn new Promise<boolean>((resolve) => {\n\t\t\t\tresolverRef.current = resolve;\n\t\t\t});\n\t\t},\n\t\t[settle],\n\t);\n\n\treturn {\n\t\tconfirm,\n\t\tdialogProps: {\n\t\t\topen,\n\t\t\ttitle: options.title,\n\t\t\tdescription: options.description,\n\t\t\tconfirmLabel: options.confirmLabel,\n\t\t\tcancelLabel: options.cancelLabel,\n\t\t\tvariant: options.variant,\n\t\t\tonOpenChange: (next) => {\n\t\t\t\tsetOpen(next);\n\t\t\t\tif (!next) {\n\t\t\t\t\tsettle(false);\n\t\t\t\t}\n\t\t\t},\n\t\t\tonConfirm: () => {\n\t\t\t\tsettle(true);\n\t\t\t\tsetOpen(false);\n\t\t\t},\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;AAsEA,SAAgB,EAAc,EAC7B,iBAAc,UACd,kBAAe,WACf,gBACA,aAAU,IACV,cACA,iBACA,SACA,UACA,YACA,aAAU,aACY;CACtB,IAAM,IAAa,EAAM,OAA0B,IAAI,GACjD,IAAW,EAAM,OAAuB,IAAI,GAC5C,IAAY,EAAM,OAA0B,IAAI,GAChD,IAAa,EAAM,OAAO,CAAI,GAC9B,IAAY,EAAM,OAA2B,IAAI,GAEjD,IAAe,EAAM,kBAAkB;EAM5C,AALI,EAAW,SAAS,cACvB,EAAW,QAAQ,MAAM,IACf,EAAU,SAAS,eAC7B,EAAU,QAAQ,MAAM,GAEzB,EAAU,UAAU;CACrB,GAAG,CAAC,CAAC;CAWL,OATA,EAAM,gBAAgB;EAMrB,AALI,EAAW,WAAW,CAAC,KACtB,EAAW,SAAS,eACvB,EAAW,QAAQ,MAAM,GAG3B,EAAW,UAAU;CACtB,GAAG,CAAC,CAAI,CAAC,GAGR,kBAAC,GAAD;EACO;EACN,eAAe,MAAS;GACnB,
|
|
1
|
+
{"version":3,"file":"confirm-dialog.js","names":[],"sources":["../../src/components/confirm-dialog.tsx"],"sourcesContent":["import * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\nimport {\n\tAlertDialog,\n\tAlertDialogContent,\n\tAlertDialogDescription,\n\tAlertDialogFooter,\n\tAlertDialogHeader,\n\tAlertDialogTitle,\n\tAlertDialogTrigger,\n} from \"./alert-dialog\";\nimport { Button } from \"./button\";\n\nexport type ConfirmDialogVariant = \"default\" | \"destructive\";\n\nexport interface ConfirmDialogProps {\n\t/** Whether the confirmation dialog is shown. */\n\topen: boolean;\n\t/** Called when the dialog requests to open or close. */\n\tonOpenChange: (open: boolean) => void;\n\t/** Called once when the user confirms. The dialog does not close itself; caller manages loading and asynchronous errors. */\n\tonConfirm: () => void | Promise<void>;\n\t/** The dialog title. */\n\ttitle: React.ReactNode;\n\t/** Supporting copy that describes the action. */\n\tdescription: React.ReactNode;\n\t/**\n\t * Label for the confirm button.\n\t * @default \"Confirm\"\n\t */\n\tconfirmLabel?: React.ReactNode;\n\t/**\n\t * Label for the cancel button.\n\t * @default \"Cancel\"\n\t */\n\tcancelLabel?: React.ReactNode;\n\t/**\n\t * Appearance of the confirm button.\n\t * @default \"default\"\n\t */\n\tvariant?: ConfirmDialogVariant;\n\t/**\n\t * Disable both actions and ignore close requests while work is pending.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Control that opens the dialog. When set, closing restores focus to it.\n\t */\n\ttrigger?: React.ReactElement;\n}\n\nexport interface UseConfirmOptions {\n\t/** The dialog title. */\n\ttitle: React.ReactNode;\n\t/** Supporting copy that describes the action. */\n\tdescription: React.ReactNode;\n\t/** Label for the confirm button. */\n\tconfirmLabel?: React.ReactNode;\n\t/** Label for the cancel button. */\n\tcancelLabel?: React.ReactNode;\n\t/** Appearance of the confirm button. */\n\tvariant?: ConfirmDialogVariant;\n}\n\nexport interface UseConfirmResult {\n\tconfirm: (options: UseConfirmOptions) => Promise<boolean>;\n\tdialogProps: ConfirmDialogProps;\n}\n\nexport function ConfirmDialog({\n\tcancelLabel = \"Cancel\",\n\tconfirmLabel = \"Confirm\",\n\tdescription,\n\tloading = false,\n\tonConfirm,\n\tonOpenChange,\n\topen,\n\ttitle,\n\ttrigger,\n\tvariant = \"default\",\n}: ConfirmDialogProps) {\n\tconst triggerRef = React.useRef<HTMLButtonElement>(null);\n\tconst panelRef = React.useRef<HTMLDivElement>(null);\n\tconst cancelRef = React.useRef<HTMLButtonElement>(null);\n\tconst wasOpenRef = React.useRef(open);\n\tconst openerRef = React.useRef<HTMLElement | null>(null);\n\n\tconst restoreFocus = React.useCallback(() => {\n\t\tif (triggerRef.current?.isConnected) {\n\t\t\ttriggerRef.current.focus();\n\t\t} else if (openerRef.current?.isConnected) {\n\t\t\topenerRef.current.focus();\n\t\t}\n\t\topenerRef.current = null;\n\t}, []);\n\n\tReact.useEffect(() => {\n\t\tif (wasOpenRef.current && !open) {\n\t\t\tif (triggerRef.current?.isConnected) {\n\t\t\t\ttriggerRef.current.focus();\n\t\t\t}\n\t\t}\n\t\twasOpenRef.current = open;\n\t}, [open]);\n\n\treturn (\n\t\t<AlertDialog\n\t\t\topen={open}\n\t\t\tonOpenChange={(next) => {\n\t\t\t\tif (loading && !next) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonOpenChange(next);\n\t\t\t}}\n\t\t>\n\t\t\t{React.isValidElement(trigger) ? (\n\t\t\t\t<AlertDialogTrigger ref={triggerRef} asChild>\n\t\t\t\t\t{trigger}\n\t\t\t\t</AlertDialogTrigger>\n\t\t\t) : null}\n\t\t\t<AlertDialogContent\n\t\t\t\tref={panelRef}\n\t\t\t\tonOpenAutoFocus={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (\n\t\t\t\t\t\t!openerRef.current?.isConnected &&\n\t\t\t\t\t\tdocument.activeElement instanceof HTMLElement &&\n\t\t\t\t\t\t!panelRef.current?.contains(document.activeElement)\n\t\t\t\t\t) {\n\t\t\t\t\t\topenerRef.current = document.activeElement;\n\t\t\t\t\t}\n\t\t\t\t\tif (cancelRef.current && !cancelRef.current.disabled) {\n\t\t\t\t\t\tcancelRef.current.focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tpanelRef.current?.focus();\n\t\t\t\t}}\n\t\t\t\tonCloseAutoFocus={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\trestoreFocus();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<AlertDialogHeader>\n\t\t\t\t\t<AlertDialogTitle>{title}</AlertDialogTitle>\n\t\t\t\t\t<AlertDialogDescription>{description}</AlertDialogDescription>\n\t\t\t\t</AlertDialogHeader>\n\t\t\t\t<AlertDialogFooter>\n\t\t\t\t\t<AlertDialogPrimitive.Cancel asChild>\n\t\t\t\t\t\t<Button ref={cancelRef} disabled={loading} variant=\"outline\">\n\t\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</AlertDialogPrimitive.Cancel>\n\t\t\t\t\t<AlertDialogPrimitive.Action asChild>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tloading={loading}\n\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tif (!loading) {\n\t\t\t\t\t\t\t\t\tvoid onConfirm();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</AlertDialogPrimitive.Action>\n\t\t\t\t</AlertDialogFooter>\n\t\t\t</AlertDialogContent>\n\t\t</AlertDialog>\n\t);\n}\n\nexport function useConfirm(): UseConfirmResult {\n\tconst [open, setOpen] = React.useState(false);\n\tconst [options, setOptions] = React.useState<UseConfirmOptions>({\n\t\ttitle: \"\",\n\t\tdescription: \"\",\n\t});\n\tconst resolverRef = React.useRef<((value: boolean) => void) | null>(null);\n\n\tconst settle = React.useCallback((value: boolean) => {\n\t\tconst resolve = resolverRef.current;\n\t\tresolverRef.current = null;\n\t\tresolve?.(value);\n\t}, []);\n\n\tReact.useEffect(() => {\n\t\treturn () => {\n\t\t\tsettle(false);\n\t\t};\n\t}, [settle]);\n\n\tconst confirm = React.useCallback(\n\t\t(next: UseConfirmOptions) => {\n\t\t\tsettle(false);\n\t\t\tsetOptions(next);\n\t\t\tsetOpen(true);\n\t\t\treturn new Promise<boolean>((resolve) => {\n\t\t\t\tresolverRef.current = resolve;\n\t\t\t});\n\t\t},\n\t\t[settle],\n\t);\n\n\treturn {\n\t\tconfirm,\n\t\tdialogProps: {\n\t\t\topen,\n\t\t\ttitle: options.title,\n\t\t\tdescription: options.description,\n\t\t\tconfirmLabel: options.confirmLabel,\n\t\t\tcancelLabel: options.cancelLabel,\n\t\t\tvariant: options.variant,\n\t\t\tonOpenChange: (next) => {\n\t\t\t\tsetOpen(next);\n\t\t\t\tif (!next) {\n\t\t\t\t\tsettle(false);\n\t\t\t\t}\n\t\t\t},\n\t\t\tonConfirm: () => {\n\t\t\t\tsettle(true);\n\t\t\t\tsetOpen(false);\n\t\t\t},\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -82,7 +82,7 @@ function b({ data: g, columns: b, filter: ae = "", loading: x = !1, empty: oe =
|
|
|
82
82
|
let t = v(e.row) ? e.row : null;
|
|
83
83
|
if (!t) continue;
|
|
84
84
|
let r = B.current.get(t)?.[e.occurrence];
|
|
85
|
-
|
|
85
|
+
r && !n.has(r) && V.current.get(r) === t && (e.key = r, n.add(r));
|
|
86
86
|
}
|
|
87
87
|
let u = l.map(({ row: r, index: i, occurrence: a, key: o }) => {
|
|
88
88
|
let c = v(r) ? r : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.js","names":[],"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n\ttype CSSProperties,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { Pagination } from \"./pagination\";\nimport { SkeletonLine } from \"./skeleton-line\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type DataTableColumn<T> = {\n\tid: string;\n\theader: string;\n\taccessor: (row: T) => ReactNode;\n\tsortValue?: (row: T) => string | number | bigint;\n\tfilterValue?: (row: T) => string | number | bigint;\n\t/** Rich header content; header remains the plain text accessible name. */\n\theaderContent?: ReactNode;\n\t/** Whether the header changes sorting. @default true */\n\tsortable?: boolean;\n\t/** Width of the header and its column. */\n\twidth?: CSSProperties[\"width\"];\n\t/** Classes applied to the header cell. */\n\theaderClassName?: string;\n\t/** Classes applied to each data cell. */\n\tcellClassName?: string;\n};\n\nexport type DataTableSort = { id: string; dir: \"asc\" | \"desc\" };\n\nfunction rank(value: unknown): number {\n\tif (value === Number.NEGATIVE_INFINITY) {\n\t\treturn 0;\n\t}\n\tif (typeof value === \"bigint\" || (typeof value === \"number\" && Number.isFinite(value))) {\n\t\treturn 1;\n\t}\n\tif (value === Number.POSITIVE_INFINITY) {\n\t\treturn 2;\n\t}\n\tif (typeof value === \"number\") {\n\t\treturn 3;\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn 4;\n\t}\n\treturn 5;\n}\n\nfunction compareUnknown(left: unknown, right: unknown): number {\n\tconst leftRank = rank(left);\n\tconst rightRank = rank(right);\n\tif (leftRank !== rightRank) {\n\t\treturn leftRank - rightRank;\n\t}\n\tif (leftRank === 1) {\n\t\tconst a = left as number | bigint;\n\t\tconst b = right as number | bigint;\n\t\treturn a < b ? -1 : a > b ? 1 : 0;\n\t}\n\tconst leftStr = String(left);\n\tconst rightStr = String(right);\n\treturn leftStr < rightStr ? -1 : leftStr > rightStr ? 1 : 0;\n}\n\nfunction primitiveKey(\n\trow: unknown,\n\tindex: number,\n\tsymbols: Map<symbol, string>,\n\tseq: { current: number },\n): string {\n\tif (row === null) {\n\t\treturn \"prim:null\";\n\t}\n\tif (row === undefined) {\n\t\treturn \"prim:undefined\";\n\t}\n\tif (typeof row === \"symbol\") {\n\t\tlet key = symbols.get(row);\n\t\tif (!key) {\n\t\t\tkey = `prim:symbol:${seq.current++}`;\n\t\t\tsymbols.set(row, key);\n\t\t}\n\t\treturn key;\n\t}\n\tconst type = typeof row;\n\tif (type === \"number\") {\n\t\tif (Object.is(row, -0)) {\n\t\t\treturn \"prim:number:-0\";\n\t\t}\n\t\treturn `prim:number:${String(row)}`;\n\t}\n\tif (type === \"string\" || type === \"bigint\" || type === \"boolean\") {\n\t\treturn `prim:${type}:${String(row)}`;\n\t}\n\treturn `prim:${index}`;\n}\n\nfunction isInstanceKey(key: string) {\n\treturn key.startsWith(\"dup:\") || key.startsWith(\"gen:\");\n}\n\nfunction isRefRow(row: unknown): row is object {\n\treturn typeof row === \"function\" || (typeof row === \"object\" && row !== null);\n}\n\nfunction filterSource<T>(column: DataTableColumn<T>, row: T): string {\n\tif (column.filterValue) {\n\t\treturn String(column.filterValue(row));\n\t}\n\tif (column.sortValue) {\n\t\treturn String(column.sortValue(row));\n\t}\n\tconst rendered = column.accessor(row);\n\tif (\n\t\ttypeof rendered === \"string\" ||\n\t\ttypeof rendered === \"number\" ||\n\t\ttypeof rendered === \"bigint\"\n\t) {\n\t\treturn String(rendered);\n\t}\n\treturn \"\";\n}\n\nfunction publicSelectId<T>(\n\trow: T,\n\tindex: number,\n\tkey: string,\n\tgetRowId?: (row: T, index: number) => string,\n): string {\n\tconst requested = getRowId?.(row, index);\n\tif (requested !== undefined) {\n\t\treturn requested;\n\t}\n\tif (isRefRow(row) && \"id\" in row && row.id != null) {\n\t\treturn String(row.id);\n\t}\n\treturn key;\n}\n\nexport type DataTableProps<T = unknown> = {\n\t/**\n\t * Rows to render.\n\t */\n\tdata: T[];\n\t/**\n\t * Column descriptors.\n\t */\n\tcolumns: DataTableColumn<T>[];\n\t/**\n\t * Filter query matched against column values.\n\t * @default \"\"\n\t */\n\tfilter?: string;\n\t/**\n\t * Replace rows with a loading placeholder.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Copy shown when no rows remain after filtering.\n\t * @default \"No results\"\n\t */\n\tempty?: ReactNode;\n\t/**\n\t * Controlled selected row ids.\n\t */\n\tselected?: string[];\n\t/**\n\t * Uncontrolled initial selected row ids.\n\t */\n\tdefaultSelected?: string[];\n\t/**\n\t * Called when selected row ids change.\n\t */\n\tonSelectedChange?: (ids: string[]) => void;\n\t/**\n\t * Allow more than one selected row.\n\t * @default false\n\t */\n\tmultiple?: boolean;\n\t/**\n\t * Controlled 1-based page. Used with pageSize.\n\t */\n\tpage?: number;\n\t/**\n\t * Uncontrolled initial page.\n\t * @default 1\n\t */\n\tdefaultPage?: number;\n\t/**\n\t * Rows per page. Omit to show every row.\n\t */\n\tpageSize?: number;\n\t/**\n\t * Called when the page changes.\n\t */\n\tonPageChange?: (page: number) => void;\n\t/**\n\t * Stable id for a row.\n\t */\n\tgetRowId?: (row: T, index: number) => string;\n\t/**\n\t * Additional classes for the table.\n\t */\n\tclassName?: string;\n\t/** Controlled sorting. null explicitly disables sorting. */\n\tsort?: DataTableSort | null;\n\t/** Initial sorting for uncontrolled usage. @default null */\n\tdefaultSort?: DataTableSort | null;\n\t/** Reports header sorting requests. Controlled values change only when the caller accepts. */\n\tonSortChange?: (sort: DataTableSort | null) => void;\n\t/** Caller supplies sorted rows; headers only report requests. @default false */\n\tmanualSorting?: boolean;\n\t/** Caller supplies the current page; rows are never sliced again. Use stable row IDs across pages. @default false */\n\tmanualPagination?: boolean;\n\t/** Caller supplies filtered rows; filter is not applied locally. @default false */\n\tmanualFiltering?: boolean;\n\t/** Total matching row count in manualPagination mode; defaults to data.length. */\n\ttotal?: number;\n\t/** Error content replacing rows after loading finishes. */\n\terror?: ReactNode;\n\t/** Optional retry action for an error. The caller owns the request. */\n\tonRetry?: () => void;\n\t/** Retry button text. @default \"Try again\" */\n\tretryLabel?: string;\n\t/** Accessible table name. @default \"Data table\" */\n\t\"aria-label\"?: string;\n\t/** ID of additional table instructions or summary. */\n\t\"aria-describedby\"?: string;\n};\n\nexport function DataTable<T>({\n\tdata,\n\tcolumns,\n\tfilter = \"\",\n\tloading = false,\n\tempty = \"No results\",\n\tselected,\n\tdefaultSelected,\n\tonSelectedChange,\n\tmultiple = false,\n\tpage,\n\tdefaultPage = 1,\n\tpageSize,\n\tonPageChange,\n\tgetRowId,\n\tclassName,\n\tsort: controlledSort,\n\tdefaultSort = null,\n\tonSortChange,\n\tmanualSorting = false,\n\tmanualPagination = false,\n\tmanualFiltering = false,\n\ttotal,\n\terror,\n\tonRetry,\n\tretryLabel = \"Try again\",\n\t\"aria-label\": ariaLabel = \"Data table\",\n\t\"aria-describedby\": ariaDescribedBy,\n}: DataTableProps<T>) {\n\tconst [uncontrolledSort, setUncontrolledSort] = useState<DataTableSort | null>(defaultSort);\n\tconst sort = controlledSort === undefined ? uncontrolledSort : controlledSort;\n\tconst requestSort = (next: DataTableSort) => {\n\t\tif (controlledSort === undefined) setUncontrolledSort(next);\n\t\tonSortChange?.(next);\n\t};\n\tconst [uncontrolledSelected, setUncontrolledSelected] = useState<string[]>(defaultSelected ?? []);\n\tconst [uncontrolledPage, setUncontrolledPage] = useState(defaultPage);\n\tconst rowIds = useRef(new WeakMap<object, string>());\n\tconst rowSeq = useRef(0);\n\tconst assignedKeys = useRef(new WeakMap<object, string[]>());\n\tconst lastOwner = useRef(new Map<string, object>());\n\tconst lastKeyByCanonical = useRef(new Map<string, string>());\n\tconst lastDupsByCanonical = useRef(new Map<string, string[]>());\n\tconst symbolKeys = useRef(new Map<symbol, string>());\n\tconst query = filter.trim().toLowerCase();\n\n\tconst rows = useMemo(() => {\n\t\tconst identityOf = (row: object) => {\n\t\t\tlet stored = rowIds.current.get(row);\n\t\t\tif (!stored) {\n\t\t\t\tstored = `basalt-row-${rowSeq.current++}`;\n\t\t\t\trowIds.current.set(row, stored);\n\t\t\t}\n\t\t\treturn stored;\n\t\t};\n\t\tconst canonicalOf = (row: T, index: number) => {\n\t\t\tconst requested = getRowId?.(row, index);\n\t\t\tif (requested !== undefined) {\n\t\t\t\treturn `get:${requested}`;\n\t\t\t}\n\t\t\tif (isRefRow(row) && \"id\" in row) {\n\t\t\t\tconst raw = (row as { id: unknown }).id;\n\t\t\t\tif (raw != null) {\n\t\t\t\t\treturn `id:${String(raw)}`;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst used = new Set<string>();\n\t\tconst nextLastKey = new Map<string, string>();\n\t\tconst nextDups = new Map<string, string[]>();\n\t\tconst nextAssigned = new Map<object, string[]>();\n\t\tconst nextOwner = new Map<string, object>();\n\t\tconst rememberKey = (row: T, index: number, key: string, objectRow: object | null) => {\n\t\t\tif (!objectRow) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst list = nextAssigned.get(objectRow) ?? [];\n\t\t\tlist.push(key);\n\t\t\tnextAssigned.set(objectRow, list);\n\t\t\tnextOwner.set(key, objectRow);\n\t\t\tconst canonical = canonicalOf(row, index);\n\t\t\tif (!canonical) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnextLastKey.set(canonical, key);\n\t\t\tif (isInstanceKey(key)) {\n\t\t\t\tconst dups = nextDups.get(canonical) ?? [];\n\t\t\t\tdups.push(key);\n\t\t\t\tnextDups.set(canonical, dups);\n\t\t\t}\n\t\t};\n\t\tconst counts = new WeakMap<object, number>();\n\t\tconst pending = data.map((row, index) => {\n\t\t\tconst objectRow = isRefRow(row) ? row : null;\n\t\t\tconst occurrence = objectRow ? (counts.get(objectRow) ?? 0) : 0;\n\t\t\tif (objectRow) {\n\t\t\t\tcounts.set(objectRow, occurrence + 1);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\trow,\n\t\t\t\tindex,\n\t\t\t\toccurrence,\n\t\t\t\tkey: undefined as string | undefined,\n\t\t\t};\n\t\t});\n\t\tfor (const item of pending) {\n\t\t\tconst objectRow = isRefRow(item.row) ? item.row : null;\n\t\t\tif (!objectRow) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst previous = assignedKeys.current.get(objectRow)?.[item.occurrence];\n\t\t\tif (!previous || used.has(previous)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lastOwner.current.get(previous) === objectRow) {\n\t\t\t\titem.key = previous;\n\t\t\t\tused.add(previous);\n\t\t\t}\n\t\t}\n\t\tconst keyed = pending.map(({ row, index, occurrence, key: reserved }) => {\n\t\t\tconst objectRow = isRefRow(row) ? row : null;\n\t\t\tif (reserved) {\n\t\t\t\trememberKey(row, index, reserved, objectRow);\n\t\t\t\treturn {\n\t\t\t\t\trow,\n\t\t\t\t\tkey: reserved,\n\t\t\t\t\tselectId: publicSelectId(row, index, reserved, getRowId),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst isRepeat = occurrence > 0;\n\t\t\tlet key: string | undefined;\n\t\t\tconst requested = canonicalOf(row, index);\n\t\t\tif (requested) {\n\t\t\t\tkey = requested;\n\t\t\t}\n\t\t\tif (objectRow) {\n\t\t\t\tconst stored = identityOf(objectRow);\n\t\t\t\tif (!key) {\n\t\t\t\t\tkey = isRepeat ? `gen:${stored}#${occurrence}` : `gen:${stored}`;\n\t\t\t\t} else if (used.has(key) || isRepeat) {\n\t\t\t\t\tconst reused = (lastDupsByCanonical.current.get(key) ?? []).find(\n\t\t\t\t\t\t(candidate) => !used.has(candidate),\n\t\t\t\t\t);\n\t\t\t\t\tkey = reused ?? (isRepeat ? `dup:${stored}#${occurrence}` : `dup:${stored}`);\n\t\t\t\t} else {\n\t\t\t\t\tconst inherited = lastKeyByCanonical.current.get(key);\n\t\t\t\t\tif (inherited && !used.has(inherited) && isInstanceKey(inherited)) {\n\t\t\t\t\t\tkey = inherited;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tkey = key ?? primitiveKey(row, index, symbolKeys.current, rowSeq);\n\t\t\tif (used.has(key)) {\n\t\t\t\tlet n = 0;\n\t\t\t\tlet candidate = `occ:${key}#${n}`;\n\t\t\t\twhile (used.has(candidate)) {\n\t\t\t\t\tn += 1;\n\t\t\t\t\tcandidate = `occ:${key}#${n}`;\n\t\t\t\t}\n\t\t\t\tkey = candidate;\n\t\t\t}\n\t\t\tused.add(key);\n\t\t\trememberKey(row, index, key, objectRow);\n\t\t\treturn { row, key, selectId: publicSelectId(row, index, key, getRowId) };\n\t\t});\n\t\tconst filtered =\n\t\t\tquery && !manualFiltering\n\t\t\t\t? keyed.filter(({ row }) =>\n\t\t\t\t\t\tcolumns.some((column) => filterSource(column, row).toLowerCase().includes(query)),\n\t\t\t\t\t)\n\t\t\t\t: keyed;\n\t\tconst sorted = (() => {\n\t\t\tif (!sort || manualSorting) {\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t\tconst column = columns.find((item) => item.id === sort.id);\n\t\t\tif (!column) {\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t\treturn [...filtered].sort((a, b) => {\n\t\t\t\tconst left = column.sortValue?.(a.row) ?? column.accessor(a.row);\n\t\t\t\tconst right = column.sortValue?.(b.row) ?? column.accessor(b.row);\n\t\t\t\tconst cmp = compareUnknown(left, right);\n\t\t\t\treturn sort.dir === \"asc\" ? cmp : -cmp;\n\t\t\t});\n\t\t})();\n\t\treturn {\n\t\t\trows: sorted,\n\t\t\tassigned: nextAssigned,\n\t\t\towner: nextOwner,\n\t\t\tlastKey: nextLastKey,\n\t\t\tdups: nextDups,\n\t\t};\n\t}, [columns, data, getRowId, query, sort, manualFiltering, manualSorting]);\n\n\tuseLayoutEffect(() => {\n\t\tfor (const [objectRow, keys] of rows.assigned) {\n\t\t\tassignedKeys.current.set(objectRow, keys);\n\t\t}\n\t\tlastOwner.current = rows.owner;\n\t\tlastKeyByCanonical.current = rows.lastKey;\n\t\tlastDupsByCanonical.current = rows.dups;\n\t}, [rows]);\n\n\tconst selectable =\n\t\tselected !== undefined || defaultSelected !== undefined || onSelectedChange !== undefined;\n\tconst selectedIds = selected ?? uncontrolledSelected;\n\tconst setSelectedIds = useCallback(\n\t\t(next: string[]) => {\n\t\t\tif (selected === undefined) {\n\t\t\t\tsetUncontrolledSelected(next);\n\t\t\t}\n\t\t\tonSelectedChange?.(next);\n\t\t},\n\t\t[onSelectedChange, selected],\n\t);\n\tconst rowCount = manualPagination && total !== undefined ? Math.max(0, total) : rows.rows.length;\n\tconst pageCount = pageSize && pageSize > 0 ? Math.max(1, Math.ceil(rowCount / pageSize)) : 1;\n\tconst resolvedPage = Math.min(pageCount, Math.max(1, page ?? uncontrolledPage));\n\tconst setResolvedPage = useCallback(\n\t\t(next: number) => {\n\t\t\tif (page === undefined) {\n\t\t\t\tsetUncontrolledPage(next);\n\t\t\t}\n\t\t\tonPageChange?.(next);\n\t\t},\n\t\t[onPageChange, page],\n\t);\n\tconst lastCorrection = useRef<string | null>(null);\n\tuseEffect(() => {\n\t\tconst requested = page ?? uncontrolledPage;\n\t\tif (requested === resolvedPage || loading) {\n\t\t\tlastCorrection.current = null;\n\t\t\treturn;\n\t\t}\n\t\tconst correction = `${requested}:${resolvedPage}`;\n\t\tif (lastCorrection.current !== correction) {\n\t\t\tlastCorrection.current = correction;\n\t\t\tsetResolvedPage(resolvedPage);\n\t\t}\n\t}, [page, uncontrolledPage, resolvedPage, loading, setResolvedPage]);\n\tconst paged =\n\t\t!manualPagination && pageSize && pageSize > 0\n\t\t\t? rows.rows.slice((resolvedPage - 1) * pageSize, resolvedPage * pageSize)\n\t\t\t: rows.rows;\n\tconst colCount = columns.length + (selectable ? 1 : 0);\n\tconst toggleSelected = (id: string) => {\n\t\tif (multiple) {\n\t\t\tsetSelectedIds(\n\t\t\t\tselectedIds.includes(id) ? selectedIds.filter((item) => item !== id) : [...selectedIds, id],\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tsetSelectedIds(selectedIds.includes(id) ? [] : [id]);\n\t};\n\n\treturn (\n\t\t<div className=\"flex min-w-0 flex-col gap-3\">\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${ariaLabel} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow regions need keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"min-w-0 overflow-x-auto rounded-basalt-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-primary\"\n\t\t\t>\n\t\t\t\t<Table\n\t\t\t\t\tclassName={cn(\"w-full\", className)}\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t{selectable ? (\n\t\t\t\t\t\t\t\t<TableHead>\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Select</span>\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead\n\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\tclassName={column.headerClassName}\n\t\t\t\t\t\t\t\t\tstyle={{ width: column.width }}\n\t\t\t\t\t\t\t\t\tscope=\"col\"\n\t\t\t\t\t\t\t\t\taria-sort={\n\t\t\t\t\t\t\t\t\t\tcolumn.sortable === false\n\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t: sort?.id === column.id\n\t\t\t\t\t\t\t\t\t\t\t\t? sort.dir === \"asc\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"ascending\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"descending\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"none\"\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{column.sortable === false ? (\n\t\t\t\t\t\t\t\t\t\t(column.headerContent ?? column.header)\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label={column.header}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"appearance-none border-0 bg-transparent p-0 font-inherit text-inherit font-medium cursor-pointer rounded-sm focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-basalt-primary\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\trequestSort(\n\t\t\t\t\t\t\t\t\t\t\t\t\tsort?.id === column.id && sort.dir === \"asc\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? { id: column.id, dir: \"desc\" }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: { id: column.id, dir: \"asc\" },\n\t\t\t\t\t\t\t\t\t\t\t\t)\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\t\t{column.headerContent ?? column.header}\n\t\t\t\t\t\t\t\t\t\t\t{sort?.id === column.id ? (sort.dir === \"asc\" ? \" ↑\" : \" ↓\") : \"\"}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t)}\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</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{loading ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div role=\"status\" className=\"flex flex-col gap-2 py-2\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Loading</span>\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t</div>\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) : error != null && error !== false ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex flex-wrap items-center justify-between gap-3 py-6\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div>{error}</div>\n\t\t\t\t\t\t\t\t\t\t{onRetry ? (\n\t\t\t\t\t\t\t\t\t\t\t<Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n\t\t\t\t\t\t\t\t\t\t\t\t{retryLabel}\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</div>\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) : paged.length === 0 ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div role=\"status\">{empty}</div>\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\t\tpaged.map(({ row, key, selectId }) => {\n\t\t\t\t\t\t\t\tconst isSelected = selectedIds.includes(selectId);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\t\tvariant={isSelected ? \"selected\" : \"default\"}\n\t\t\t\t\t\t\t\t\t\taria-selected={selectable ? isSelected : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{selectable ? (\n\t\t\t\t\t\t\t\t\t\t\t<TableCell>\n\t\t\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={isSelected}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Select ${selectId}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={() => toggleSelected(selectId)}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t{columns.map((column) => {\n\t\t\t\t\t\t\t\t\t\t\tconst cell = column.accessor(row);\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<TableCell key={column.id} className={column.cellClassName}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{typeof cell === \"bigint\" ? String(cell) : cell}\n\t\t\t\t\t\t\t\t\t\t\t\t</TableCell>\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</TableRow>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\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{pageSize && pageSize > 0 ? (\n\t\t\t\t<Pagination\n\t\t\t\t\tpage={resolvedPage}\n\t\t\t\t\tpageCount={pageCount}\n\t\t\t\t\tdisabled={loading}\n\t\t\t\t\tonPageChange={setResolvedPage}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-table.js","names":[],"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n\ttype CSSProperties,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { Pagination } from \"./pagination\";\nimport { SkeletonLine } from \"./skeleton-line\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"./table\";\n\nexport type DataTableColumn<T> = {\n\tid: string;\n\theader: string;\n\taccessor: (row: T) => ReactNode;\n\tsortValue?: (row: T) => string | number | bigint;\n\tfilterValue?: (row: T) => string | number | bigint;\n\t/** Rich header content; header remains the plain text accessible name. */\n\theaderContent?: ReactNode;\n\t/** Whether the header changes sorting. @default true */\n\tsortable?: boolean;\n\t/** Width of the header and its column. */\n\twidth?: CSSProperties[\"width\"];\n\t/** Classes applied to the header cell. */\n\theaderClassName?: string;\n\t/** Classes applied to each data cell. */\n\tcellClassName?: string;\n};\n\nexport type DataTableSort = { id: string; dir: \"asc\" | \"desc\" };\n\nfunction rank(value: unknown): number {\n\tif (value === Number.NEGATIVE_INFINITY) {\n\t\treturn 0;\n\t}\n\tif (typeof value === \"bigint\" || (typeof value === \"number\" && Number.isFinite(value))) {\n\t\treturn 1;\n\t}\n\tif (value === Number.POSITIVE_INFINITY) {\n\t\treturn 2;\n\t}\n\tif (typeof value === \"number\") {\n\t\treturn 3;\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn 4;\n\t}\n\treturn 5;\n}\n\nfunction compareUnknown(left: unknown, right: unknown): number {\n\tconst leftRank = rank(left);\n\tconst rightRank = rank(right);\n\tif (leftRank !== rightRank) {\n\t\treturn leftRank - rightRank;\n\t}\n\tif (leftRank === 1) {\n\t\tconst a = left as number | bigint;\n\t\tconst b = right as number | bigint;\n\t\treturn a < b ? -1 : a > b ? 1 : 0;\n\t}\n\tconst leftStr = String(left);\n\tconst rightStr = String(right);\n\treturn leftStr < rightStr ? -1 : leftStr > rightStr ? 1 : 0;\n}\n\nfunction primitiveKey(\n\trow: unknown,\n\tindex: number,\n\tsymbols: Map<symbol, string>,\n\tseq: { current: number },\n): string {\n\tif (row === null) {\n\t\treturn \"prim:null\";\n\t}\n\tif (row === undefined) {\n\t\treturn \"prim:undefined\";\n\t}\n\tif (typeof row === \"symbol\") {\n\t\tlet key = symbols.get(row);\n\t\tif (!key) {\n\t\t\tkey = `prim:symbol:${seq.current++}`;\n\t\t\tsymbols.set(row, key);\n\t\t}\n\t\treturn key;\n\t}\n\tconst type = typeof row;\n\tif (type === \"number\") {\n\t\tif (Object.is(row, -0)) {\n\t\t\treturn \"prim:number:-0\";\n\t\t}\n\t\treturn `prim:number:${String(row)}`;\n\t}\n\tif (type === \"string\" || type === \"bigint\" || type === \"boolean\") {\n\t\treturn `prim:${type}:${String(row)}`;\n\t}\n\treturn `prim:${index}`;\n}\n\nfunction isInstanceKey(key: string) {\n\treturn key.startsWith(\"dup:\") || key.startsWith(\"gen:\");\n}\n\nfunction isRefRow(row: unknown): row is object {\n\treturn typeof row === \"function\" || (typeof row === \"object\" && row !== null);\n}\n\nfunction filterSource<T>(column: DataTableColumn<T>, row: T): string {\n\tif (column.filterValue) {\n\t\treturn String(column.filterValue(row));\n\t}\n\tif (column.sortValue) {\n\t\treturn String(column.sortValue(row));\n\t}\n\tconst rendered = column.accessor(row);\n\tif (\n\t\ttypeof rendered === \"string\" ||\n\t\ttypeof rendered === \"number\" ||\n\t\ttypeof rendered === \"bigint\"\n\t) {\n\t\treturn String(rendered);\n\t}\n\treturn \"\";\n}\n\nfunction publicSelectId<T>(\n\trow: T,\n\tindex: number,\n\tkey: string,\n\tgetRowId?: (row: T, index: number) => string,\n): string {\n\tconst requested = getRowId?.(row, index);\n\tif (requested !== undefined) {\n\t\treturn requested;\n\t}\n\tif (isRefRow(row) && \"id\" in row && row.id != null) {\n\t\treturn String(row.id);\n\t}\n\treturn key;\n}\n\nexport type DataTableProps<T = unknown> = {\n\t/**\n\t * Rows to render.\n\t */\n\tdata: T[];\n\t/**\n\t * Column descriptors.\n\t */\n\tcolumns: DataTableColumn<T>[];\n\t/**\n\t * Filter query matched against column values.\n\t * @default \"\"\n\t */\n\tfilter?: string;\n\t/**\n\t * Replace rows with a loading placeholder.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Copy shown when no rows remain after filtering.\n\t * @default \"No results\"\n\t */\n\tempty?: ReactNode;\n\t/**\n\t * Controlled selected row ids.\n\t */\n\tselected?: string[];\n\t/**\n\t * Uncontrolled initial selected row ids.\n\t */\n\tdefaultSelected?: string[];\n\t/**\n\t * Called when selected row ids change.\n\t */\n\tonSelectedChange?: (ids: string[]) => void;\n\t/**\n\t * Allow more than one selected row.\n\t * @default false\n\t */\n\tmultiple?: boolean;\n\t/**\n\t * Controlled 1-based page. Used with pageSize.\n\t */\n\tpage?: number;\n\t/**\n\t * Uncontrolled initial page.\n\t * @default 1\n\t */\n\tdefaultPage?: number;\n\t/**\n\t * Rows per page. Omit to show every row.\n\t */\n\tpageSize?: number;\n\t/**\n\t * Called when the page changes.\n\t */\n\tonPageChange?: (page: number) => void;\n\t/**\n\t * Stable id for a row.\n\t */\n\tgetRowId?: (row: T, index: number) => string;\n\t/**\n\t * Additional classes for the table.\n\t */\n\tclassName?: string;\n\t/** Controlled sorting. null explicitly disables sorting. */\n\tsort?: DataTableSort | null;\n\t/** Initial sorting for uncontrolled usage. @default null */\n\tdefaultSort?: DataTableSort | null;\n\t/** Reports header sorting requests. Controlled values change only when the caller accepts. */\n\tonSortChange?: (sort: DataTableSort | null) => void;\n\t/** Caller supplies sorted rows; headers only report requests. @default false */\n\tmanualSorting?: boolean;\n\t/** Caller supplies the current page; rows are never sliced again. Use stable row IDs across pages. @default false */\n\tmanualPagination?: boolean;\n\t/** Caller supplies filtered rows; filter is not applied locally. @default false */\n\tmanualFiltering?: boolean;\n\t/** Total matching row count in manualPagination mode; defaults to data.length. */\n\ttotal?: number;\n\t/** Error content replacing rows after loading finishes. */\n\terror?: ReactNode;\n\t/** Optional retry action for an error. The caller owns the request. */\n\tonRetry?: () => void;\n\t/** Retry button text. @default \"Try again\" */\n\tretryLabel?: string;\n\t/** Accessible table name. @default \"Data table\" */\n\t\"aria-label\"?: string;\n\t/** ID of additional table instructions or summary. */\n\t\"aria-describedby\"?: string;\n};\n\nexport function DataTable<T>({\n\tdata,\n\tcolumns,\n\tfilter = \"\",\n\tloading = false,\n\tempty = \"No results\",\n\tselected,\n\tdefaultSelected,\n\tonSelectedChange,\n\tmultiple = false,\n\tpage,\n\tdefaultPage = 1,\n\tpageSize,\n\tonPageChange,\n\tgetRowId,\n\tclassName,\n\tsort: controlledSort,\n\tdefaultSort = null,\n\tonSortChange,\n\tmanualSorting = false,\n\tmanualPagination = false,\n\tmanualFiltering = false,\n\ttotal,\n\terror,\n\tonRetry,\n\tretryLabel = \"Try again\",\n\t\"aria-label\": ariaLabel = \"Data table\",\n\t\"aria-describedby\": ariaDescribedBy,\n}: DataTableProps<T>) {\n\tconst [uncontrolledSort, setUncontrolledSort] = useState<DataTableSort | null>(defaultSort);\n\tconst sort = controlledSort === undefined ? uncontrolledSort : controlledSort;\n\tconst requestSort = (next: DataTableSort) => {\n\t\tif (controlledSort === undefined) setUncontrolledSort(next);\n\t\tonSortChange?.(next);\n\t};\n\tconst [uncontrolledSelected, setUncontrolledSelected] = useState<string[]>(defaultSelected ?? []);\n\tconst [uncontrolledPage, setUncontrolledPage] = useState(defaultPage);\n\tconst rowIds = useRef(new WeakMap<object, string>());\n\tconst rowSeq = useRef(0);\n\tconst assignedKeys = useRef(new WeakMap<object, string[]>());\n\tconst lastOwner = useRef(new Map<string, object>());\n\tconst lastKeyByCanonical = useRef(new Map<string, string>());\n\tconst lastDupsByCanonical = useRef(new Map<string, string[]>());\n\tconst symbolKeys = useRef(new Map<symbol, string>());\n\tconst query = filter.trim().toLowerCase();\n\n\tconst rows = useMemo(() => {\n\t\tconst identityOf = (row: object) => {\n\t\t\tlet stored = rowIds.current.get(row);\n\t\t\tif (!stored) {\n\t\t\t\tstored = `basalt-row-${rowSeq.current++}`;\n\t\t\t\trowIds.current.set(row, stored);\n\t\t\t}\n\t\t\treturn stored;\n\t\t};\n\t\tconst canonicalOf = (row: T, index: number) => {\n\t\t\tconst requested = getRowId?.(row, index);\n\t\t\tif (requested !== undefined) {\n\t\t\t\treturn `get:${requested}`;\n\t\t\t}\n\t\t\tif (isRefRow(row) && \"id\" in row) {\n\t\t\t\tconst raw = (row as { id: unknown }).id;\n\t\t\t\tif (raw != null) {\n\t\t\t\t\treturn `id:${String(raw)}`;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst used = new Set<string>();\n\t\tconst nextLastKey = new Map<string, string>();\n\t\tconst nextDups = new Map<string, string[]>();\n\t\tconst nextAssigned = new Map<object, string[]>();\n\t\tconst nextOwner = new Map<string, object>();\n\t\tconst rememberKey = (row: T, index: number, key: string, objectRow: object | null) => {\n\t\t\tif (!objectRow) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst list = nextAssigned.get(objectRow) ?? [];\n\t\t\tlist.push(key);\n\t\t\tnextAssigned.set(objectRow, list);\n\t\t\tnextOwner.set(key, objectRow);\n\t\t\tconst canonical = canonicalOf(row, index);\n\t\t\tif (!canonical) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnextLastKey.set(canonical, key);\n\t\t\tif (isInstanceKey(key)) {\n\t\t\t\tconst dups = nextDups.get(canonical) ?? [];\n\t\t\t\tdups.push(key);\n\t\t\t\tnextDups.set(canonical, dups);\n\t\t\t}\n\t\t};\n\t\tconst counts = new WeakMap<object, number>();\n\t\tconst pending = data.map((row, index) => {\n\t\t\tconst objectRow = isRefRow(row) ? row : null;\n\t\t\tconst occurrence = objectRow ? (counts.get(objectRow) ?? 0) : 0;\n\t\t\tif (objectRow) {\n\t\t\t\tcounts.set(objectRow, occurrence + 1);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\trow,\n\t\t\t\tindex,\n\t\t\t\toccurrence,\n\t\t\t\tkey: undefined as string | undefined,\n\t\t\t};\n\t\t});\n\t\tfor (const item of pending) {\n\t\t\tconst objectRow = isRefRow(item.row) ? item.row : null;\n\t\t\tif (!objectRow) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst previous = assignedKeys.current.get(objectRow)?.[item.occurrence];\n\t\t\tif (!previous || used.has(previous)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lastOwner.current.get(previous) === objectRow) {\n\t\t\t\titem.key = previous;\n\t\t\t\tused.add(previous);\n\t\t\t}\n\t\t}\n\t\tconst keyed = pending.map(({ row, index, occurrence, key: reserved }) => {\n\t\t\tconst objectRow = isRefRow(row) ? row : null;\n\t\t\tif (reserved) {\n\t\t\t\trememberKey(row, index, reserved, objectRow);\n\t\t\t\treturn {\n\t\t\t\t\trow,\n\t\t\t\t\tkey: reserved,\n\t\t\t\t\tselectId: publicSelectId(row, index, reserved, getRowId),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst isRepeat = occurrence > 0;\n\t\t\tlet key: string | undefined;\n\t\t\tconst requested = canonicalOf(row, index);\n\t\t\tif (requested) {\n\t\t\t\tkey = requested;\n\t\t\t}\n\t\t\tif (objectRow) {\n\t\t\t\tconst stored = identityOf(objectRow);\n\t\t\t\tif (!key) {\n\t\t\t\t\tkey = isRepeat ? `gen:${stored}#${occurrence}` : `gen:${stored}`;\n\t\t\t\t} else if (used.has(key) || isRepeat) {\n\t\t\t\t\tconst reused = (lastDupsByCanonical.current.get(key) ?? []).find(\n\t\t\t\t\t\t(candidate) => !used.has(candidate),\n\t\t\t\t\t);\n\t\t\t\t\tkey = reused ?? (isRepeat ? `dup:${stored}#${occurrence}` : `dup:${stored}`);\n\t\t\t\t} else {\n\t\t\t\t\tconst inherited = lastKeyByCanonical.current.get(key);\n\t\t\t\t\tif (inherited && !used.has(inherited) && isInstanceKey(inherited)) {\n\t\t\t\t\t\tkey = inherited;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tkey = key ?? primitiveKey(row, index, symbolKeys.current, rowSeq);\n\t\t\tif (used.has(key)) {\n\t\t\t\tlet n = 0;\n\t\t\t\tlet candidate = `occ:${key}#${n}`;\n\t\t\t\twhile (used.has(candidate)) {\n\t\t\t\t\tn += 1;\n\t\t\t\t\tcandidate = `occ:${key}#${n}`;\n\t\t\t\t}\n\t\t\t\tkey = candidate;\n\t\t\t}\n\t\t\tused.add(key);\n\t\t\trememberKey(row, index, key, objectRow);\n\t\t\treturn { row, key, selectId: publicSelectId(row, index, key, getRowId) };\n\t\t});\n\t\tconst filtered =\n\t\t\tquery && !manualFiltering\n\t\t\t\t? keyed.filter(({ row }) =>\n\t\t\t\t\t\tcolumns.some((column) => filterSource(column, row).toLowerCase().includes(query)),\n\t\t\t\t\t)\n\t\t\t\t: keyed;\n\t\tconst sorted = (() => {\n\t\t\tif (!sort || manualSorting) {\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t\tconst column = columns.find((item) => item.id === sort.id);\n\t\t\tif (!column) {\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t\treturn [...filtered].sort((a, b) => {\n\t\t\t\tconst left = column.sortValue?.(a.row) ?? column.accessor(a.row);\n\t\t\t\tconst right = column.sortValue?.(b.row) ?? column.accessor(b.row);\n\t\t\t\tconst cmp = compareUnknown(left, right);\n\t\t\t\treturn sort.dir === \"asc\" ? cmp : -cmp;\n\t\t\t});\n\t\t})();\n\t\treturn {\n\t\t\trows: sorted,\n\t\t\tassigned: nextAssigned,\n\t\t\towner: nextOwner,\n\t\t\tlastKey: nextLastKey,\n\t\t\tdups: nextDups,\n\t\t};\n\t}, [columns, data, getRowId, query, sort, manualFiltering, manualSorting]);\n\n\tuseLayoutEffect(() => {\n\t\tfor (const [objectRow, keys] of rows.assigned) {\n\t\t\tassignedKeys.current.set(objectRow, keys);\n\t\t}\n\t\tlastOwner.current = rows.owner;\n\t\tlastKeyByCanonical.current = rows.lastKey;\n\t\tlastDupsByCanonical.current = rows.dups;\n\t}, [rows]);\n\n\tconst selectable =\n\t\tselected !== undefined || defaultSelected !== undefined || onSelectedChange !== undefined;\n\tconst selectedIds = selected ?? uncontrolledSelected;\n\tconst setSelectedIds = useCallback(\n\t\t(next: string[]) => {\n\t\t\tif (selected === undefined) {\n\t\t\t\tsetUncontrolledSelected(next);\n\t\t\t}\n\t\t\tonSelectedChange?.(next);\n\t\t},\n\t\t[onSelectedChange, selected],\n\t);\n\tconst rowCount = manualPagination && total !== undefined ? Math.max(0, total) : rows.rows.length;\n\tconst pageCount = pageSize && pageSize > 0 ? Math.max(1, Math.ceil(rowCount / pageSize)) : 1;\n\tconst resolvedPage = Math.min(pageCount, Math.max(1, page ?? uncontrolledPage));\n\tconst setResolvedPage = useCallback(\n\t\t(next: number) => {\n\t\t\tif (page === undefined) {\n\t\t\t\tsetUncontrolledPage(next);\n\t\t\t}\n\t\t\tonPageChange?.(next);\n\t\t},\n\t\t[onPageChange, page],\n\t);\n\tconst lastCorrection = useRef<string | null>(null);\n\tuseEffect(() => {\n\t\tconst requested = page ?? uncontrolledPage;\n\t\tif (requested === resolvedPage || loading) {\n\t\t\tlastCorrection.current = null;\n\t\t\treturn;\n\t\t}\n\t\tconst correction = `${requested}:${resolvedPage}`;\n\t\tif (lastCorrection.current !== correction) {\n\t\t\tlastCorrection.current = correction;\n\t\t\tsetResolvedPage(resolvedPage);\n\t\t}\n\t}, [page, uncontrolledPage, resolvedPage, loading, setResolvedPage]);\n\tconst paged =\n\t\t!manualPagination && pageSize && pageSize > 0\n\t\t\t? rows.rows.slice((resolvedPage - 1) * pageSize, resolvedPage * pageSize)\n\t\t\t: rows.rows;\n\tconst colCount = columns.length + (selectable ? 1 : 0);\n\tconst toggleSelected = (id: string) => {\n\t\tif (multiple) {\n\t\t\tsetSelectedIds(\n\t\t\t\tselectedIds.includes(id) ? selectedIds.filter((item) => item !== id) : [...selectedIds, id],\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tsetSelectedIds(selectedIds.includes(id) ? [] : [id]);\n\t};\n\n\treturn (\n\t\t<div className=\"flex min-w-0 flex-col gap-3\">\n\t\t\t<div\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={`${ariaLabel} scroll area`}\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveTabindex: Named overflow regions need keyboard scrolling.\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName=\"min-w-0 overflow-x-auto rounded-basalt-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-primary\"\n\t\t\t>\n\t\t\t\t<Table\n\t\t\t\t\tclassName={cn(\"w-full\", className)}\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t>\n\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t{selectable ? (\n\t\t\t\t\t\t\t\t<TableHead>\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Select</span>\n\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<TableHead\n\t\t\t\t\t\t\t\t\tkey={column.id}\n\t\t\t\t\t\t\t\t\tclassName={column.headerClassName}\n\t\t\t\t\t\t\t\t\tstyle={{ width: column.width }}\n\t\t\t\t\t\t\t\t\tscope=\"col\"\n\t\t\t\t\t\t\t\t\taria-sort={\n\t\t\t\t\t\t\t\t\t\tcolumn.sortable === false\n\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t: sort?.id === column.id\n\t\t\t\t\t\t\t\t\t\t\t\t? sort.dir === \"asc\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"ascending\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"descending\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"none\"\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{column.sortable === false ? (\n\t\t\t\t\t\t\t\t\t\t(column.headerContent ?? column.header)\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label={column.header}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"appearance-none border-0 bg-transparent p-0 font-inherit text-inherit font-medium cursor-pointer rounded-sm focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-basalt-primary\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\trequestSort(\n\t\t\t\t\t\t\t\t\t\t\t\t\tsort?.id === column.id && sort.dir === \"asc\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? { id: column.id, dir: \"desc\" }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: { id: column.id, dir: \"asc\" },\n\t\t\t\t\t\t\t\t\t\t\t\t)\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\t\t{column.headerContent ?? column.header}\n\t\t\t\t\t\t\t\t\t\t\t{sort?.id === column.id ? (sort.dir === \"asc\" ? \" ↑\" : \" ↓\") : \"\"}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t)}\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</TableRow>\n\t\t\t\t\t</TableHeader>\n\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t{loading ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div role=\"status\" className=\"flex flex-col gap-2 py-2\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Loading</span>\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t\t<SkeletonLine />\n\t\t\t\t\t\t\t\t\t</div>\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) : error != null && error !== false ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex flex-wrap items-center justify-between gap-3 py-6\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div>{error}</div>\n\t\t\t\t\t\t\t\t\t\t{onRetry ? (\n\t\t\t\t\t\t\t\t\t\t\t<Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n\t\t\t\t\t\t\t\t\t\t\t\t{retryLabel}\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</div>\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) : paged.length === 0 ? (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={colCount}>\n\t\t\t\t\t\t\t\t\t<div role=\"status\">{empty}</div>\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\t\tpaged.map(({ row, key, selectId }) => {\n\t\t\t\t\t\t\t\tconst isSelected = selectedIds.includes(selectId);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\t\tvariant={isSelected ? \"selected\" : \"default\"}\n\t\t\t\t\t\t\t\t\t\taria-selected={selectable ? isSelected : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{selectable ? (\n\t\t\t\t\t\t\t\t\t\t\t<TableCell>\n\t\t\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={isSelected}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={`Select ${selectId}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={() => toggleSelected(selectId)}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t{columns.map((column) => {\n\t\t\t\t\t\t\t\t\t\t\tconst cell = column.accessor(row);\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<TableCell key={column.id} className={column.cellClassName}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{typeof cell === \"bigint\" ? String(cell) : cell}\n\t\t\t\t\t\t\t\t\t\t\t\t</TableCell>\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</TableRow>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\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{pageSize && pageSize > 0 ? (\n\t\t\t\t<Pagination\n\t\t\t\t\tpage={resolvedPage}\n\t\t\t\t\tpageCount={pageCount}\n\t\t\t\t\tdisabled={loading}\n\t\t\t\t\tonPageChange={setResolvedPage}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ function o({ name: o, onDelete: s, errorMessage: c }) {
|
|
|
22
22
|
}) : null] }),
|
|
23
23
|
confirmLabel: "Delete",
|
|
24
24
|
onOpenChange: (e) => {
|
|
25
|
-
d
|
|
25
|
+
(!d || e) && (u(e), e || (f(!1), m(null)));
|
|
26
26
|
},
|
|
27
27
|
onConfirm: async () => {
|
|
28
28
|
f(!0), m(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete-resource.js","names":[],"sources":["../../src/components/delete-resource.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Button } from \"./button\";\nimport { ConfirmDialog } from \"./confirm-dialog\";\n\nexport type DeleteResourceErrorFormatter = (error: unknown) => React.ReactNode;\n\nexport type DeleteResourceProps = {\n\t/** Name of the resource being deleted, interpolated into dialog title and trigger label. */\n\tname: string;\n\t/** Called when deletion is confirmed. When this throws or rejects, an error alert is shown and the dialog remains open for retry. */\n\tonDelete: () => void | Promise<void>;\n\t/** Custom error message or renderer when onDelete fails. Accepts a ReactNode or an (error: unknown) => ReactNode formatter. Defaults to the caught Error message or 'Failed to delete resource. Please try again.' */\n\terrorMessage?: React.ReactNode | DeleteResourceErrorFormatter;\n};\n\nexport function DeleteResource({ name, onDelete, errorMessage }: DeleteResourceProps) {\n\tconst [open, setOpen] = React.useState(false);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst [error, setError] = React.useState<React.ReactNode | null>(null);\n\n\tconst resolveErrorMessage = (err: unknown): React.ReactNode => {\n\t\tif (typeof errorMessage === \"function\") {\n\t\t\treturn errorMessage(err);\n\t\t}\n\t\tif (errorMessage != null) {\n\t\t\treturn errorMessage;\n\t\t}\n\t\tif (err instanceof Error && err.message) {\n\t\t\treturn err.message;\n\t\t}\n\t\treturn \"Failed to delete resource. Please try again.\";\n\t};\n\n\treturn (\n\t\t<ConfirmDialog\n\t\t\ttrigger={<Button variant=\"destructive\">Delete {name}</Button>}\n\t\t\topen={open}\n\t\t\tloading={loading}\n\t\t\tvariant=\"destructive\"\n\t\t\ttitle={`Delete ${name}?`}\n\t\t\tdescription={\n\t\t\t\t<>\n\t\t\t\t\t<span>This cannot be undone.</span>\n\t\t\t\t\t{error ? (\n\t\t\t\t\t\t<span role=\"alert\" className=\"mt-2 block text-xs text-basalt-destructive\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t}\n\t\t\tconfirmLabel=\"Delete\"\n\t\t\tonOpenChange={(next) => {\n\t\t\t\tif (loading && !next) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetOpen(next);\n\t\t\t\tif (!next) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t\tsetError(null);\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonConfirm={async () => {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetError(null);\n\t\t\t\ttry {\n\t\t\t\t\tawait onDelete();\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tsetError(resolveErrorMessage(err));\n\t\t\t\t\tsetOpen(true);\n\t\t\t\t} finally {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n}\n"],"mappings":";;;;;;AAeA,SAAgB,EAAe,EAAE,SAAM,aAAU,mBAAqC;CACrF,IAAM,CAAC,GAAM,KAAW,EAAM,SAAS,EAAK,GACtC,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,CAAC,GAAO,KAAY,EAAM,SAAiC,IAAI,GAE/D,KAAuB,MACxB,OAAO,KAAiB,aACpB,EAAa,CAAG,IAEpB,MAGA,aAAe,SAAS,EAAI,UACxB,EAAI,UAEL;CAGR,OACC,kBAAC,GAAD;EACC,SAAS,kBAAC,GAAD;GAAQ,SAAQ;GAAhB,UAAA,CAA8B,WAAQ,CAAa;;EACtD;EACG;EACT,SAAQ;EACR,OAAO,UAAU,EAAK;EACtB,aACC,kBAAA,GAAA,EAAA,UAAA,CACC,kBAAC,QAAD,EAAA,UAAM,yBAA4B,CAAA,GACjC,IACA,kBAAC,QAAD;GAAM,MAAK;GAAQ,WAAU;GAC3B,UAAA;EACI,CAAA,IACH,IACH,EAAA,CAAA;EAEH,cAAa;EACb,eAAe,MAAS;GACnB,
|
|
1
|
+
{"version":3,"file":"delete-resource.js","names":[],"sources":["../../src/components/delete-resource.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Button } from \"./button\";\nimport { ConfirmDialog } from \"./confirm-dialog\";\n\nexport type DeleteResourceErrorFormatter = (error: unknown) => React.ReactNode;\n\nexport type DeleteResourceProps = {\n\t/** Name of the resource being deleted, interpolated into dialog title and trigger label. */\n\tname: string;\n\t/** Called when deletion is confirmed. When this throws or rejects, an error alert is shown and the dialog remains open for retry. */\n\tonDelete: () => void | Promise<void>;\n\t/** Custom error message or renderer when onDelete fails. Accepts a ReactNode or an (error: unknown) => ReactNode formatter. Defaults to the caught Error message or 'Failed to delete resource. Please try again.' */\n\terrorMessage?: React.ReactNode | DeleteResourceErrorFormatter;\n};\n\nexport function DeleteResource({ name, onDelete, errorMessage }: DeleteResourceProps) {\n\tconst [open, setOpen] = React.useState(false);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst [error, setError] = React.useState<React.ReactNode | null>(null);\n\n\tconst resolveErrorMessage = (err: unknown): React.ReactNode => {\n\t\tif (typeof errorMessage === \"function\") {\n\t\t\treturn errorMessage(err);\n\t\t}\n\t\tif (errorMessage != null) {\n\t\t\treturn errorMessage;\n\t\t}\n\t\tif (err instanceof Error && err.message) {\n\t\t\treturn err.message;\n\t\t}\n\t\treturn \"Failed to delete resource. Please try again.\";\n\t};\n\n\treturn (\n\t\t<ConfirmDialog\n\t\t\ttrigger={<Button variant=\"destructive\">Delete {name}</Button>}\n\t\t\topen={open}\n\t\t\tloading={loading}\n\t\t\tvariant=\"destructive\"\n\t\t\ttitle={`Delete ${name}?`}\n\t\t\tdescription={\n\t\t\t\t<>\n\t\t\t\t\t<span>This cannot be undone.</span>\n\t\t\t\t\t{error ? (\n\t\t\t\t\t\t<span role=\"alert\" className=\"mt-2 block text-xs text-basalt-destructive\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t}\n\t\t\tconfirmLabel=\"Delete\"\n\t\t\tonOpenChange={(next) => {\n\t\t\t\tif (loading && !next) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetOpen(next);\n\t\t\t\tif (!next) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t\tsetError(null);\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonConfirm={async () => {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetError(null);\n\t\t\t\ttry {\n\t\t\t\t\tawait onDelete();\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tsetError(resolveErrorMessage(err));\n\t\t\t\t\tsetOpen(true);\n\t\t\t\t} finally {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n}\n"],"mappings":";;;;;;AAeA,SAAgB,EAAe,EAAE,SAAM,aAAU,mBAAqC;CACrF,IAAM,CAAC,GAAM,KAAW,EAAM,SAAS,EAAK,GACtC,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,CAAC,GAAO,KAAY,EAAM,SAAiC,IAAI,GAE/D,KAAuB,MACxB,OAAO,KAAiB,aACpB,EAAa,CAAG,IAEpB,MAGA,aAAe,SAAS,EAAI,UACxB,EAAI,UAEL;CAGR,OACC,kBAAC,GAAD;EACC,SAAS,kBAAC,GAAD;GAAQ,SAAQ;GAAhB,UAAA,CAA8B,WAAQ,CAAa;;EACtD;EACG;EACT,SAAQ;EACR,OAAO,UAAU,EAAK;EACtB,aACC,kBAAA,GAAA,EAAA,UAAA,CACC,kBAAC,QAAD,EAAA,UAAM,yBAA4B,CAAA,GACjC,IACA,kBAAC,QAAD;GAAM,MAAK;GAAQ,WAAU;GAC3B,UAAA;EACI,CAAA,IACH,IACH,EAAA,CAAA;EAEH,cAAa;EACb,eAAe,MAAS;GACnB,OAAY,OAGhB,EAAQ,CAAI,GACP,MACJ,EAAW,EAAK,GAChB,EAAS,IAAI;EAEf;EACA,WAAW,YAAY;GAEtB,AADA,EAAW,EAAI,GACf,EAAS,IAAI;GACb,IAAI;IAEH,AADA,MAAM,EAAS,GACf,EAAQ,EAAK;GACd,SAAS,GAAK;IAEb,AADA,EAAS,EAAoB,CAAG,CAAC,GACjC,EAAQ,EAAI;GACb,UAAU;IACT,EAAW,EAAK;GACjB;EACD;CACA,CAAA;AAEH"}
|
|
@@ -9,7 +9,7 @@ import * as s from "@radix-ui/react-toggle-group";
|
|
|
9
9
|
//#region src/components/toggle-group.tsx
|
|
10
10
|
var c = i.createContext("single"), l = i.forwardRef(({ className: n, children: i, ...l }, u) => {
|
|
11
11
|
let d = l.type === "single", { ref: f, state: p, motionClassName: m } = r({
|
|
12
|
-
itemSelector: "[
|
|
12
|
+
itemSelector: "[aria-checked=\"true\"]",
|
|
13
13
|
enabled: d,
|
|
14
14
|
ref: u
|
|
15
15
|
});
|
|
@@ -38,7 +38,7 @@ var u = i.forwardRef(({ className: t, ...r }, o) => {
|
|
|
38
38
|
let l = i.useContext(c);
|
|
39
39
|
return /* @__PURE__ */ a(s.Item, {
|
|
40
40
|
ref: o,
|
|
41
|
-
className: e("relative inline-flex h-7 items-center rounded-full px-2.5 text-[11px] font-semibold tracking-wide text-basalt-muted-foreground transition-colors", "hover:text-basalt-foreground", n, "
|
|
41
|
+
className: e("relative inline-flex h-7 cursor-pointer items-center rounded-full px-2.5 text-[11px] font-semibold tracking-wide text-basalt-muted-foreground transition-colors before:absolute before:inset-0", "hover:text-basalt-foreground", n, "aria-checked:text-basalt-primary-foreground aria-pressed:text-basalt-primary-foreground", l === "multiple" && "aria-pressed:bg-basalt-primary aria-pressed:shadow-sm", "disabled:pointer-events-none disabled:opacity-50", t),
|
|
42
42
|
...r
|
|
43
43
|
});
|
|
44
44
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-group.js","names":[],"sources":["../../src/components/toggle-group.tsx"],"sourcesContent":["import * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { useSelectionIndicator } from \"../utils/selection-indicator\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst ToggleGroupMode = React.createContext<\"single\" | \"multiple\">(\"single\");\n\ntype RadixToggleGroupSingleProps = React.ComponentPropsWithoutRef<\n\ttypeof ToggleGroupPrimitive.Root\n> & { type: \"single\" };\ntype RadixToggleGroupMultipleProps = React.ComponentPropsWithoutRef<\n\ttypeof ToggleGroupPrimitive.Root\n> & { type: \"multiple\" };\ntype RadixToggleGroupItemProps = React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>;\n\nexport interface ToggleGroupSingleProps\n\textends Omit<\n\t\tRadixToggleGroupSingleProps,\n\t\t\"type\" | \"value\" | \"defaultValue\" | \"onValueChange\" | \"disabled\" | \"rovingFocus\" | \"orientation\"\n\t> {\n\t/**\n\t * Single-selection mode.\n\t */\n\ttype: \"single\";\n\t/**\n\t * Controlled string value in single mode. Root forwards ref to HTMLDivElement.\n\t */\n\tvalue?: RadixToggleGroupSingleProps[\"value\"];\n\t/**\n\t * Default string value in single mode when initially rendered.\n\t * @default \"\"\n\t */\n\tdefaultValue?: RadixToggleGroupSingleProps[\"defaultValue\"];\n\t/**\n\t * Callback invoked when single selected value changes.\n\t */\n\tonValueChange?: RadixToggleGroupSingleProps[\"onValueChange\"];\n\t/**\n\t * Whether all toggle group items are disabled.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleGroupSingleProps[\"disabled\"];\n\t/**\n\t * Whether keyboard navigation uses roving tabindex.\n\t * @default true\n\t */\n\trovingFocus?: RadixToggleGroupSingleProps[\"rovingFocus\"];\n\t/**\n\t * Constrains keyboard navigation axis; does not alter horizontal CSS layout.\n\t */\n\torientation?: RadixToggleGroupSingleProps[\"orientation\"];\n}\n\nexport interface ToggleGroupMultipleProps\n\textends Omit<\n\t\tRadixToggleGroupMultipleProps,\n\t\t\"type\" | \"value\" | \"defaultValue\" | \"onValueChange\" | \"disabled\" | \"rovingFocus\" | \"orientation\"\n\t> {\n\t/**\n\t * Multiple-selection mode.\n\t */\n\ttype: \"multiple\";\n\t/**\n\t * Controlled array in multiple mode. Root forwards ref to HTMLDivElement.\n\t */\n\tvalue?: RadixToggleGroupMultipleProps[\"value\"];\n\t/**\n\t * Default string array in multiple mode when initially rendered.\n\t * @default []\n\t */\n\tdefaultValue?: RadixToggleGroupMultipleProps[\"defaultValue\"];\n\t/**\n\t * Callback invoked when multiple selected values change.\n\t */\n\tonValueChange?: RadixToggleGroupMultipleProps[\"onValueChange\"];\n\t/**\n\t * Whether all toggle group items are disabled.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleGroupMultipleProps[\"disabled\"];\n\t/**\n\t * Whether keyboard navigation uses roving tabindex.\n\t * @default true\n\t */\n\trovingFocus?: RadixToggleGroupMultipleProps[\"rovingFocus\"];\n\t/**\n\t * Constrains keyboard navigation axis; does not alter horizontal CSS layout.\n\t */\n\torientation?: RadixToggleGroupMultipleProps[\"orientation\"];\n}\n\nexport type ToggleGroupProps = ToggleGroupSingleProps | ToggleGroupMultipleProps;\n\nexport const ToggleGroup = React.forwardRef<\n\tReact.ElementRef<typeof ToggleGroupPrimitive.Root>,\n\tToggleGroupProps\n>(({ className, children, ...props }, ref) => {\n\tconst sliding = props.type === \"single\";\n\tconst {\n\t\tref: rootRef,\n\t\tstate,\n\t\tmotionClassName,\n\t} = useSelectionIndicator({\n\t\titemSelector: '[
|
|
1
|
+
{"version":3,"file":"toggle-group.js","names":[],"sources":["../../src/components/toggle-group.tsx"],"sourcesContent":["import * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { useSelectionIndicator } from \"../utils/selection-indicator\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst ToggleGroupMode = React.createContext<\"single\" | \"multiple\">(\"single\");\n\ntype RadixToggleGroupSingleProps = React.ComponentPropsWithoutRef<\n\ttypeof ToggleGroupPrimitive.Root\n> & { type: \"single\" };\ntype RadixToggleGroupMultipleProps = React.ComponentPropsWithoutRef<\n\ttypeof ToggleGroupPrimitive.Root\n> & { type: \"multiple\" };\ntype RadixToggleGroupItemProps = React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>;\n\nexport interface ToggleGroupSingleProps\n\textends Omit<\n\t\tRadixToggleGroupSingleProps,\n\t\t\"type\" | \"value\" | \"defaultValue\" | \"onValueChange\" | \"disabled\" | \"rovingFocus\" | \"orientation\"\n\t> {\n\t/**\n\t * Single-selection mode.\n\t */\n\ttype: \"single\";\n\t/**\n\t * Controlled string value in single mode. Root forwards ref to HTMLDivElement.\n\t */\n\tvalue?: RadixToggleGroupSingleProps[\"value\"];\n\t/**\n\t * Default string value in single mode when initially rendered.\n\t * @default \"\"\n\t */\n\tdefaultValue?: RadixToggleGroupSingleProps[\"defaultValue\"];\n\t/**\n\t * Callback invoked when single selected value changes.\n\t */\n\tonValueChange?: RadixToggleGroupSingleProps[\"onValueChange\"];\n\t/**\n\t * Whether all toggle group items are disabled.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleGroupSingleProps[\"disabled\"];\n\t/**\n\t * Whether keyboard navigation uses roving tabindex.\n\t * @default true\n\t */\n\trovingFocus?: RadixToggleGroupSingleProps[\"rovingFocus\"];\n\t/**\n\t * Constrains keyboard navigation axis; does not alter horizontal CSS layout.\n\t */\n\torientation?: RadixToggleGroupSingleProps[\"orientation\"];\n}\n\nexport interface ToggleGroupMultipleProps\n\textends Omit<\n\t\tRadixToggleGroupMultipleProps,\n\t\t\"type\" | \"value\" | \"defaultValue\" | \"onValueChange\" | \"disabled\" | \"rovingFocus\" | \"orientation\"\n\t> {\n\t/**\n\t * Multiple-selection mode.\n\t */\n\ttype: \"multiple\";\n\t/**\n\t * Controlled array in multiple mode. Root forwards ref to HTMLDivElement.\n\t */\n\tvalue?: RadixToggleGroupMultipleProps[\"value\"];\n\t/**\n\t * Default string array in multiple mode when initially rendered.\n\t * @default []\n\t */\n\tdefaultValue?: RadixToggleGroupMultipleProps[\"defaultValue\"];\n\t/**\n\t * Callback invoked when multiple selected values change.\n\t */\n\tonValueChange?: RadixToggleGroupMultipleProps[\"onValueChange\"];\n\t/**\n\t * Whether all toggle group items are disabled.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleGroupMultipleProps[\"disabled\"];\n\t/**\n\t * Whether keyboard navigation uses roving tabindex.\n\t * @default true\n\t */\n\trovingFocus?: RadixToggleGroupMultipleProps[\"rovingFocus\"];\n\t/**\n\t * Constrains keyboard navigation axis; does not alter horizontal CSS layout.\n\t */\n\torientation?: RadixToggleGroupMultipleProps[\"orientation\"];\n}\n\nexport type ToggleGroupProps = ToggleGroupSingleProps | ToggleGroupMultipleProps;\n\nexport const ToggleGroup = React.forwardRef<\n\tReact.ElementRef<typeof ToggleGroupPrimitive.Root>,\n\tToggleGroupProps\n>(({ className, children, ...props }, ref) => {\n\tconst sliding = props.type === \"single\";\n\tconst {\n\t\tref: rootRef,\n\t\tstate,\n\t\tmotionClassName,\n\t} = useSelectionIndicator({\n\t\t// TooltipTrigger can also own data-state on a composed toggle.\n\t\titemSelector: '[aria-checked=\"true\"]',\n\t\tenabled: sliding,\n\t\tref,\n\t});\n\n\treturn (\n\t\t<ToggleGroupMode.Provider value={props.type}>\n\t\t\t<ToggleGroupPrimitive.Root\n\t\t\t\tref={rootRef}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\t\"relative inline-flex h-8 shrink-0 items-center gap-0.5 rounded-full bg-basalt-muted p-0.5 ring-1 ring-basalt-border/70\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{sliding ? (\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tdata-slot=\"selection-indicator\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"pointer-events-none absolute rounded-full bg-basalt-primary shadow-sm\",\n\t\t\t\t\t\t\tmotionClassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tleft: state.left,\n\t\t\t\t\t\t\twidth: state.visible ? state.width : 0,\n\t\t\t\t\t\t\ttop: state.top,\n\t\t\t\t\t\t\theight: state.visible ? state.height : 0,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t\t{children}\n\t\t\t</ToggleGroupPrimitive.Root>\n\t\t</ToggleGroupMode.Provider>\n\t);\n});\nToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;\n\nexport interface ToggleGroupItemProps\n\textends Omit<RadixToggleGroupItemProps, \"value\" | \"disabled\"> {\n\t/**\n\t * Unique item value within the group. Forwards ref to HTMLButtonElement.\n\t */\n\tvalue: RadixToggleGroupItemProps[\"value\"];\n\t/**\n\t * Whether this toggle item is disabled.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleGroupItemProps[\"disabled\"];\n}\n\nexport const ToggleGroupItem = React.forwardRef<\n\tReact.ElementRef<typeof ToggleGroupPrimitive.Item>,\n\tToggleGroupItemProps\n>(({ className, ...props }, ref) => {\n\tconst mode = React.useContext(ToggleGroupMode);\n\treturn (\n\t\t<ToggleGroupPrimitive.Item\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"relative inline-flex h-7 cursor-pointer items-center rounded-full px-2.5 text-[11px] font-semibold tracking-wide text-basalt-muted-foreground transition-colors before:absolute before:inset-0\",\n\t\t\t\t\"hover:text-basalt-foreground\",\n\t\t\t\tFOCUS_RING,\n\t\t\t\t\"aria-checked:text-basalt-primary-foreground aria-pressed:text-basalt-primary-foreground\",\n\t\t\t\tmode === \"multiple\" && \"aria-pressed:bg-basalt-primary aria-pressed:shadow-sm\",\n\t\t\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;\n"],"mappings":";;;;;;;;;AAOA,IAAM,IAAkB,EAAM,cAAqC,QAAQ,GAwF9D,IAAc,EAAM,YAG9B,EAAE,cAAW,aAAU,GAAG,KAAS,MAAQ;CAC7C,IAAM,IAAU,EAAM,SAAS,UACzB,EACL,KAAK,GACL,UACA,uBACG,EAAsB;EAEzB,cAAc;EACd,SAAS;EACT;CACD,CAAC;CAED,OACC,kBAAC,EAAgB,UAAjB;EAA0B,OAAO,EAAM;EACtC,UAAA,kBAAC,EAAqB,MAAtB;GACC,KAAK;GACL,WAAW,EACV,GACA,0HACA,CACD;GACA,GAAI;GAPL,UAAA,CASE,IACA,kBAAC,QAAD;IACC,eAAY;IACZ,aAAU;IACV,WAAW,EACV,yEACA,CACD;IACA,OAAO;KACN,MAAM,EAAM;KACZ,OAAO,EAAM,UAAU,EAAM,QAAQ;KACrC,KAAK,EAAM;KACX,QAAQ,EAAM,UAAU,EAAM,SAAS;IACxC;GACA,CAAA,IACE,MACH,CACyB;;CACF,CAAA;AAE5B,CAAC;AACD,EAAY,cAAc,EAAqB,KAAK;AAepD,IAAa,IAAkB,EAAM,YAGlC,EAAE,cAAW,GAAG,KAAS,MAAQ;CACnC,IAAM,IAAO,EAAM,WAAW,CAAe;CAC7C,OACC,kBAAC,EAAqB,MAAtB;EACM;EACL,WAAW,EACV,kMACA,gCACA,GACA,2FACA,MAAS,cAAc,yDACvB,oDACA,CACD;EACA,GAAI;CACJ,CAAA;AAEH,CAAC;AACD,EAAgB,cAAc,EAAqB,KAAK"}
|
|
@@ -7,7 +7,7 @@ import { cva as i } from "class-variance-authority";
|
|
|
7
7
|
import { jsx as a } from "react/jsx-runtime";
|
|
8
8
|
import * as o from "@radix-ui/react-toggle";
|
|
9
9
|
//#region src/components/toggle.tsx
|
|
10
|
-
var s = i(`${t} inline-flex items-center justify-center rounded-basalt-md text-sm font-medium transition-colors hover:bg-basalt-accent
|
|
10
|
+
var s = i(`${t} relative inline-flex cursor-pointer items-center justify-center rounded-basalt-md text-sm font-medium transition-colors before:absolute before:inset-0 hover:bg-basalt-accent aria-pressed:bg-basalt-accent ${n}`, {
|
|
11
11
|
variants: {
|
|
12
12
|
variant: {
|
|
13
13
|
default: "bg-basalt-muted text-basalt-foreground",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle.js","names":[],"sources":["../../src/components/toggle.tsx"],"sourcesContent":["import * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst toggleVariants = cva(\n\t`${BASALT_UI_CLASS} inline-flex items-center justify-center rounded-basalt-md text-sm font-medium transition-colors hover:bg-basalt-accent
|
|
1
|
+
{"version":3,"file":"toggle.js","names":[],"sources":["../../src/components/toggle.tsx"],"sourcesContent":["import * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst toggleVariants = cva(\n\t`${BASALT_UI_CLASS} relative inline-flex cursor-pointer items-center justify-center rounded-basalt-md text-sm font-medium transition-colors before:absolute before:inset-0 hover:bg-basalt-accent aria-pressed:bg-basalt-accent ${FOCUS_RING}`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-muted text-basalt-foreground\",\n\t\t\t\toutline: \"border border-basalt-border bg-basalt-secondary\",\n\t\t\t},\n\t\t\tsize: { default: \"h-9 px-3\", sm: \"h-8 px-2 text-xs\", lg: \"h-10 px-4\" },\n\t\t},\n\t\tdefaultVariants: { variant: \"default\", size: \"default\" },\n\t},\n);\n\ntype RadixToggleProps = React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>;\n\nexport interface ToggleProps\n\textends Omit<RadixToggleProps, \"pressed\" | \"defaultPressed\" | \"onPressedChange\" | \"disabled\">,\n\t\tOmit<VariantProps<typeof toggleVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof toggleVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof toggleVariants>[\"size\"];\n\t/**\n\t * Controlled pressed state of the toggle. Forwards ref to HTMLButtonElement.\n\t */\n\tpressed?: RadixToggleProps[\"pressed\"];\n\t/**\n\t * Uncontrolled pressed state when initially rendered.\n\t * @default false\n\t */\n\tdefaultPressed?: RadixToggleProps[\"defaultPressed\"];\n\t/**\n\t * Callback invoked when pressed state changes.\n\t */\n\tonPressedChange?: RadixToggleProps[\"onPressedChange\"];\n\t/**\n\t * Whether the toggle is disabled from user interaction.\n\t * @default false\n\t */\n\tdisabled?: RadixToggleProps[\"disabled\"];\n}\n\nexport const Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(\n\t({ className, variant, size, ...props }, ref) => (\n\t\t<TogglePrimitive.Root\n\t\t\tref={ref}\n\t\t\tclassName={cn(toggleVariants({ variant, size }), className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nToggle.displayName = TogglePrimitive.Root.displayName;\n"],"mappings":";;;;;;;;;AAOA,IAAM,IAAiB,EACtB,GAAG,EAAgB,+MAA+M,KAClO;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,SAAS;EACV;EACA,MAAM;GAAE,SAAS;GAAY,IAAI;GAAoB,IAAI;EAAY;CACtE;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAU;AACxD,CACD,GAqCa,IAAS,EAAM,YAC1B,EAAE,cAAW,YAAS,SAAM,GAAG,KAAS,MACxC,kBAAC,EAAgB,MAAjB;CACM;CACL,WAAW,EAAG,EAAe;EAAE;EAAS;CAAK,CAAC,GAAG,CAAS;CAC1D,GAAI;AACJ,CAAA,CAEH;AACA,EAAO,cAAc,EAAgB,KAAK"}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../utils/cn.js";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
3
|
+
import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
|
|
4
|
+
import { OVERLAY_LAYER as n, OVERLAY_MOTION as r } from "./overlay.js";
|
|
5
|
+
import * as i from "react";
|
|
6
|
+
import { jsx as a } from "react/jsx-runtime";
|
|
7
|
+
import * as o from "@radix-ui/react-tooltip";
|
|
7
8
|
//#region src/components/tooltip.tsx
|
|
8
|
-
var
|
|
9
|
-
forceMount:
|
|
10
|
-
children: /* @__PURE__ */
|
|
11
|
-
ref:
|
|
12
|
-
sideOffset:
|
|
13
|
-
className: e(t, n, "overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-
|
|
14
|
-
...
|
|
9
|
+
var s = o.Provider, c = o.Root, l = o.Trigger, u = i.forwardRef(({ className: i, sideOffset: s = 4, ...c }, l) => /* @__PURE__ */ a(o.Portal, {
|
|
10
|
+
forceMount: c.forceMount,
|
|
11
|
+
children: /* @__PURE__ */ a(o.Content, {
|
|
12
|
+
ref: l,
|
|
13
|
+
sideOffset: s,
|
|
14
|
+
className: e(t, n, r, "overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-2 py-1 text-xs font-normal leading-4 text-basalt-popover-foreground shadow-md", i),
|
|
15
|
+
...c
|
|
15
16
|
})
|
|
16
17
|
}));
|
|
17
|
-
|
|
18
|
+
u.displayName = o.Content.displayName;
|
|
18
19
|
//#endregion
|
|
19
|
-
export {
|
|
20
|
+
export { c as Tooltip, u as TooltipContent, s as TooltipProvider, l as TooltipTrigger };
|
|
20
21
|
|
|
21
22
|
//# sourceMappingURL=tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","names":[],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\ntype RadixTooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\ntype RadixTooltipProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;\ntype RadixTooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\ntype RadixTooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport interface TooltipProviderProps\n\textends Omit<\n\t\tRadixTooltipProviderProps,\n\t\t\"children\" | \"delayDuration\" | \"skipDelayDuration\" | \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Application or component tree wrapped by the tooltip provider context.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * Default delay before tooltips open when pointer enters a trigger, in milliseconds.\n\t * Can be overridden per tooltip instance via Tooltip.\n\t * @default 700\n\t */\n\tdelayDuration?: RadixTooltipProviderProps[\"delayDuration\"];\n\t/**\n\t * Duration in milliseconds a user has to enter another trigger without incurring the opening delay again.\n\t * @default 300\n\t */\n\tskipDelayDuration?: RadixTooltipProviderProps[\"skipDelayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * @default false\n\t */\n\tdisableHoverableContent?: RadixTooltipProviderProps[\"disableHoverableContent\"];\n}\n\nexport const TooltipProvider: React.FC<TooltipProviderProps> = TooltipPrimitive.Provider;\n\nexport interface TooltipProps\n\textends Omit<\n\t\tRadixTooltipProps,\n\t\t| \"children\"\n\t\t| \"open\"\n\t\t| \"defaultOpen\"\n\t\t| \"onOpenChange\"\n\t\t| \"delayDuration\"\n\t\t| \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Content elements rendered within the tooltip root, typically a TooltipTrigger and TooltipContent.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Controlled open state of the tooltip.\n\t */\n\topen?: RadixTooltipProps[\"open\"];\n\t/**\n\t * Uncontrolled initial open state of the tooltip.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixTooltipProps[\"defaultOpen\"];\n\t/**\n\t * Callback called when the open state changes.\n\t */\n\tonOpenChange?: RadixTooltipProps[\"onOpenChange\"];\n\t/**\n\t * Delay before the tooltip opens, in milliseconds. Overrides TooltipProvider delayDuration.\n\t * Defaults to provider value (typically 700ms).\n\t */\n\tdelayDuration?: RadixTooltipProps[\"delayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * Overrides TooltipProvider setting.\n\t */\n\tdisableHoverableContent?: RadixTooltipProps[\"disableHoverableContent\"];\n}\n\nexport const Tooltip: React.FC<TooltipProps> = TooltipPrimitive.Root;\n\nexport interface TooltipTriggerProps extends Omit<RadixTooltipTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * TooltipTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipTriggerProps[\"asChild\"];\n}\n\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport interface TooltipContentProps\n\textends Omit<\n\t\tRadixTooltipContentProps,\n\t\t| \"aria-label\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * A more descriptive accessible label announced by screen readers.\n\t */\n\t\"aria-label\"?: RadixTooltipContentProps[\"aria-label\"];\n\t/**\n\t * Callback fired when the Escape key is down on the tooltip content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixTooltipContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the tooltip. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixTooltipContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"top\"\n\t */\n\tside?: RadixTooltipContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * @default 4\n\t */\n\tsideOffset?: RadixTooltipContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixTooltipContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixTooltipContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixTooltipContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixTooltipContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixTooltipContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixTooltipContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixTooltipContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixTooltipContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixTooltipContentProps[\"updatePositionStrategy\"];\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 */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * TooltipContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipContentProps[\"asChild\"];\n}\n\nexport const TooltipContent = React.forwardRef<\n\tReact.ElementRef<typeof TooltipPrimitive.Content>,\n\tTooltipContentProps\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<TooltipPrimitive.Portal forceMount={props.forceMount}>\n\t\t<TooltipPrimitive.Content\n\t\t\tref={ref}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\"overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\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\ntype RadixTooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\ntype RadixTooltipProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;\ntype RadixTooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\ntype RadixTooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport interface TooltipProviderProps\n\textends Omit<\n\t\tRadixTooltipProviderProps,\n\t\t\"children\" | \"delayDuration\" | \"skipDelayDuration\" | \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Application or component tree wrapped by the tooltip provider context.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * Default delay before tooltips open when pointer enters a trigger, in milliseconds.\n\t * Can be overridden per tooltip instance via Tooltip.\n\t * @default 700\n\t */\n\tdelayDuration?: RadixTooltipProviderProps[\"delayDuration\"];\n\t/**\n\t * Duration in milliseconds a user has to enter another trigger without incurring the opening delay again.\n\t * @default 300\n\t */\n\tskipDelayDuration?: RadixTooltipProviderProps[\"skipDelayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * @default false\n\t */\n\tdisableHoverableContent?: RadixTooltipProviderProps[\"disableHoverableContent\"];\n}\n\nexport const TooltipProvider: React.FC<TooltipProviderProps> = TooltipPrimitive.Provider;\n\nexport interface TooltipProps\n\textends Omit<\n\t\tRadixTooltipProps,\n\t\t| \"children\"\n\t\t| \"open\"\n\t\t| \"defaultOpen\"\n\t\t| \"onOpenChange\"\n\t\t| \"delayDuration\"\n\t\t| \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Content elements rendered within the tooltip root, typically a TooltipTrigger and TooltipContent.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Controlled open state of the tooltip.\n\t */\n\topen?: RadixTooltipProps[\"open\"];\n\t/**\n\t * Uncontrolled initial open state of the tooltip.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixTooltipProps[\"defaultOpen\"];\n\t/**\n\t * Callback called when the open state changes.\n\t */\n\tonOpenChange?: RadixTooltipProps[\"onOpenChange\"];\n\t/**\n\t * Delay before the tooltip opens, in milliseconds. Overrides TooltipProvider delayDuration.\n\t * Defaults to provider value (typically 700ms).\n\t */\n\tdelayDuration?: RadixTooltipProps[\"delayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * Overrides TooltipProvider setting.\n\t */\n\tdisableHoverableContent?: RadixTooltipProps[\"disableHoverableContent\"];\n}\n\nexport const Tooltip: React.FC<TooltipProps> = TooltipPrimitive.Root;\n\nexport interface TooltipTriggerProps extends Omit<RadixTooltipTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * TooltipTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipTriggerProps[\"asChild\"];\n}\n\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport interface TooltipContentProps\n\textends Omit<\n\t\tRadixTooltipContentProps,\n\t\t| \"aria-label\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * A more descriptive accessible label announced by screen readers.\n\t */\n\t\"aria-label\"?: RadixTooltipContentProps[\"aria-label\"];\n\t/**\n\t * Callback fired when the Escape key is down on the tooltip content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixTooltipContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the tooltip. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixTooltipContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"top\"\n\t */\n\tside?: RadixTooltipContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * @default 4\n\t */\n\tsideOffset?: RadixTooltipContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixTooltipContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixTooltipContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixTooltipContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixTooltipContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixTooltipContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixTooltipContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixTooltipContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixTooltipContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixTooltipContentProps[\"updatePositionStrategy\"];\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 */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * TooltipContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipContentProps[\"asChild\"];\n}\n\nexport const TooltipContent = React.forwardRef<\n\tReact.ElementRef<typeof TooltipPrimitive.Content>,\n\tTooltipContentProps\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<TooltipPrimitive.Portal forceMount={props.forceMount}>\n\t\t<TooltipPrimitive.Content\n\t\t\tref={ref}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\"overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-2 py-1 text-xs font-normal leading-4 text-basalt-popover-foreground shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</TooltipPrimitive.Portal>\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n"],"mappings":";;;;;;;;AAsCA,IAAa,IAAkD,EAAiB,UAyCnE,IAAkC,EAAiB,MAWnD,IAAiB,EAAiB,SAuGlC,IAAiB,EAAM,YAGjC,EAAE,cAAW,gBAAa,GAAG,GAAG,KAAS,MAC3C,kBAAC,EAAiB,QAAlB;CAAyB,YAAY,EAAM;CAC1C,UAAA,kBAAC,EAAiB,SAAlB;EACM;EACO;EACZ,WAAW,EACV,GACA,GACA,GACA,oKACA,CACD;EACA,GAAI;CACJ,CAAA;AACuB,CAAA,CACzB;AACD,EAAe,cAAc,EAAiB,QAAQ"}
|
|
@@ -1688,6 +1688,10 @@
|
|
|
1688
1688
|
.text-\[13px\] {
|
|
1689
1689
|
font-size: 13px;
|
|
1690
1690
|
}
|
|
1691
|
+
.leading-4 {
|
|
1692
|
+
--tw-leading: calc(var(--spacing) * 4);
|
|
1693
|
+
line-height: calc(var(--spacing) * 4);
|
|
1694
|
+
}
|
|
1691
1695
|
.leading-5 {
|
|
1692
1696
|
--tw-leading: calc(var(--spacing) * 5);
|
|
1693
1697
|
line-height: calc(var(--spacing) * 5);
|
|
@@ -2014,6 +2018,14 @@
|
|
|
2014
2018
|
.placeholder\:text-basalt-muted-foreground::placeholder {
|
|
2015
2019
|
color: hsl(var(--basalt-muted-foreground));
|
|
2016
2020
|
}
|
|
2021
|
+
.before\:absolute::before {
|
|
2022
|
+
content: var(--tw-content);
|
|
2023
|
+
position: absolute;
|
|
2024
|
+
}
|
|
2025
|
+
.before\:inset-0::before {
|
|
2026
|
+
content: var(--tw-content);
|
|
2027
|
+
inset: 0px;
|
|
2028
|
+
}
|
|
2017
2029
|
.first\:rounded-l-basalt-md:first-child {
|
|
2018
2030
|
border-top-left-radius: calc(var(--basalt-radius) - 2px);
|
|
2019
2031
|
border-bottom-left-radius: calc(var(--basalt-radius) - 2px);
|
|
@@ -2214,6 +2226,12 @@
|
|
|
2214
2226
|
.disabled\:opacity-100:disabled {
|
|
2215
2227
|
opacity: 100%;
|
|
2216
2228
|
}
|
|
2229
|
+
.aria-checked\:text-basalt-primary-foreground[aria-checked="true"] {
|
|
2230
|
+
color: hsl(var(--basalt-primary-foreground));
|
|
2231
|
+
}
|
|
2232
|
+
.aria-disabled\:cursor-not-allowed[aria-disabled="true"] {
|
|
2233
|
+
cursor: not-allowed;
|
|
2234
|
+
}
|
|
2217
2235
|
.aria-disabled\:opacity-50[aria-disabled="true"] {
|
|
2218
2236
|
opacity: 50%;
|
|
2219
2237
|
}
|
|
@@ -2223,6 +2241,19 @@
|
|
|
2223
2241
|
.aria-invalid\:focus-visible\:border-basalt-destructive[aria-invalid="true"]:focus-visible {
|
|
2224
2242
|
border-color: hsl(var(--basalt-destructive));
|
|
2225
2243
|
}
|
|
2244
|
+
.aria-pressed\:bg-basalt-accent[aria-pressed="true"] {
|
|
2245
|
+
background-color: hsl(var(--basalt-accent));
|
|
2246
|
+
}
|
|
2247
|
+
.aria-pressed\:bg-basalt-primary[aria-pressed="true"] {
|
|
2248
|
+
background-color: hsl(var(--basalt-primary));
|
|
2249
|
+
}
|
|
2250
|
+
.aria-pressed\:text-basalt-primary-foreground[aria-pressed="true"] {
|
|
2251
|
+
color: hsl(var(--basalt-primary-foreground));
|
|
2252
|
+
}
|
|
2253
|
+
.aria-pressed\:shadow-sm[aria-pressed="true"] {
|
|
2254
|
+
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
2255
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2256
|
+
}
|
|
2226
2257
|
.data-disabled\:pointer-events-none[data-disabled] {
|
|
2227
2258
|
pointer-events: none;
|
|
2228
2259
|
}
|
|
@@ -2287,19 +2318,6 @@
|
|
|
2287
2318
|
.data-\[state\=indeterminate\]\:text-basalt-primary-foreground[data-state="indeterminate"] {
|
|
2288
2319
|
color: hsl(var(--basalt-primary-foreground));
|
|
2289
2320
|
}
|
|
2290
|
-
.data-\[state\=on\]\:bg-basalt-accent[data-state="on"] {
|
|
2291
|
-
background-color: hsl(var(--basalt-accent));
|
|
2292
|
-
}
|
|
2293
|
-
.data-\[state\=on\]\:bg-basalt-primary[data-state="on"] {
|
|
2294
|
-
background-color: hsl(var(--basalt-primary));
|
|
2295
|
-
}
|
|
2296
|
-
.data-\[state\=on\]\:text-basalt-primary-foreground[data-state="on"] {
|
|
2297
|
-
color: hsl(var(--basalt-primary-foreground));
|
|
2298
|
-
}
|
|
2299
|
-
.data-\[state\=on\]\:shadow-sm[data-state="on"] {
|
|
2300
|
-
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
2301
|
-
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2302
|
-
}
|
|
2303
2321
|
.data-\[state\=open\]\:animate-basalt-collapsible-down[data-state="open"] {
|
|
2304
2322
|
animation: basalt-collapsible-down 150ms ease-out;
|
|
2305
2323
|
}
|
|
@@ -3010,6 +3028,11 @@
|
|
|
3010
3028
|
syntax: "*";
|
|
3011
3029
|
inherits: false;
|
|
3012
3030
|
}
|
|
3031
|
+
@property --tw-content {
|
|
3032
|
+
syntax: "*";
|
|
3033
|
+
initial-value: "";
|
|
3034
|
+
inherits: false;
|
|
3035
|
+
}
|
|
3013
3036
|
@layer properties {
|
|
3014
3037
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
3015
3038
|
*, ::before, ::after, ::backdrop {
|
|
@@ -3079,6 +3102,7 @@
|
|
|
3079
3102
|
--tw-backdrop-sepia: initial;
|
|
3080
3103
|
--tw-duration: initial;
|
|
3081
3104
|
--tw-ease: initial;
|
|
3105
|
+
--tw-content: "";
|
|
3082
3106
|
}
|
|
3083
3107
|
}
|
|
3084
3108
|
}
|
|
@@ -92,7 +92,7 @@ function s({ itemSelector: s, enabled: c = !0, mapGeometry: l, ref: u }) {
|
|
|
92
92
|
subtree: !0,
|
|
93
93
|
childList: !0,
|
|
94
94
|
characterData: !0,
|
|
95
|
-
attributeFilter: ["data-state"]
|
|
95
|
+
attributeFilter: ["data-state", "aria-checked"]
|
|
96
96
|
}), () => {
|
|
97
97
|
cancelAnimationFrame(t), i.disconnect(), n.disconnect();
|
|
98
98
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-indicator.js","names":[],"sources":["../../src/utils/selection-indicator.ts"],"sourcesContent":["import * as React from \"react\";\n\nexport const SELECTION_INDICATOR_MOTION_CLASS =\n\t\"transition-[left,width,top,height] duration-200 ease-out\";\n\nexport type SelectionGeometry = {\n\tleft: number;\n\twidth: number;\n\ttop: number;\n\theight: number;\n};\n\nexport type SelectionIndicatorState = SelectionGeometry & {\n\tvisible: boolean;\n\tanimated: boolean;\n};\n\nconst EMPTY: SelectionGeometry = { left: 0, width: 0, top: 0, height: 0 };\n\nexport function assignRef<T>(ref: React.Ref<T> | undefined, value: T | null) {\n\tif (typeof ref === \"function\") {\n\t\tref(value);\n\t} else if (ref) {\n\t\t(ref as React.MutableRefObject<T | null>).current = value;\n\t}\n}\n\nexport function measureSelectionItem(item: HTMLElement): SelectionGeometry {\n\treturn {\n\t\tleft: item.offsetLeft,\n\t\twidth: item.offsetWidth,\n\t\ttop: item.offsetTop,\n\t\theight: item.offsetHeight,\n\t};\n}\n\nfunction prefersReducedMotion() {\n\treturn (\n\t\ttypeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n\t);\n}\n\nfunction selectionTargets(root: HTMLElement) {\n\tconst targets: HTMLElement[] = [root];\n\tfor (const node of root.children) {\n\t\tif (node instanceof HTMLElement && node.getAttribute(\"aria-hidden\") !== \"true\") {\n\t\t\ttargets.push(node);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function useSelectionIndicator({\n\titemSelector,\n\tenabled = true,\n\tmapGeometry,\n\tref,\n}: {\n\titemSelector: string;\n\tenabled?: boolean;\n\tmapGeometry?: (item: HTMLElement, root: HTMLElement) => SelectionGeometry;\n\tref?: React.Ref<HTMLElement | null>;\n}) {\n\tconst rootRef = React.useRef<HTMLElement | null>(null);\n\tconst composedRef = React.useMemo(() => {\n\t\treturn (node: HTMLElement | null) => {\n\t\t\trootRef.current = node;\n\t\t\tassignRef(ref, node);\n\t\t};\n\t}, [ref]);\n\tconst [state, setState] = React.useState<SelectionIndicatorState>({\n\t\t...EMPTY,\n\t\tvisible: false,\n\t\tanimated: false,\n\t});\n\tconst [reduced, setReduced] = React.useState(prefersReducedMotion);\n\n\tReact.useEffect(() => {\n\t\tconst media = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n\t\tconst onChange = () => setReduced(media.matches);\n\t\tonChange();\n\t\tmedia.addEventListener(\"change\", onChange);\n\t\treturn () => media.removeEventListener(\"change\", onChange);\n\t}, []);\n\n\tconst sync = React.useCallback(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root || !enabled) {\n\t\t\tsetState((current) => ({ ...current, ...EMPTY, visible: false, animated: false }));\n\t\t\treturn;\n\t\t}\n\t\tconst item = root.querySelector<HTMLElement>(itemSelector);\n\t\tif (!item) {\n\t\t\tsetState((current) => ({ ...current, width: 0, height: 0, visible: false, animated: false }));\n\t\t\treturn;\n\t\t}\n\t\t// Keep the optional dependency undefined. Production optimizers may inline a\n\t\t// function-valued parameter default, creating a new effect dependency every render.\n\t\tconst geometry = (mapGeometry ?? measureSelectionItem)(item, root);\n\t\tsetState((current) => ({\n\t\t\t...geometry,\n\t\t\tvisible: true,\n\t\t\tanimated: current.visible && !reduced,\n\t\t}));\n\t}, [enabled, itemSelector, mapGeometry, reduced]);\n\n\tReact.useLayoutEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root || !enabled) {\n\t\t\treturn;\n\t\t}\n\t\tlet frame = 0;\n\t\tconst ro = new ResizeObserver(() => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tframe = requestAnimationFrame(sync);\n\t\t});\n\t\tconst observe = () => {\n\t\t\tro.disconnect();\n\t\t\tfor (const node of selectionTargets(root)) {\n\t\t\t\tro.observe(node);\n\t\t\t}\n\t\t};\n\t\tobserve();\n\t\tsync();\n\t\tconst mo = new MutationObserver(() => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tframe = requestAnimationFrame(() => {\n\t\t\t\tobserve();\n\t\t\t\tsync();\n\t\t\t});\n\t\t});\n\t\tmo.observe(root, {\n\t\t\tattributes: true,\n\t\t\tsubtree: true,\n\t\t\tchildList: true,\n\t\t\tcharacterData: true,\n\t\t\tattributeFilter: [\"data-state\"],\n\t\t});\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tmo.disconnect();\n\t\t\tro.disconnect();\n\t\t};\n\t}, [enabled, sync]);\n\n\treturn {\n\t\tref: composedRef,\n\t\tstate,\n\t\tmotionClassName: state.animated && !reduced ? SELECTION_INDICATOR_MOTION_CLASS : undefined,\n\t};\n}\n"],"mappings":";;;AAEA,IAAa,IACZ,4DAcK,IAA2B;CAAE,MAAM;CAAG,OAAO;CAAG,KAAK;CAAG,QAAQ;AAAE;AAExE,SAAgB,EAAa,GAA+B,GAAiB;CAC5E,AAAI,OAAO,KAAQ,aAClB,EAAI,CAAK,IACC,MACV,EAA0C,UAAU;AAEtD;AAEA,SAAgB,EAAqB,GAAsC;CAC1E,OAAO;EACN,MAAM,EAAK;EACX,OAAO,EAAK;EACZ,KAAK,EAAK;EACV,QAAQ,EAAK;CACd;AACD;AAEA,SAAS,IAAuB;CAC/B,OACC,OAAO,SAAW,OAAe,OAAO,WAAW,kCAAkC,CAAC,CAAC;AAEzF;AAEA,SAAS,EAAiB,GAAmB;CAC5C,IAAM,IAAyB,CAAC,CAAI;CACpC,KAAK,IAAM,KAAQ,EAAK,UACvB,AAAI,aAAgB,eAAe,EAAK,aAAa,aAAa,MAAM,UACvE,EAAQ,KAAK,CAAI;CAGnB,OAAO;AACR;AAEA,SAAgB,EAAsB,EACrC,iBACA,aAAU,IACV,gBACA,UAME;CACF,IAAM,IAAU,EAAM,OAA2B,IAAI,GAC/C,IAAc,EAAM,eACjB,MAA6B;EAEpC,AADA,EAAQ,UAAU,GAClB,EAAU,GAAK,CAAI;CACpB,GACE,CAAC,CAAG,CAAC,GACF,CAAC,GAAO,KAAY,EAAM,SAAkC;EACjE,GAAG;EACH,SAAS;EACT,UAAU;CACX,CAAC,GACK,CAAC,GAAS,KAAc,EAAM,SAAS,CAAoB;CAEjE,EAAM,gBAAgB;EACrB,IAAM,IAAQ,OAAO,WAAW,kCAAkC,GAC5D,UAAiB,EAAW,EAAM,OAAO;EAG/C,OAFA,EAAS,GACT,EAAM,iBAAiB,UAAU,CAAQ,SAC5B,EAAM,oBAAoB,UAAU,CAAQ;CAC1D,GAAG,CAAC,CAAC;CAEL,IAAM,IAAO,EAAM,kBAAkB;EACpC,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAQ,CAAC,GAAS;GACtB,GAAU,OAAa;IAAE,GAAG;IAAS,GAAG;IAAO,SAAS;IAAO,UAAU;GAAM,EAAE;GACjF;EACD;EACA,IAAM,IAAO,EAAK,cAA2B,CAAY;EACzD,IAAI,CAAC,GAAM;GACV,GAAU,OAAa;IAAE,GAAG;IAAS,OAAO;IAAG,QAAQ;IAAG,SAAS;IAAO,UAAU;GAAM,EAAE;GAC5F;EACD;EAGA,IAAM,KAAY,KAAe,EAAA,CAAsB,GAAM,CAAI;EACjE,GAAU,OAAa;GACtB,GAAG;GACH,SAAS;GACT,UAAU,EAAQ,WAAW,CAAC;EAC/B,EAAE;CACH,GAAG;EAAC;EAAS;EAAc;EAAa;CAAO,CAAC;CAyChD,OAvCA,EAAM,sBAAsB;EAC3B,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAQ,CAAC,GACb;EAED,IAAI,IAAQ,GACN,IAAK,IAAI,qBAAqB;GAEnC,AADA,qBAAqB,CAAK,GAC1B,IAAQ,sBAAsB,CAAI;EACnC,CAAC,GACK,UAAgB;GACrB,EAAG,WAAW;GACd,KAAK,IAAM,KAAQ,EAAiB,CAAI,GACvC,EAAG,QAAQ,CAAI;EAEjB;EAEA,AADA,EAAQ,GACR,EAAK;EACL,IAAM,IAAK,IAAI,uBAAuB;GAErC,AADA,qBAAqB,CAAK,GAC1B,IAAQ,4BAA4B;IAEnC,AADA,EAAQ,GACR,EAAK;GACN,CAAC;EACF,CAAC;EAQD,OAPA,EAAG,QAAQ,GAAM;GAChB,YAAY;GACZ,SAAS;GACT,WAAW;GACX,eAAe;GACf,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"selection-indicator.js","names":[],"sources":["../../src/utils/selection-indicator.ts"],"sourcesContent":["import * as React from \"react\";\n\nexport const SELECTION_INDICATOR_MOTION_CLASS =\n\t\"transition-[left,width,top,height] duration-200 ease-out\";\n\nexport type SelectionGeometry = {\n\tleft: number;\n\twidth: number;\n\ttop: number;\n\theight: number;\n};\n\nexport type SelectionIndicatorState = SelectionGeometry & {\n\tvisible: boolean;\n\tanimated: boolean;\n};\n\nconst EMPTY: SelectionGeometry = { left: 0, width: 0, top: 0, height: 0 };\n\nexport function assignRef<T>(ref: React.Ref<T> | undefined, value: T | null) {\n\tif (typeof ref === \"function\") {\n\t\tref(value);\n\t} else if (ref) {\n\t\t(ref as React.MutableRefObject<T | null>).current = value;\n\t}\n}\n\nexport function measureSelectionItem(item: HTMLElement): SelectionGeometry {\n\treturn {\n\t\tleft: item.offsetLeft,\n\t\twidth: item.offsetWidth,\n\t\ttop: item.offsetTop,\n\t\theight: item.offsetHeight,\n\t};\n}\n\nfunction prefersReducedMotion() {\n\treturn (\n\t\ttypeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n\t);\n}\n\nfunction selectionTargets(root: HTMLElement) {\n\tconst targets: HTMLElement[] = [root];\n\tfor (const node of root.children) {\n\t\tif (node instanceof HTMLElement && node.getAttribute(\"aria-hidden\") !== \"true\") {\n\t\t\ttargets.push(node);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function useSelectionIndicator({\n\titemSelector,\n\tenabled = true,\n\tmapGeometry,\n\tref,\n}: {\n\titemSelector: string;\n\tenabled?: boolean;\n\tmapGeometry?: (item: HTMLElement, root: HTMLElement) => SelectionGeometry;\n\tref?: React.Ref<HTMLElement | null>;\n}) {\n\tconst rootRef = React.useRef<HTMLElement | null>(null);\n\tconst composedRef = React.useMemo(() => {\n\t\treturn (node: HTMLElement | null) => {\n\t\t\trootRef.current = node;\n\t\t\tassignRef(ref, node);\n\t\t};\n\t}, [ref]);\n\tconst [state, setState] = React.useState<SelectionIndicatorState>({\n\t\t...EMPTY,\n\t\tvisible: false,\n\t\tanimated: false,\n\t});\n\tconst [reduced, setReduced] = React.useState(prefersReducedMotion);\n\n\tReact.useEffect(() => {\n\t\tconst media = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n\t\tconst onChange = () => setReduced(media.matches);\n\t\tonChange();\n\t\tmedia.addEventListener(\"change\", onChange);\n\t\treturn () => media.removeEventListener(\"change\", onChange);\n\t}, []);\n\n\tconst sync = React.useCallback(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root || !enabled) {\n\t\t\tsetState((current) => ({ ...current, ...EMPTY, visible: false, animated: false }));\n\t\t\treturn;\n\t\t}\n\t\tconst item = root.querySelector<HTMLElement>(itemSelector);\n\t\tif (!item) {\n\t\t\tsetState((current) => ({ ...current, width: 0, height: 0, visible: false, animated: false }));\n\t\t\treturn;\n\t\t}\n\t\t// Keep the optional dependency undefined. Production optimizers may inline a\n\t\t// function-valued parameter default, creating a new effect dependency every render.\n\t\tconst geometry = (mapGeometry ?? measureSelectionItem)(item, root);\n\t\tsetState((current) => ({\n\t\t\t...geometry,\n\t\t\tvisible: true,\n\t\t\tanimated: current.visible && !reduced,\n\t\t}));\n\t}, [enabled, itemSelector, mapGeometry, reduced]);\n\n\tReact.useLayoutEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root || !enabled) {\n\t\t\treturn;\n\t\t}\n\t\tlet frame = 0;\n\t\tconst ro = new ResizeObserver(() => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tframe = requestAnimationFrame(sync);\n\t\t});\n\t\tconst observe = () => {\n\t\t\tro.disconnect();\n\t\t\tfor (const node of selectionTargets(root)) {\n\t\t\t\tro.observe(node);\n\t\t\t}\n\t\t};\n\t\tobserve();\n\t\tsync();\n\t\tconst mo = new MutationObserver(() => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tframe = requestAnimationFrame(() => {\n\t\t\t\tobserve();\n\t\t\t\tsync();\n\t\t\t});\n\t\t});\n\t\tmo.observe(root, {\n\t\t\tattributes: true,\n\t\t\tsubtree: true,\n\t\t\tchildList: true,\n\t\t\tcharacterData: true,\n\t\t\tattributeFilter: [\"data-state\", \"aria-checked\"],\n\t\t});\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tmo.disconnect();\n\t\t\tro.disconnect();\n\t\t};\n\t}, [enabled, sync]);\n\n\treturn {\n\t\tref: composedRef,\n\t\tstate,\n\t\tmotionClassName: state.animated && !reduced ? SELECTION_INDICATOR_MOTION_CLASS : undefined,\n\t};\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocoo/basalt",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"clsx": "^2.1.1",
|
|
82
82
|
"cmdk": "^1.1.1",
|
|
83
83
|
"sonner": "2.0.8",
|
|
84
|
-
"tailwind-merge": "3.
|
|
84
|
+
"tailwind-merge": "3.7.0"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
87
|
"react": "^19",
|