@labpane/ui 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -2
- package/dist/LICENSE +21 -0
- package/dist/chunk-3ZY2AVB4.js +434 -0
- package/dist/chunk-3ZY2AVB4.js.map +7 -0
- package/dist/index.js +918 -0
- package/dist/index.js.map +7 -0
- package/dist/styles.css +2 -0
- package/dist/styles.d.ts +1 -0
- package/dist/terminal.js +369 -0
- package/dist/terminal.js.map +7 -0
- package/dist/ui/app-menu.d.ts +14 -0
- package/dist/ui/classes.d.ts +2 -0
- package/dist/ui/dialog.d.ts +27 -0
- package/dist/ui/form-fields.d.ts +21 -0
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/menu.d.ts +33 -0
- package/dist/ui/primitives.d.ts +85 -0
- package/dist/ui/table.d.ts +30 -0
- package/dist/ui/terminal.d.ts +57 -0
- package/package.json +99 -4
- package/styles.css +235 -0
package/README.md
CHANGED
|
@@ -1,3 +1,116 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @labpane/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Page layouts, forms, dialogs, menus, tables, and an optional terminal for React, built on Radix. It pairs with [`@labpane/os`](../os) but works on its own.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @labpane/ui @radix-ui/react-alert-dialog @radix-ui/react-checkbox @radix-ui/react-context-menu @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-slot
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@labpane/ui/styles.css";
|
|
11
|
+
import { Button, Page } from "@labpane/ui";
|
|
12
|
+
|
|
13
|
+
export function Settings() {
|
|
14
|
+
return (
|
|
15
|
+
<Page title="Settings" actions={<Button>Save</Button>}>
|
|
16
|
+
…
|
|
17
|
+
</Page>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Radix and React are peer dependencies, so your app keeps one copy of each. The stylesheet is built with Tailwind 4 but needs no Tailwind in your app: every class is prefixed `labui:`, nothing is global, and it builds in Tailwind 3 PostCSS pipelines too.
|
|
23
|
+
|
|
24
|
+
## Components
|
|
25
|
+
|
|
26
|
+
| | |
|
|
27
|
+
| --------- | ------------------------------------------------------------------------------------------------------------ |
|
|
28
|
+
| Pages | `Page`, `PageHeader`, `PageActions`, `Back` |
|
|
29
|
+
| Controls | `Button`, `Badge`, `Input`, `Checkbox`, `Select` and its parts, `Spinner`, `Skeleton`, `CopyButton`, `Alert` |
|
|
30
|
+
| Forms | `Field`, `FieldLabel`, `FieldError`, `TextField`, `SelectField`, `AddButton` |
|
|
31
|
+
| Dialogs | `Dialog` and its parts, `ConfirmDialog`, `DiscardDialog` |
|
|
32
|
+
| Menus | `OptionMenu`, `ActionMenu`, `MenuContent` |
|
|
33
|
+
| Tables | `Table`, `column`, `mono`, `num` |
|
|
34
|
+
| Workspace | `AppMenu`: logo menu with theme, size, and full-screen controls |
|
|
35
|
+
|
|
36
|
+
`cn()` merges class names and lets your own Tailwind classes override the `labui:` defaults they conflict with.
|
|
37
|
+
|
|
38
|
+
Tailwind 4 apps can also write their own `labui:` classes on the same theme by importing ui's Tailwind source instead of the built stylesheet:
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
@import "@labpane/ui/tailwind.css";
|
|
42
|
+
@source "./src";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## With @labpane/os
|
|
46
|
+
|
|
47
|
+
Fill the workspace's slots with ui's menus and dialog:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<Workspace
|
|
51
|
+
{...workspaceProps}
|
|
52
|
+
toolbar={(pane) => (
|
|
53
|
+
<OptionMenu
|
|
54
|
+
options={[{ id: "reports", label: "Reports" }]}
|
|
55
|
+
onSelect={openTab}
|
|
56
|
+
trigger={
|
|
57
|
+
<Button size="icon-sm" aria-label="Open a tab">
|
|
58
|
+
+
|
|
59
|
+
</Button>
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
menu={(target, actions, restoreFocus) => (
|
|
64
|
+
<ActionMenu
|
|
65
|
+
actions={actions}
|
|
66
|
+
onCloseAutoFocus={
|
|
67
|
+
restoreFocus &&
|
|
68
|
+
((event) => {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
restoreFocus();
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
{target}
|
|
75
|
+
</ActionMenu>
|
|
76
|
+
)}
|
|
77
|
+
confirmClose={(tab) => askToDiscard(tab.label)}
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`askToDiscard` returns a promise that a `DiscardDialog` resolves with the user's choice. Action menu items can hold `items` for a submenu, or `checked` for a check mark.
|
|
82
|
+
|
|
83
|
+
## Terminal
|
|
84
|
+
|
|
85
|
+
`@labpane/ui/terminal` is a separate entry point, so apps that don't import it never load the terminal. It needs [`@wterm/dom`](https://wterm.dev):
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm install @wterm/dom
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import "@wterm/dom/css";
|
|
93
|
+
import { Terminal } from "@labpane/ui/terminal";
|
|
94
|
+
|
|
95
|
+
<Terminal connect={() => "/pty"} expandable />;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`connect` returns the URL of a WebSocket that streams the terminal: binary frames carry input and output, text frames carry error messages, and resizes arrive as JSON `{ cols, rows }`. Instead of `connect`, `shell` runs an in-browser shell such as `BashShell` from `@wterm/just-bash`. `core` swaps in another terminal engine, such as `GhosttyCore` from `@wterm/ghostty`, and `theme` picks one of `terminalThemes` or `"auto"`.
|
|
99
|
+
|
|
100
|
+
## Theming
|
|
101
|
+
|
|
102
|
+
Set these on `:root`, or on any ancestor. Add a `dark` class to an ancestor for the dark defaults.
|
|
103
|
+
|
|
104
|
+
```css
|
|
105
|
+
:root {
|
|
106
|
+
--labui-primary: #05697a;
|
|
107
|
+
--labui-radius: 0.75rem;
|
|
108
|
+
--labui-font-sans: inherit;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Colours: `background`, `foreground`, `card`, `popover`, `primary`, `secondary`, `muted`, `accent`, `destructive`, `success`, and `warning`, each with a `-foreground` pair where it applies, plus `link`, `border`, `input`, `input-background`, `ring`, `overlay`, and `destructive-muted`. Fonts: `font-sans`, `font-mono`, and `font-display`. Sizes: `radius`, `radius-dialog`, `control-height`, `control-height-sm`, `control-px`, and `row-py`. Each is a `--labui-` variable.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
package/dist/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Authors of Labpane
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
// classes.ts
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
4
|
+
var twMerge = extendTailwindMerge({
|
|
5
|
+
experimentalParseClassName: ({ className, parseClassName }) => parseClassName(className.replace(/^labui:/, ""))
|
|
6
|
+
});
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// primitives.tsx
|
|
12
|
+
import * as React from "react";
|
|
13
|
+
import {
|
|
14
|
+
ArrowLeftIcon,
|
|
15
|
+
CheckIcon,
|
|
16
|
+
ChevronDownIcon,
|
|
17
|
+
CopyIcon,
|
|
18
|
+
Loader2Icon
|
|
19
|
+
} from "lucide-react";
|
|
20
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
21
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
22
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
23
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
24
|
+
function PageActions({ children }) {
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { className: "labui:ml-auto labui:flex labui:max-w-full labui:flex-wrap labui:items-center labui:justify-end labui:gap-2 labui:[--labui-control-height:2.25rem] labui:empty:hidden labui:[@media(pointer:coarse)]:[--labui-control-height:2.75rem]", children });
|
|
26
|
+
}
|
|
27
|
+
function PageHeader({
|
|
28
|
+
title,
|
|
29
|
+
actions
|
|
30
|
+
}) {
|
|
31
|
+
return /* @__PURE__ */ jsxs("header", { className: "labui:flex labui:flex-wrap labui:items-center labui:gap-3", children: [
|
|
32
|
+
/* @__PURE__ */ jsx("h1", { className: "labui:font-display labui:text-2xl labui:font-bold labui:tracking-tight", children: title }),
|
|
33
|
+
/* @__PURE__ */ jsx(PageActions, { children: actions })
|
|
34
|
+
] });
|
|
35
|
+
}
|
|
36
|
+
function Page({
|
|
37
|
+
title,
|
|
38
|
+
actions,
|
|
39
|
+
className,
|
|
40
|
+
children
|
|
41
|
+
}) {
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: cn(
|
|
46
|
+
"labui:flex labui:min-w-0 labui:flex-col labui:gap-4",
|
|
47
|
+
className
|
|
48
|
+
),
|
|
49
|
+
children: [
|
|
50
|
+
title && /* @__PURE__ */ jsx(PageHeader, { title, actions }),
|
|
51
|
+
children
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
var focusRing = "labui:focus-visible:border-ring labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50";
|
|
57
|
+
var invalidRing = "labui:aria-invalid:border-destructive labui:aria-invalid:ring-destructive/20 labui:dark:aria-invalid:ring-destructive/40";
|
|
58
|
+
var raisedButtonSurface = [
|
|
59
|
+
"labui:border labui:border-border labui:border-b-input labui:bg-card labui:bg-linear-to-b labui:from-card labui:to-muted labui:text-foreground",
|
|
60
|
+
"labui:shadow-[inset_0_1px_0_#ffffff,0_1px_1px_#00000014,0_3px_4px_#0000000d]",
|
|
61
|
+
"labui:hover:to-background labui:hover:shadow-[inset_0_1px_0_#ffffff,0_2px_3px_#0000001a,0_4px_6px_#0000000d]",
|
|
62
|
+
"labui:active:translate-y-px labui:active:from-muted labui:active:to-card labui:active:shadow-[inset_0_1px_2px_#0000001a,0_1px_0_#ffffff80]",
|
|
63
|
+
"labui:dark:border-foreground/15 labui:dark:border-b-foreground/10 labui:dark:bg-secondary labui:dark:from-[color-mix(in_srgb,var(--labui-secondary)_88%,var(--labui-foreground))] labui:dark:to-secondary labui:dark:text-popover-foreground",
|
|
64
|
+
"labui:dark:shadow-[inset_0_1px_0_#ffffff14,0_1px_2px_#00000026]",
|
|
65
|
+
"labui:dark:hover:border-foreground/25 labui:dark:hover:from-[color-mix(in_srgb,var(--labui-secondary)_82%,var(--labui-foreground))] labui:dark:hover:to-secondary labui:dark:hover:shadow-[inset_0_1px_0_#ffffff1f,0_2px_4px_#00000033]",
|
|
66
|
+
"labui:dark:active:from-secondary labui:dark:active:to-secondary labui:dark:active:shadow-[inset_0_1px_2px_#00000033,0_1px_0_#ffffff0a]",
|
|
67
|
+
"labui:disabled:bg-secondary labui:disabled:bg-none labui:disabled:shadow-none labui:dark:disabled:shadow-none"
|
|
68
|
+
].join(" ");
|
|
69
|
+
var buttonVariants = {
|
|
70
|
+
default: "labui:border labui:border-transparent labui:bg-primary labui:text-primary-foreground labui:shadow-xs labui:hover:bg-primary/90 labui:active:translate-y-px",
|
|
71
|
+
destructive: "labui:border labui:border-transparent labui:bg-destructive-muted labui:text-destructive labui:hover:border-destructive/20 labui:hover:bg-destructive/15 labui:focus-visible:ring-destructive/20 labui:dark:focus-visible:ring-destructive/40",
|
|
72
|
+
secondary: raisedButtonSurface,
|
|
73
|
+
ghost: "labui:hover:bg-accent labui:hover:text-accent-foreground labui:dark:hover:bg-accent/50",
|
|
74
|
+
link: "labui:text-link labui:underline-offset-4 labui:hover:underline"
|
|
75
|
+
};
|
|
76
|
+
var buttonSizes = {
|
|
77
|
+
default: "labui:h-(--labui-control-height) labui:px-4 labui:py-2 labui:has-[>svg]:px-3",
|
|
78
|
+
sm: "labui:h-(--labui-control-height-sm) labui:gap-1.5 labui:rounded-md labui:px-3 labui:has-[>svg]:px-2.5",
|
|
79
|
+
"icon-xs": "labui:size-6 labui:rounded-md labui:[&_svg:not([class*='size-'])]:size-3",
|
|
80
|
+
"icon-sm": "labui:size-(--labui-control-height-sm)"
|
|
81
|
+
};
|
|
82
|
+
var Button = React.forwardRef(function Button2({
|
|
83
|
+
className,
|
|
84
|
+
variant = "default",
|
|
85
|
+
size = "default",
|
|
86
|
+
asChild = false,
|
|
87
|
+
...props
|
|
88
|
+
}, ref) {
|
|
89
|
+
const Comp = asChild ? Slot : "button";
|
|
90
|
+
return /* @__PURE__ */ jsx(
|
|
91
|
+
Comp,
|
|
92
|
+
{
|
|
93
|
+
ref,
|
|
94
|
+
"data-slot": "button",
|
|
95
|
+
"data-variant": variant,
|
|
96
|
+
"data-size": size,
|
|
97
|
+
className: cn(
|
|
98
|
+
"labui:inline-flex labui:shrink-0 labui:items-center labui:justify-center labui:gap-2 labui:rounded-md",
|
|
99
|
+
"labui:text-sm labui:font-medium labui:whitespace-nowrap labui:transition-all labui:outline-none",
|
|
100
|
+
"labui:disabled:pointer-events-none labui:disabled:opacity-50",
|
|
101
|
+
focusRing,
|
|
102
|
+
invalidRing,
|
|
103
|
+
"labui:[&_svg]:pointer-events-none labui:[&_svg]:shrink-0 labui:[&_svg:not([class*='size-'])]:size-4",
|
|
104
|
+
variant && buttonVariants[variant],
|
|
105
|
+
size && buttonSizes[size],
|
|
106
|
+
className
|
|
107
|
+
),
|
|
108
|
+
...props
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
var badgeVariants = {
|
|
113
|
+
default: "labui:bg-primary labui:text-primary-foreground labui:[a&]:hover:bg-primary/90",
|
|
114
|
+
destructive: "labui:border-destructive/30 labui:bg-destructive/15 labui:text-destructive labui:focus-visible:ring-destructive/20 labui:[a&]:hover:bg-destructive/25",
|
|
115
|
+
success: "labui:border-success/30 labui:bg-success/15 labui:text-success labui:[a&]:hover:bg-success/25",
|
|
116
|
+
warning: "labui:border-warning/30 labui:bg-warning/15 labui:text-warning labui:[a&]:hover:bg-warning/25"
|
|
117
|
+
};
|
|
118
|
+
var Badge = React.forwardRef(function Badge2({ className, variant = "default", ...props }, ref) {
|
|
119
|
+
return /* @__PURE__ */ jsx(
|
|
120
|
+
"span",
|
|
121
|
+
{
|
|
122
|
+
ref,
|
|
123
|
+
"data-slot": "badge",
|
|
124
|
+
"data-variant": variant,
|
|
125
|
+
className: cn(
|
|
126
|
+
"labui:inline-flex labui:w-fit labui:shrink-0 labui:items-center labui:justify-center labui:gap-1 labui:overflow-hidden",
|
|
127
|
+
"labui:rounded-full labui:border labui:border-transparent labui:px-2 labui:py-0.5",
|
|
128
|
+
"labui:text-xs labui:font-medium labui:whitespace-nowrap labui:transition-[color,box-shadow]",
|
|
129
|
+
focusRing,
|
|
130
|
+
invalidRing,
|
|
131
|
+
"labui:[&>svg]:pointer-events-none labui:[&>svg]:size-3",
|
|
132
|
+
variant && badgeVariants[variant],
|
|
133
|
+
className
|
|
134
|
+
),
|
|
135
|
+
...props
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
var alertVariants = {
|
|
140
|
+
destructive: "labui:border-destructive/40 labui:bg-card labui:text-destructive labui:*:data-[slot=alert-description]:text-destructive/90 labui:[&>svg]:text-current",
|
|
141
|
+
warning: "labui:border-warning/40 labui:bg-card labui:text-foreground labui:[&>svg]:text-warning"
|
|
142
|
+
};
|
|
143
|
+
var Alert = React.forwardRef(function Alert2({ className, variant, ...props }, ref) {
|
|
144
|
+
return /* @__PURE__ */ jsx(
|
|
145
|
+
"div",
|
|
146
|
+
{
|
|
147
|
+
ref,
|
|
148
|
+
"data-slot": "alert",
|
|
149
|
+
role: "alert",
|
|
150
|
+
className: cn(
|
|
151
|
+
"labui:relative labui:grid labui:w-full labui:grid-cols-[0_1fr] labui:items-start labui:gap-y-0.5 labui:rounded-lg labui:border labui:px-4 labui:py-3 labui:text-sm labui:has-[>svg]:grid-cols-[--spacing(4)_1fr] labui:has-[>svg]:gap-x-3 labui:[&>svg]:size-4 labui:[&>svg]:translate-y-0.5 labui:[&>svg]:text-current",
|
|
152
|
+
variant && alertVariants[variant],
|
|
153
|
+
className
|
|
154
|
+
),
|
|
155
|
+
...props
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
var AlertTitle = React.forwardRef(function AlertTitle2({ className, ...props }, ref) {
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
"div",
|
|
162
|
+
{
|
|
163
|
+
ref,
|
|
164
|
+
"data-slot": "alert-title",
|
|
165
|
+
className: cn(
|
|
166
|
+
"labui:col-start-2 labui:line-clamp-1 labui:min-h-4 labui:font-medium labui:tracking-tight",
|
|
167
|
+
className
|
|
168
|
+
),
|
|
169
|
+
...props
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
var AlertDescription = React.forwardRef(function AlertDescription2({ className, ...props }, ref) {
|
|
174
|
+
return /* @__PURE__ */ jsx(
|
|
175
|
+
"div",
|
|
176
|
+
{
|
|
177
|
+
ref,
|
|
178
|
+
"data-slot": "alert-description",
|
|
179
|
+
className: cn(
|
|
180
|
+
"labui:col-start-2 labui:grid labui:justify-items-start labui:gap-1 labui:text-sm labui:text-muted-foreground labui:[&_p]:leading-relaxed",
|
|
181
|
+
className
|
|
182
|
+
),
|
|
183
|
+
...props
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
var Input = React.forwardRef(function Input2({ className, type, ...props }, ref) {
|
|
188
|
+
return /* @__PURE__ */ jsx(
|
|
189
|
+
"input",
|
|
190
|
+
{
|
|
191
|
+
ref,
|
|
192
|
+
type,
|
|
193
|
+
autoComplete: "off",
|
|
194
|
+
"data-slot": "input",
|
|
195
|
+
className: cn(
|
|
196
|
+
"labui:h-(--labui-control-height) labui:w-full labui:min-w-0 labui:rounded-md labui:border labui:border-input",
|
|
197
|
+
"labui:bg-input-background labui:px-(--labui-control-px) labui:py-1 labui:shadow-xs",
|
|
198
|
+
"labui:text-base labui:md:text-sm labui:placeholder:text-muted-foreground labui:transition-[color,box-shadow] labui:outline-none",
|
|
199
|
+
"labui:selection:bg-primary labui:selection:text-primary-foreground",
|
|
200
|
+
"labui:file:me-3 labui:file:inline-flex labui:file:h-7 labui:file:border-0 labui:file:bg-transparent",
|
|
201
|
+
"labui:file:text-sm labui:file:font-medium labui:file:text-foreground",
|
|
202
|
+
"labui:disabled:pointer-events-none labui:disabled:cursor-not-allowed labui:disabled:opacity-50",
|
|
203
|
+
focusRing,
|
|
204
|
+
invalidRing,
|
|
205
|
+
"labui:[&::-webkit-search-cancel-button]:appearance-none labui:[&::-webkit-search-decoration]:appearance-none labui:[&::-webkit-search-results-button]:appearance-none",
|
|
206
|
+
"labui:[&::-webkit-calendar-picker-indicator]:opacity-60 labui:[&::-webkit-datetime-edit]:leading-none",
|
|
207
|
+
className
|
|
208
|
+
),
|
|
209
|
+
...props
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
var Checkbox = React.forwardRef(function Checkbox2({ className, ...props }, ref) {
|
|
214
|
+
return /* @__PURE__ */ jsx(
|
|
215
|
+
CheckboxPrimitive.Root,
|
|
216
|
+
{
|
|
217
|
+
ref,
|
|
218
|
+
"data-slot": "checkbox",
|
|
219
|
+
className: cn(
|
|
220
|
+
"labui:peer labui:size-4 labui:shrink-0 labui:rounded-[4px] labui:border labui:border-input labui:dark:bg-input/30",
|
|
221
|
+
"labui:shadow-xs labui:transition-shadow labui:outline-none",
|
|
222
|
+
"labui:disabled:cursor-not-allowed labui:disabled:opacity-50",
|
|
223
|
+
"labui:data-[state=checked]:border-primary labui:data-[state=checked]:bg-primary labui:data-[state=checked]:text-primary-foreground labui:dark:data-[state=checked]:bg-primary",
|
|
224
|
+
focusRing,
|
|
225
|
+
invalidRing,
|
|
226
|
+
className
|
|
227
|
+
),
|
|
228
|
+
...props,
|
|
229
|
+
children: /* @__PURE__ */ jsx(
|
|
230
|
+
CheckboxPrimitive.Indicator,
|
|
231
|
+
{
|
|
232
|
+
"data-slot": "checkbox-indicator",
|
|
233
|
+
className: "labui:grid labui:place-content-center labui:text-current labui:transition-none",
|
|
234
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "labui:size-3.5" })
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
var Field = React.forwardRef(function Field2({ className, orientation, ...props }, ref) {
|
|
241
|
+
return /* @__PURE__ */ jsx(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
ref,
|
|
245
|
+
role: "group",
|
|
246
|
+
className: cn(
|
|
247
|
+
"labui:flex labui:w-full labui:gap-3 labui:data-[invalid=true]:text-destructive",
|
|
248
|
+
orientation ? "labui:items-center" : "labui:flex-col",
|
|
249
|
+
className
|
|
250
|
+
),
|
|
251
|
+
...props
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
var FieldLabel = React.forwardRef(function FieldLabel2({ className, ...props }, ref) {
|
|
256
|
+
return (
|
|
257
|
+
// oxlint-disable-next-line jsx-a11y/label-has-associated-control -- callers pass htmlFor
|
|
258
|
+
/* @__PURE__ */ jsx(
|
|
259
|
+
"label",
|
|
260
|
+
{
|
|
261
|
+
ref,
|
|
262
|
+
className: cn(
|
|
263
|
+
"labui:flex labui:w-fit labui:items-center labui:gap-2 labui:text-sm labui:leading-snug labui:font-medium labui:select-none",
|
|
264
|
+
className
|
|
265
|
+
),
|
|
266
|
+
...props
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
var FieldError = React.forwardRef(function FieldError2({ className, ...props }, ref) {
|
|
272
|
+
return /* @__PURE__ */ jsx(
|
|
273
|
+
"div",
|
|
274
|
+
{
|
|
275
|
+
ref,
|
|
276
|
+
role: "alert",
|
|
277
|
+
className: cn("labui:text-sm labui:text-destructive", className),
|
|
278
|
+
...props
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
function Select(props) {
|
|
283
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
|
|
284
|
+
}
|
|
285
|
+
function SelectValue(props) {
|
|
286
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
|
|
287
|
+
}
|
|
288
|
+
var SelectTrigger = React.forwardRef(function SelectTrigger2({ className, size = "default", children, ...props }, ref) {
|
|
289
|
+
return /* @__PURE__ */ jsxs(
|
|
290
|
+
SelectPrimitive.Trigger,
|
|
291
|
+
{
|
|
292
|
+
ref,
|
|
293
|
+
"data-slot": "select-trigger",
|
|
294
|
+
"data-size": size,
|
|
295
|
+
className: cn(
|
|
296
|
+
"labui:flex labui:h-(--labui-control-height) labui:w-full labui:min-w-0 labui:items-center labui:justify-between labui:gap-2",
|
|
297
|
+
"labui:rounded-md labui:border labui:border-input labui:bg-input-background labui:px-(--labui-control-px) labui:shadow-xs",
|
|
298
|
+
"labui:text-sm labui:whitespace-nowrap labui:transition-[color,box-shadow] labui:outline-none labui:data-[placeholder]:text-muted-foreground",
|
|
299
|
+
"labui:data-[size=sm]:h-(--labui-control-height-sm) labui:data-[size=sm]:px-2 labui:data-[size=sm]:text-xs",
|
|
300
|
+
focusRing,
|
|
301
|
+
invalidRing,
|
|
302
|
+
"labui:disabled:cursor-not-allowed labui:disabled:opacity-50",
|
|
303
|
+
"labui:*:data-[slot=select-value]:truncate labui:[&_svg]:pointer-events-none labui:[&_svg]:shrink-0",
|
|
304
|
+
className
|
|
305
|
+
),
|
|
306
|
+
...props,
|
|
307
|
+
children: [
|
|
308
|
+
children,
|
|
309
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "labui:size-4 labui:text-muted-foreground" }) })
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
});
|
|
314
|
+
var SelectContent = React.forwardRef(function SelectContent2({ className, children, ...props }, ref) {
|
|
315
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
316
|
+
SelectPrimitive.Content,
|
|
317
|
+
{
|
|
318
|
+
ref,
|
|
319
|
+
"data-slot": "select-content",
|
|
320
|
+
position: "popper",
|
|
321
|
+
sideOffset: 4,
|
|
322
|
+
className: cn(
|
|
323
|
+
"labui:relative labui:z-50 labui:max-h-(--radix-select-content-available-height) labui:min-w-(--radix-select-trigger-width) labui:overflow-x-hidden labui:overflow-y-auto labui:rounded-lg labui:border labui:bg-popover/90 labui:p-1 labui:text-popover-foreground labui:shadow-lg labui:backdrop-blur-xl labui:backdrop-saturate-150",
|
|
324
|
+
className
|
|
325
|
+
),
|
|
326
|
+
...props,
|
|
327
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, { children: React.Children.toArray(children).length ? children : /* @__PURE__ */ jsx("p", { className: "labui:p-2 labui:text-sm labui:text-muted-foreground", children: "Empty" }) })
|
|
328
|
+
}
|
|
329
|
+
) });
|
|
330
|
+
});
|
|
331
|
+
var SelectItem = React.forwardRef(function SelectItem2({ className, children, ...props }, ref) {
|
|
332
|
+
return /* @__PURE__ */ jsxs(
|
|
333
|
+
SelectPrimitive.Item,
|
|
334
|
+
{
|
|
335
|
+
ref,
|
|
336
|
+
"data-slot": "select-item",
|
|
337
|
+
className: cn(
|
|
338
|
+
"labui:relative labui:flex labui:w-full labui:cursor-default labui:items-center labui:rounded-md labui:py-1.5 labui:pr-8 labui:pl-2 labui:text-sm labui:outline-none labui:select-none labui:data-[disabled]:pointer-events-none labui:data-[disabled]:opacity-50 labui:data-[highlighted]:bg-accent labui:data-[highlighted]:text-accent-foreground",
|
|
339
|
+
className
|
|
340
|
+
),
|
|
341
|
+
...props,
|
|
342
|
+
children: [
|
|
343
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children }),
|
|
344
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { className: "labui:absolute labui:right-2 labui:flex labui:items-center", children: /* @__PURE__ */ jsx(CheckIcon, { className: "labui:size-4 labui:text-primary" }) })
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
var Spinner = React.forwardRef(function Spinner2({ className, ...props }, ref) {
|
|
350
|
+
return /* @__PURE__ */ jsx(
|
|
351
|
+
Loader2Icon,
|
|
352
|
+
{
|
|
353
|
+
ref,
|
|
354
|
+
role: "status",
|
|
355
|
+
"aria-label": "Loading",
|
|
356
|
+
className: cn("labui:size-4 labui:animate-spin", className),
|
|
357
|
+
...props
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
});
|
|
361
|
+
var Skeleton = React.forwardRef(function Skeleton2({ className, ...props }, ref) {
|
|
362
|
+
return /* @__PURE__ */ jsx(
|
|
363
|
+
"div",
|
|
364
|
+
{
|
|
365
|
+
ref,
|
|
366
|
+
"data-slot": "skeleton",
|
|
367
|
+
className: cn(
|
|
368
|
+
"labui:animate-pulse labui:rounded-md labui:bg-accent",
|
|
369
|
+
className
|
|
370
|
+
),
|
|
371
|
+
...props
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
});
|
|
375
|
+
function CopyButton({ value, label }) {
|
|
376
|
+
const [copied, setCopied] = React.useState(false);
|
|
377
|
+
return /* @__PURE__ */ jsx(
|
|
378
|
+
Button,
|
|
379
|
+
{
|
|
380
|
+
type: "button",
|
|
381
|
+
variant: "ghost",
|
|
382
|
+
size: "icon-xs",
|
|
383
|
+
"aria-label": label,
|
|
384
|
+
title: label,
|
|
385
|
+
onClick: () => navigator.clipboard.writeText(value).then(() => setCopied(true)),
|
|
386
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
function Back({
|
|
391
|
+
label,
|
|
392
|
+
...props
|
|
393
|
+
}) {
|
|
394
|
+
return /* @__PURE__ */ jsx(
|
|
395
|
+
Button,
|
|
396
|
+
{
|
|
397
|
+
variant: "ghost",
|
|
398
|
+
size: "sm",
|
|
399
|
+
className: "labui:-ml-2.5 labui:self-start",
|
|
400
|
+
asChild: true,
|
|
401
|
+
children: /* @__PURE__ */ jsxs("a", { ...props, children: [
|
|
402
|
+
/* @__PURE__ */ jsx(ArrowLeftIcon, {}),
|
|
403
|
+
label
|
|
404
|
+
] })
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export {
|
|
410
|
+
cn,
|
|
411
|
+
PageActions,
|
|
412
|
+
PageHeader,
|
|
413
|
+
Page,
|
|
414
|
+
Button,
|
|
415
|
+
Badge,
|
|
416
|
+
Alert,
|
|
417
|
+
AlertTitle,
|
|
418
|
+
AlertDescription,
|
|
419
|
+
Input,
|
|
420
|
+
Checkbox,
|
|
421
|
+
Field,
|
|
422
|
+
FieldLabel,
|
|
423
|
+
FieldError,
|
|
424
|
+
Select,
|
|
425
|
+
SelectValue,
|
|
426
|
+
SelectTrigger,
|
|
427
|
+
SelectContent,
|
|
428
|
+
SelectItem,
|
|
429
|
+
Spinner,
|
|
430
|
+
Skeleton,
|
|
431
|
+
CopyButton,
|
|
432
|
+
Back
|
|
433
|
+
};
|
|
434
|
+
//# sourceMappingURL=chunk-3ZY2AVB4.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../classes.ts", "../primitives.tsx"],
|
|
4
|
+
"sourcesContent": ["import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n experimentalParseClassName: ({ className, parseClassName }) =>\n parseClassName(className.replace(/^labui:/, \"\")),\n});\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n", "import * as React from \"react\";\nimport {\n ArrowLeftIcon,\n CheckIcon,\n ChevronDownIcon,\n CopyIcon,\n Loader2Icon,\n} from \"lucide-react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { Slot } from \"@radix-ui/react-slot\";\n\nimport { cn } from \"./classes.js\";\nexport { cn } from \"./classes.js\";\n\nexport function PageActions({ children }: { children?: React.ReactNode }) {\n return (\n <div className=\"labui:ml-auto labui:flex labui:max-w-full labui:flex-wrap labui:items-center labui:justify-end labui:gap-2 labui:[--labui-control-height:2.25rem] labui:empty:hidden labui:[@media(pointer:coarse)]:[--labui-control-height:2.75rem]\">\n {children}\n </div>\n );\n}\nexport function PageHeader({\n title,\n actions,\n}: {\n title: string;\n actions?: React.ReactNode;\n}) {\n return (\n <header className=\"labui:flex labui:flex-wrap labui:items-center labui:gap-3\">\n <h1 className=\"labui:font-display labui:text-2xl labui:font-bold labui:tracking-tight\">\n {title}\n </h1>\n <PageActions>{actions}</PageActions>\n </header>\n );\n}\nexport function Page({\n title,\n actions,\n className,\n children,\n}: {\n title?: string;\n actions?: React.ReactNode;\n className?: string;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={cn(\n \"labui:flex labui:min-w-0 labui:flex-col labui:gap-4\",\n className,\n )}\n >\n {title && <PageHeader title={title} actions={actions} />}\n {children}\n </div>\n );\n}\n\nconst focusRing =\n \"labui:focus-visible:border-ring labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50\";\nconst invalidRing =\n \"labui:aria-invalid:border-destructive labui:aria-invalid:ring-destructive/20 labui:dark:aria-invalid:ring-destructive/40\";\n\nconst raisedButtonSurface = [\n \"labui:border labui:border-border labui:border-b-input labui:bg-card labui:bg-linear-to-b labui:from-card labui:to-muted labui:text-foreground\",\n \"labui:shadow-[inset_0_1px_0_#ffffff,0_1px_1px_#00000014,0_3px_4px_#0000000d]\",\n \"labui:hover:to-background labui:hover:shadow-[inset_0_1px_0_#ffffff,0_2px_3px_#0000001a,0_4px_6px_#0000000d]\",\n \"labui:active:translate-y-px labui:active:from-muted labui:active:to-card labui:active:shadow-[inset_0_1px_2px_#0000001a,0_1px_0_#ffffff80]\",\n \"labui:dark:border-foreground/15 labui:dark:border-b-foreground/10 labui:dark:bg-secondary labui:dark:from-[color-mix(in_srgb,var(--labui-secondary)_88%,var(--labui-foreground))] labui:dark:to-secondary labui:dark:text-popover-foreground\",\n \"labui:dark:shadow-[inset_0_1px_0_#ffffff14,0_1px_2px_#00000026]\",\n \"labui:dark:hover:border-foreground/25 labui:dark:hover:from-[color-mix(in_srgb,var(--labui-secondary)_82%,var(--labui-foreground))] labui:dark:hover:to-secondary labui:dark:hover:shadow-[inset_0_1px_0_#ffffff1f,0_2px_4px_#00000033]\",\n \"labui:dark:active:from-secondary labui:dark:active:to-secondary labui:dark:active:shadow-[inset_0_1px_2px_#00000033,0_1px_0_#ffffff0a]\",\n \"labui:disabled:bg-secondary labui:disabled:bg-none labui:disabled:shadow-none labui:dark:disabled:shadow-none\",\n].join(\" \");\n\nconst buttonVariants = {\n default:\n \"labui:border labui:border-transparent labui:bg-primary labui:text-primary-foreground labui:shadow-xs labui:hover:bg-primary/90 labui:active:translate-y-px\",\n destructive:\n \"labui:border labui:border-transparent labui:bg-destructive-muted labui:text-destructive labui:hover:border-destructive/20 labui:hover:bg-destructive/15 labui:focus-visible:ring-destructive/20 labui:dark:focus-visible:ring-destructive/40\",\n secondary: raisedButtonSurface,\n ghost:\n \"labui:hover:bg-accent labui:hover:text-accent-foreground labui:dark:hover:bg-accent/50\",\n link: \"labui:text-link labui:underline-offset-4 labui:hover:underline\",\n};\nconst buttonSizes = {\n default:\n \"labui:h-(--labui-control-height) labui:px-4 labui:py-2 labui:has-[>svg]:px-3\",\n sm: \"labui:h-(--labui-control-height-sm) labui:gap-1.5 labui:rounded-md labui:px-3 labui:has-[>svg]:px-2.5\",\n \"icon-xs\":\n \"labui:size-6 labui:rounded-md labui:[&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"labui:size-(--labui-control-height-sm)\",\n};\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<\"button\"> & {\n variant?: keyof typeof buttonVariants | null;\n size?: keyof typeof buttonSizes | null;\n asChild?: boolean;\n }\n>(function Button(\n {\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n },\n ref,\n) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n ref={ref}\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(\n \"labui:inline-flex labui:shrink-0 labui:items-center labui:justify-center labui:gap-2 labui:rounded-md\",\n \"labui:text-sm labui:font-medium labui:whitespace-nowrap labui:transition-all labui:outline-none\",\n \"labui:disabled:pointer-events-none labui:disabled:opacity-50\",\n focusRing,\n invalidRing,\n \"labui:[&_svg]:pointer-events-none labui:[&_svg]:shrink-0 labui:[&_svg:not([class*='size-'])]:size-4\",\n variant && buttonVariants[variant],\n size && buttonSizes[size],\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Button };\n\nconst badgeVariants = {\n default:\n \"labui:bg-primary labui:text-primary-foreground labui:[a&]:hover:bg-primary/90\",\n destructive:\n \"labui:border-destructive/30 labui:bg-destructive/15 labui:text-destructive labui:focus-visible:ring-destructive/20 labui:[a&]:hover:bg-destructive/25\",\n success:\n \"labui:border-success/30 labui:bg-success/15 labui:text-success labui:[a&]:hover:bg-success/25\",\n warning:\n \"labui:border-warning/30 labui:bg-warning/15 labui:text-warning labui:[a&]:hover:bg-warning/25\",\n};\n\nconst Badge = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<\"span\"> & {\n variant?: keyof typeof badgeVariants | null;\n }\n>(function Badge({ className, variant = \"default\", ...props }, ref) {\n return (\n <span\n ref={ref}\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(\n \"labui:inline-flex labui:w-fit labui:shrink-0 labui:items-center labui:justify-center labui:gap-1 labui:overflow-hidden\",\n \"labui:rounded-full labui:border labui:border-transparent labui:px-2 labui:py-0.5\",\n \"labui:text-xs labui:font-medium labui:whitespace-nowrap labui:transition-[color,box-shadow]\",\n focusRing,\n invalidRing,\n \"labui:[&>svg]:pointer-events-none labui:[&>svg]:size-3\",\n variant && badgeVariants[variant],\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Badge };\n\nconst alertVariants = {\n destructive:\n \"labui:border-destructive/40 labui:bg-card labui:text-destructive labui:*:data-[slot=alert-description]:text-destructive/90 labui:[&>svg]:text-current\",\n warning:\n \"labui:border-warning/40 labui:bg-card labui:text-foreground labui:[&>svg]:text-warning\",\n};\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\"> & {\n variant?: keyof typeof alertVariants | null;\n }\n>(function Alert({ className, variant, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(\n \"labui:relative labui:grid labui:w-full labui:grid-cols-[0_1fr] labui:items-start labui:gap-y-0.5 labui:rounded-lg labui:border labui:px-4 labui:py-3 labui:text-sm labui:has-[>svg]:grid-cols-[--spacing(4)_1fr] labui:has-[>svg]:gap-x-3 labui:[&>svg]:size-4 labui:[&>svg]:translate-y-0.5 labui:[&>svg]:text-current\",\n variant && alertVariants[variant],\n className,\n )}\n {...props}\n />\n );\n});\n\nconst AlertTitle = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\">\n>(function AlertTitle({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"alert-title\"\n className={cn(\n \"labui:col-start-2 labui:line-clamp-1 labui:min-h-4 labui:font-medium labui:tracking-tight\",\n className,\n )}\n {...props}\n />\n );\n});\n\nconst AlertDescription = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\">\n>(function AlertDescription({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"alert-description\"\n className={cn(\n \"labui:col-start-2 labui:grid labui:justify-items-start labui:gap-1 labui:text-sm labui:text-muted-foreground labui:[&_p]:leading-relaxed\",\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Alert, AlertTitle, AlertDescription };\n\nconst Input = React.forwardRef<\n HTMLInputElement,\n React.ComponentPropsWithoutRef<\"input\">\n>(function Input({ className, type, ...props }, ref) {\n return (\n <input\n ref={ref}\n type={type}\n autoComplete=\"off\"\n data-slot=\"input\"\n className={cn(\n \"labui:h-(--labui-control-height) labui:w-full labui:min-w-0 labui:rounded-md labui:border labui:border-input\",\n \"labui:bg-input-background labui:px-(--labui-control-px) labui:py-1 labui:shadow-xs\",\n \"labui:text-base labui:md:text-sm labui:placeholder:text-muted-foreground labui:transition-[color,box-shadow] labui:outline-none\",\n \"labui:selection:bg-primary labui:selection:text-primary-foreground\",\n \"labui:file:me-3 labui:file:inline-flex labui:file:h-7 labui:file:border-0 labui:file:bg-transparent\",\n \"labui:file:text-sm labui:file:font-medium labui:file:text-foreground\",\n \"labui:disabled:pointer-events-none labui:disabled:cursor-not-allowed labui:disabled:opacity-50\",\n focusRing,\n invalidRing,\n \"labui:[&::-webkit-search-cancel-button]:appearance-none labui:[&::-webkit-search-decoration]:appearance-none labui:[&::-webkit-search-results-button]:appearance-none\",\n \"labui:[&::-webkit-calendar-picker-indicator]:opacity-60 labui:[&::-webkit-datetime-edit]:leading-none\",\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Input };\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(function Checkbox({ className, ...props }, ref) {\n return (\n <CheckboxPrimitive.Root\n ref={ref}\n data-slot=\"checkbox\"\n className={cn(\n \"labui:peer labui:size-4 labui:shrink-0 labui:rounded-[4px] labui:border labui:border-input labui:dark:bg-input/30\",\n \"labui:shadow-xs labui:transition-shadow labui:outline-none\",\n \"labui:disabled:cursor-not-allowed labui:disabled:opacity-50\",\n \"labui:data-[state=checked]:border-primary labui:data-[state=checked]:bg-primary labui:data-[state=checked]:text-primary-foreground labui:dark:data-[state=checked]:bg-primary\",\n focusRing,\n invalidRing,\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"labui:grid labui:place-content-center labui:text-current labui:transition-none\"\n >\n <CheckIcon className=\"labui:size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n});\n\nexport { Checkbox };\n\nconst Field = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\"> & { orientation?: \"horizontal\" }\n>(function Field({ className, orientation, ...props }, ref) {\n return (\n <div\n ref={ref}\n role=\"group\"\n className={cn(\n \"labui:flex labui:w-full labui:gap-3 labui:data-[invalid=true]:text-destructive\",\n orientation ? \"labui:items-center\" : \"labui:flex-col\",\n className,\n )}\n {...props}\n />\n );\n});\n\nconst FieldLabel = React.forwardRef<\n HTMLLabelElement,\n React.ComponentPropsWithoutRef<\"label\">\n>(function FieldLabel({ className, ...props }, ref) {\n return (\n // oxlint-disable-next-line jsx-a11y/label-has-associated-control -- callers pass htmlFor\n <label\n ref={ref}\n className={cn(\n \"labui:flex labui:w-fit labui:items-center labui:gap-2 labui:text-sm labui:leading-snug labui:font-medium labui:select-none\",\n className,\n )}\n {...props}\n />\n );\n});\n\nconst FieldError = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\">\n>(function FieldError({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(\"labui:text-sm labui:text-destructive\", className)}\n {...props}\n />\n );\n});\n\nexport { Field, FieldLabel, FieldError };\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectValue(\n props: React.ComponentProps<typeof SelectPrimitive.Value>,\n) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\";\n }\n>(function SelectTrigger(\n { className, size = \"default\", children, ...props },\n ref,\n) {\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"labui:flex labui:h-(--labui-control-height) labui:w-full labui:min-w-0 labui:items-center labui:justify-between labui:gap-2\",\n \"labui:rounded-md labui:border labui:border-input labui:bg-input-background labui:px-(--labui-control-px) labui:shadow-xs\",\n \"labui:text-sm labui:whitespace-nowrap labui:transition-[color,box-shadow] labui:outline-none labui:data-[placeholder]:text-muted-foreground\",\n \"labui:data-[size=sm]:h-(--labui-control-height-sm) labui:data-[size=sm]:px-2 labui:data-[size=sm]:text-xs\",\n focusRing,\n invalidRing,\n \"labui:disabled:cursor-not-allowed labui:disabled:opacity-50\",\n \"labui:*:data-[slot=select-value]:truncate labui:[&_svg]:pointer-events-none labui:[&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"labui:size-4 labui:text-muted-foreground\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n});\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(function SelectContent({ className, children, ...props }, ref) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n data-slot=\"select-content\"\n position=\"popper\"\n sideOffset={4}\n className={cn(\n \"labui:relative labui:z-50 labui:max-h-(--radix-select-content-available-height) labui:min-w-(--radix-select-trigger-width) labui:overflow-x-hidden labui:overflow-y-auto labui:rounded-lg labui:border labui:bg-popover/90 labui:p-1 labui:text-popover-foreground labui:shadow-lg labui:backdrop-blur-xl labui:backdrop-saturate-150\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport>\n {React.Children.toArray(children).length ? (\n children\n ) : (\n <p className=\"labui:p-2 labui:text-sm labui:text-muted-foreground\">\n Empty\n </p>\n )}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n});\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(function SelectItem({ className, children, ...props }, ref) {\n return (\n <SelectPrimitive.Item\n ref={ref}\n data-slot=\"select-item\"\n className={cn(\n \"labui:relative labui:flex labui:w-full labui:cursor-default labui:items-center labui:rounded-md labui:py-1.5 labui:pr-8 labui:pl-2 labui:text-sm labui:outline-none labui:select-none labui:data-[disabled]:pointer-events-none labui:data-[disabled]:opacity-50 labui:data-[highlighted]:bg-accent labui:data-[highlighted]:text-accent-foreground\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"labui:absolute labui:right-2 labui:flex labui:items-center\">\n <CheckIcon className=\"labui:size-4 labui:text-primary\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n );\n});\n\nexport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue };\n\nconst Spinner = React.forwardRef<\n SVGSVGElement,\n React.ComponentPropsWithoutRef<\"svg\">\n>(function Spinner({ className, ...props }, ref) {\n return (\n <Loader2Icon\n ref={ref}\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"labui:size-4 labui:animate-spin\", className)}\n {...props}\n />\n );\n});\n\nexport { Spinner };\n\nconst Skeleton = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\">\n>(function Skeleton({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"skeleton\"\n className={cn(\n \"labui:animate-pulse labui:rounded-md labui:bg-accent\",\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Skeleton };\n\nexport function CopyButton({ value, label }: { value: string; label: string }) {\n const [copied, setCopied] = React.useState(false);\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={label}\n title={label}\n onClick={() =>\n navigator.clipboard.writeText(value).then(() => setCopied(true))\n }\n >\n {copied ? <CheckIcon /> : <CopyIcon />}\n </Button>\n );\n}\n\nexport function Back({\n label,\n ...props\n}: React.ComponentProps<\"a\"> & { label: string }) {\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"labui:-ml-2.5 labui:self-start\"\n asChild\n >\n <a {...props}>\n <ArrowLeftIcon />\n {label}\n </a>\n </Button>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Button", "Badge", "Alert", "AlertTitle", "AlertDescription", "Input", "Checkbox", "Field", "FieldLabel", "FieldError", "SelectTrigger", "SelectContent", "SelectItem", "Spinner", "Skeleton"]
|
|
7
|
+
}
|