@labpane/ui 0.0.0-stage → 1.2.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 +130 -2
- package/dist/LICENSE +21 -0
- package/dist/chunk-NR3PLNO7.js +100 -0
- package/dist/chunk-NR3PLNO7.js.map +7 -0
- package/dist/index.js +7137 -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/alert.d.ts +13 -0
- package/dist/ui/app-menu.d.ts +19 -0
- package/dist/ui/avatar.d.ts +11 -0
- package/dist/ui/badge.d.ts +17 -0
- package/dist/ui/breadcrumb.d.ts +11 -0
- package/dist/ui/browser-layout.d.ts +20 -0
- package/dist/ui/button.d.ts +27 -0
- package/dist/ui/card.d.ts +15 -0
- package/dist/ui/chart-frame.d.ts +4 -0
- package/dist/ui/checkbox.d.ts +4 -0
- package/dist/ui/classes.d.ts +7 -0
- package/dist/ui/command.d.ts +82 -0
- package/dist/ui/confirm-dialog.d.ts +28 -0
- package/dist/ui/copy-button.d.ts +7 -0
- package/dist/ui/dialog.d.ts +18 -0
- package/dist/ui/discard-dialog.d.ts +6 -0
- package/dist/ui/email-thread.d.ts +35 -0
- package/dist/ui/empty.d.ts +14 -0
- package/dist/ui/field.d.ts +26 -0
- package/dist/ui/file-input.d.ts +6 -0
- package/dist/ui/flame-graph-model.d.ts +23 -0
- package/dist/ui/flame-graph.d.ts +15 -0
- package/dist/ui/form-fields.d.ts +21 -0
- package/dist/ui/histogram.d.ts +23 -0
- package/dist/ui/index.d.ts +57 -0
- package/dist/ui/input-group.d.ts +28 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/kbd.d.ts +4 -0
- package/dist/ui/label.d.ts +3 -0
- package/dist/ui/menu.d.ts +60 -0
- package/dist/ui/native-select.d.ts +7 -0
- package/dist/ui/nav-tabs.d.ts +7 -0
- package/dist/ui/overlay.d.ts +1 -0
- package/dist/ui/page.d.ts +22 -0
- package/dist/ui/rail.d.ts +16 -0
- package/dist/ui/search-input.d.ts +6 -0
- package/dist/ui/select.d.ts +13 -0
- package/dist/ui/separator.d.ts +6 -0
- package/dist/ui/settings.d.ts +14 -0
- package/dist/ui/sheet.d.ts +20 -0
- package/dist/ui/side-panel.d.ts +23 -0
- package/dist/ui/sidebar.d.ts +81 -0
- package/dist/ui/skeleton.d.ts +3 -0
- package/dist/ui/spinner.d.ts +3 -0
- package/dist/ui/stat.d.ts +7 -0
- package/dist/ui/steps.d.ts +7 -0
- package/dist/ui/switch.d.ts +6 -0
- package/dist/ui/tab-state.d.ts +8 -0
- package/dist/ui/table-layout.d.ts +19 -0
- package/dist/ui/table-model.d.ts +42 -0
- package/dist/ui/table-screen.d.ts +9 -0
- package/dist/ui/table.d.ts +41 -0
- package/dist/ui/tabs.d.ts +13 -0
- package/dist/ui/terminal.d.ts +57 -0
- package/dist/ui/textarea.d.ts +3 -0
- package/dist/ui/theme.d.ts +22 -0
- package/dist/ui/time-series-chart.d.ts +19 -0
- package/dist/ui/time-series-model.d.ts +90 -0
- package/dist/ui/timing-tracks.d.ts +27 -0
- package/dist/ui/toggle.d.ts +22 -0
- package/dist/ui/tooltip.d.ts +7 -0
- package/dist/ui/topbar.d.ts +4 -0
- package/dist/ui/use-chart-width.d.ts +5 -0
- package/dist/ui/use-mobile.d.ts +1 -0
- package/package.json +116 -4
- package/styles.css +358 -0
package/README.md
CHANGED
|
@@ -1,3 +1,131 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @labpane/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pages, forms, dialogs, menus, tables, navigation, charts, 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-avatar @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 @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-toggle @radix-ui/react-toggle-group @radix-ui/react-tooltip
|
|
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` and its parts, `PageActions`, `Back`, `Topbar`, `Breadcrumb` and its parts, `TableScreen`, `BrowserLayout` and its parts, `SidePanel`, `SettingsSection`, `SettingsRow`, `SettingsFooter` |
|
|
29
|
+
| Navigation | `Sidebar` and its parts, `Rail`, `RailItem`, `NavTabs`, `NavTab`, `Tabs` and its parts, `Steps`, `Step`, `Command` and its parts |
|
|
30
|
+
| Controls | `Button`, `Badge`, `Input`, `Textarea`, `Checkbox`, `Switch`, `Toggle`, `ToggleGroup`, `Select` and its parts, `NativeSelect`, `SearchInput`, `FileInput`, `InputGroup` and its parts, `CopyButton`, `Kbd` |
|
|
31
|
+
| Forms | `Field`, `FieldLabel`, `FieldDescription`, `FieldError`, `FieldSet`, `FieldGroup`, `Label`, `TextField`, `SelectField`, `AddButton` |
|
|
32
|
+
| Display | `Alert`, `Card` and its parts, `Avatar` and its parts, `Stats`, `Stat`, `Empty` and its parts, `Separator`, `Skeleton`, `Spinner`, `Tooltip`, `EmailThread`, `EmailMessage` |
|
|
33
|
+
| Dialogs | `Dialog` and its parts, `Sheet` and its parts, `ConfirmDialog`, `DiscardDialog` |
|
|
34
|
+
| Menus | `DropdownMenu` and its parts, `OptionMenu`, `ActionMenu`, `MenuContent` |
|
|
35
|
+
| Tables | `Table`, `TableStack`, `column`, `mono`, `num` |
|
|
36
|
+
| Charts | `TimeSeriesChart`, `HistogramChart`, `HistogramSparkline`, `FlameGraph`, `TimingTracks`, `ChartFrame` |
|
|
37
|
+
| Workspace | `AppMenu` with `AppMenuSection`; `useTabActive` and `useTabVisible` read the tab state that `@labpane/os` provides |
|
|
38
|
+
|
|
39
|
+
`cn()` merges class names and lets your own Tailwind classes override the `labui:` defaults they conflict with.
|
|
40
|
+
|
|
41
|
+
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:
|
|
42
|
+
|
|
43
|
+
```css
|
|
44
|
+
@import "@labpane/ui/tailwind.css";
|
|
45
|
+
@source "./src";
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## With @labpane/os
|
|
49
|
+
|
|
50
|
+
Fill the workspace's slots with ui's menus and dialog:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Workspace
|
|
54
|
+
{...workspaceProps}
|
|
55
|
+
toolbar={(pane) => (
|
|
56
|
+
<OptionMenu
|
|
57
|
+
options={[{ id: "reports", label: "Reports" }]}
|
|
58
|
+
onSelect={openTab}
|
|
59
|
+
trigger={
|
|
60
|
+
<Button size="icon-sm" aria-label="Open a tab">
|
|
61
|
+
+
|
|
62
|
+
</Button>
|
|
63
|
+
}
|
|
64
|
+
/>
|
|
65
|
+
)}
|
|
66
|
+
menu={(target, actions, restoreFocus) => (
|
|
67
|
+
<ActionMenu
|
|
68
|
+
actions={actions}
|
|
69
|
+
onCloseAutoFocus={
|
|
70
|
+
restoreFocus &&
|
|
71
|
+
((event) => {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
restoreFocus();
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
>
|
|
77
|
+
{target}
|
|
78
|
+
</ActionMenu>
|
|
79
|
+
)}
|
|
80
|
+
confirmClose={(tab) => askToDiscard(tab.label)}
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`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.
|
|
85
|
+
|
|
86
|
+
## Terminal
|
|
87
|
+
|
|
88
|
+
`@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):
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
npm install @wterm/dom
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import "@wterm/dom/css";
|
|
96
|
+
import { Terminal } from "@labpane/ui/terminal";
|
|
97
|
+
|
|
98
|
+
<Terminal connect={() => "/pty"} expandable />;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`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"`.
|
|
102
|
+
|
|
103
|
+
## Theming
|
|
104
|
+
|
|
105
|
+
Set these on `:root`, or on any ancestor. Add a `dark` class to an ancestor for the dark defaults.
|
|
106
|
+
|
|
107
|
+
```css
|
|
108
|
+
:root {
|
|
109
|
+
--labui-primary: #05697a;
|
|
110
|
+
--labui-radius: 0.75rem;
|
|
111
|
+
--labui-font-sans: inherit;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
A theme can also be an object. `themeCss(theme)` returns the CSS for both packages' tokens and `<ThemeStyle theme={theme} />` renders it; keys left out keep the defaults.
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
<ThemeStyle
|
|
119
|
+
theme={{
|
|
120
|
+
light: { primary: "#a3242f" },
|
|
121
|
+
dark: { primary: "#f0808c" },
|
|
122
|
+
radius: "0.5rem",
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Colors: `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.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
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,100 @@
|
|
|
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
|
+
var focusRing = "labui:focus-visible:border-ring labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50";
|
|
11
|
+
var invalidRing = "labui:aria-invalid:border-destructive labui:aria-invalid:ring-destructive/20 labui:dark:aria-invalid:ring-destructive/40";
|
|
12
|
+
var overlay = "labui:fixed labui:inset-0 labui:z-50 labui:bg-overlay labui:data-[state=open]:animate-fade-in labui:data-[state=closed]:animate-fade-out";
|
|
13
|
+
var closeButton = [
|
|
14
|
+
"labui:absolute labui:top-4 labui:right-4 labui:inline-flex labui:size-8 labui:items-center labui:justify-center labui:rounded-md",
|
|
15
|
+
"labui:text-muted-foreground labui:transition-colors labui:hover:bg-accent labui:hover:text-foreground",
|
|
16
|
+
"labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50 labui:focus-visible:outline-none labui:disabled:pointer-events-none",
|
|
17
|
+
"labui:[&_svg]:pointer-events-none labui:[&_svg]:size-4 labui:[&_svg]:shrink-0"
|
|
18
|
+
].join(" ");
|
|
19
|
+
var inputSurface = [
|
|
20
|
+
"labui:w-full labui:min-w-0 labui:rounded-md labui:border labui:border-input labui:bg-input-background labui:shadow-xs",
|
|
21
|
+
"labui:text-base labui:md:text-sm labui:placeholder:text-muted-foreground labui:transition-[color,box-shadow] labui:outline-none",
|
|
22
|
+
"labui:disabled:cursor-not-allowed labui:disabled:opacity-50",
|
|
23
|
+
focusRing,
|
|
24
|
+
invalidRing
|
|
25
|
+
].join(" ");
|
|
26
|
+
|
|
27
|
+
// button.tsx
|
|
28
|
+
import * as React from "react";
|
|
29
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
30
|
+
import { jsx } from "react/jsx-runtime";
|
|
31
|
+
var raisedButtonSurface = [
|
|
32
|
+
"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",
|
|
33
|
+
"labui:shadow-[inset_0_1px_0_#ffffff,0_1px_1px_#00000014,0_3px_4px_#0000000d]",
|
|
34
|
+
"labui:hover:to-background labui:hover:shadow-[inset_0_1px_0_#ffffff,0_2px_3px_#0000001a,0_4px_6px_#0000000d]",
|
|
35
|
+
"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]",
|
|
36
|
+
"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",
|
|
37
|
+
"labui:dark:shadow-[inset_0_1px_0_#ffffff14,0_1px_2px_#00000026]",
|
|
38
|
+
"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]",
|
|
39
|
+
"labui:dark:active:from-secondary labui:dark:active:to-secondary labui:dark:active:shadow-[inset_0_1px_2px_#00000033,0_1px_0_#ffffff0a]",
|
|
40
|
+
"labui:disabled:bg-secondary labui:disabled:bg-none labui:disabled:shadow-none labui:dark:disabled:shadow-none"
|
|
41
|
+
].join(" ");
|
|
42
|
+
var buttonVariants = {
|
|
43
|
+
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",
|
|
44
|
+
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",
|
|
45
|
+
outline: "labui:border labui:bg-background labui:shadow-xs labui:hover:bg-accent labui:hover:text-accent-foreground labui:dark:border-input labui:dark:bg-input/30 labui:dark:hover:bg-input/50",
|
|
46
|
+
secondary: raisedButtonSurface,
|
|
47
|
+
ghost: "labui:hover:bg-accent labui:hover:text-accent-foreground labui:dark:hover:bg-accent/50",
|
|
48
|
+
link: "labui:text-link labui:underline-offset-4 labui:hover:underline"
|
|
49
|
+
};
|
|
50
|
+
var buttonSizes = {
|
|
51
|
+
default: "labui:h-(--labui-control-height) labui:px-4 labui:py-2 labui:has-[>svg]:px-3",
|
|
52
|
+
xs: "labui:h-6 labui:gap-1 labui:rounded-md labui:px-2 labui:text-xs labui:has-[>svg]:px-1.5 labui:[&_svg:not([class*='size-'])]:size-3",
|
|
53
|
+
sm: "labui:h-(--labui-control-height-sm) labui:gap-1.5 labui:rounded-md labui:px-3 labui:has-[>svg]:px-2.5",
|
|
54
|
+
lg: "labui:h-11 labui:rounded-md labui:px-6 labui:has-[>svg]:px-4",
|
|
55
|
+
icon: "labui:size-(--labui-control-height)",
|
|
56
|
+
"icon-xs": "labui:size-6 labui:rounded-md labui:[&_svg:not([class*='size-'])]:size-3",
|
|
57
|
+
"icon-sm": "labui:size-(--labui-control-height-sm)",
|
|
58
|
+
"icon-lg": "labui:size-11"
|
|
59
|
+
};
|
|
60
|
+
var Button = React.forwardRef(function Button2({
|
|
61
|
+
className,
|
|
62
|
+
variant = "default",
|
|
63
|
+
size = "default",
|
|
64
|
+
asChild = false,
|
|
65
|
+
...props
|
|
66
|
+
}, ref) {
|
|
67
|
+
const Comp = asChild ? Slot : "button";
|
|
68
|
+
return /* @__PURE__ */ jsx(
|
|
69
|
+
Comp,
|
|
70
|
+
{
|
|
71
|
+
ref,
|
|
72
|
+
"data-slot": "button",
|
|
73
|
+
"data-variant": variant,
|
|
74
|
+
"data-size": size,
|
|
75
|
+
className: cn(
|
|
76
|
+
"labui:inline-flex labui:shrink-0 labui:items-center labui:justify-center labui:gap-2 labui:rounded-md",
|
|
77
|
+
"labui:text-sm labui:font-medium labui:whitespace-nowrap labui:transition-all labui:outline-none",
|
|
78
|
+
"labui:disabled:pointer-events-none labui:disabled:opacity-50",
|
|
79
|
+
focusRing,
|
|
80
|
+
invalidRing,
|
|
81
|
+
"labui:[&_svg]:pointer-events-none labui:[&_svg]:shrink-0 labui:[&_svg:not([class*='size-'])]:size-4",
|
|
82
|
+
variant && buttonVariants[variant],
|
|
83
|
+
size && buttonSizes[size],
|
|
84
|
+
className
|
|
85
|
+
),
|
|
86
|
+
...props
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
cn,
|
|
93
|
+
focusRing,
|
|
94
|
+
invalidRing,
|
|
95
|
+
overlay,
|
|
96
|
+
closeButton,
|
|
97
|
+
inputSurface,
|
|
98
|
+
Button
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=chunk-NR3PLNO7.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../classes.ts", "../button.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\nexport const focusRing =\n \"labui:focus-visible:border-ring labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50\";\n\nexport const invalidRing =\n \"labui:aria-invalid:border-destructive labui:aria-invalid:ring-destructive/20 labui:dark:aria-invalid:ring-destructive/40\";\n\nexport const overlay =\n \"labui:fixed labui:inset-0 labui:z-50 labui:bg-overlay labui:data-[state=open]:animate-fade-in labui:data-[state=closed]:animate-fade-out\";\n\nexport const closeButton = [\n \"labui:absolute labui:top-4 labui:right-4 labui:inline-flex labui:size-8 labui:items-center labui:justify-center labui:rounded-md\",\n \"labui:text-muted-foreground labui:transition-colors labui:hover:bg-accent labui:hover:text-foreground\",\n \"labui:focus-visible:ring-[3px] labui:focus-visible:ring-ring/50 labui:focus-visible:outline-none labui:disabled:pointer-events-none\",\n \"labui:[&_svg]:pointer-events-none labui:[&_svg]:size-4 labui:[&_svg]:shrink-0\",\n].join(\" \");\n\nexport const inputSurface = [\n \"labui:w-full labui:min-w-0 labui:rounded-md labui:border labui:border-input labui:bg-input-background 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:disabled:cursor-not-allowed labui:disabled:opacity-50\",\n focusRing,\n invalidRing,\n].join(\" \");\n", "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cn, focusRing, invalidRing } from \"./classes.js\";\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 outline:\n \"labui:border labui:bg-background labui:shadow-xs labui:hover:bg-accent labui:hover:text-accent-foreground labui:dark:border-input labui:dark:bg-input/30 labui:dark:hover:bg-input/50\",\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};\n\nconst buttonSizes = {\n default:\n \"labui:h-(--labui-control-height) labui:px-4 labui:py-2 labui:has-[>svg]:px-3\",\n xs: \"labui:h-6 labui:gap-1 labui:rounded-md labui:px-2 labui:text-xs labui:has-[>svg]:px-1.5 labui:[&_svg:not([class*='size-'])]:size-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 lg: \"labui:h-11 labui:rounded-md labui:px-6 labui:has-[>svg]:px-4\",\n icon: \"labui:size-(--labui-control-height)\",\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 \"icon-lg\": \"labui:size-11\",\n};\n\nexport type ButtonVariant = keyof typeof buttonVariants;\nexport type ButtonSize = keyof typeof buttonSizes;\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<\"button\"> & {\n variant?: ButtonVariant | null;\n size?: ButtonSize | 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"],
|
|
5
|
+
"mappings": ";AAAA,SAA0B,YAAY;AACtC,SAAS,2BAA2B;AAEpC,IAAM,UAAU,oBAAoB;AAAA,EAClC,4BAA4B,CAAC,EAAE,WAAW,eAAe,MACvD,eAAe,UAAU,QAAQ,WAAW,EAAE,CAAC;AACnD,CAAC;AAEM,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;AAEO,IAAM,YACX;AAEK,IAAM,cACX;AAEK,IAAM,UACX;AAEK,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEH,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;;;AClCV,YAAY,WAAW;AACvB,SAAS,YAAY;AAgEjB;AA7DJ,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEV,IAAM,iBAAiB;AAAA,EACrB,SACE;AAAA,EACF,aACE;AAAA,EACF,SACE;AAAA,EACF,WAAW;AAAA,EACX,OACE;AAAA,EACF,MAAM;AACR;AAEA,IAAM,cAAc;AAAA,EAClB,SACE;AAAA,EACF,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,WACE;AAAA,EACF,WAAW;AAAA,EACX,WAAW;AACb;AAKA,IAAM,SAAe,iBAOnB,SAASA,QACT;AAAA,EACE;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,UAAU;AAAA,EACV,GAAG;AACL,GACA,KACA;AACA,QAAM,OAAO,UAAU,OAAO;AAE9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,aAAW;AAAA,MACX,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,eAAe,OAAO;AAAA,QACjC,QAAQ,YAAY,IAAI;AAAA,QACxB;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;",
|
|
6
|
+
"names": ["Button"]
|
|
7
|
+
}
|