ajo-ui-playa 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +90 -0
- package/dist/accordion.js +41 -0
- package/dist/alert-dialog.js +88 -0
- package/dist/alert.js +49 -0
- package/dist/aspect-ratio.js +21 -0
- package/dist/attachment.js +126 -0
- package/dist/avatar.js +54 -0
- package/dist/breadcrumb.js +73 -0
- package/dist/bubble.js +91 -0
- package/dist/button-group.js +58 -0
- package/dist/button.js +72 -0
- package/dist/calendar.js +109 -0
- package/dist/card.js +98 -0
- package/dist/carousel.js +86 -0
- package/dist/chart.js +125 -0
- package/dist/checkbox-group.js +30 -0
- package/dist/checkbox.js +25 -0
- package/dist/chip.js +61 -0
- package/dist/chunks/modal-rE60kyB-.js +14 -0
- package/dist/chunks/recipes-CXxPSYdV.js +78 -0
- package/dist/chunks/scroll-area-BN7ME1Uj.js +14 -0
- package/dist/collapsible.js +35 -0
- package/dist/command.js +67 -0
- package/dist/context-menu.js +65 -0
- package/dist/data-table.js +16 -0
- package/dist/dialog.js +55 -0
- package/dist/direction.js +13 -0
- package/dist/drawer.js +61 -0
- package/dist/empty.js +64 -0
- package/dist/field.js +123 -0
- package/dist/index.js +306 -0
- package/dist/input-date.js +176 -0
- package/dist/input-group.js +70 -0
- package/dist/input-otp.js +50 -0
- package/dist/input.js +18 -0
- package/dist/item.js +126 -0
- package/dist/kbd.js +22 -0
- package/dist/label.js +14 -0
- package/dist/marker.js +68 -0
- package/dist/menu.js +66 -0
- package/dist/menubar.js +77 -0
- package/dist/message-scroller.js +76 -0
- package/dist/message.js +59 -0
- package/dist/navigation-menu.js +49 -0
- package/dist/pagination.js +93 -0
- package/dist/popover.js +20 -0
- package/dist/progress.js +16 -0
- package/dist/radio-group.js +26 -0
- package/dist/resizable.js +41 -0
- package/dist/scroll-area.js +19 -0
- package/dist/select.js +133 -0
- package/dist/separator.js +17 -0
- package/dist/sidebar.js +161 -0
- package/dist/skeleton.js +15 -0
- package/dist/slider.js +39 -0
- package/dist/spinner.js +28 -0
- package/dist/switch.js +26 -0
- package/dist/table.js +70 -0
- package/dist/tabs.js +61 -0
- package/dist/textarea.js +18 -0
- package/dist/toast.js +219 -0
- package/dist/toggle-group.js +62 -0
- package/dist/toggle.js +30 -0
- package/dist/toolbar.js +19 -0
- package/dist/tooltip.js +27 -0
- package/dist/typography.js +168 -0
- package/dist/virtual-list.js +17 -0
- package/package.json +379 -0
- package/src/accordion.tsx +87 -0
- package/src/alert-dialog.tsx +174 -0
- package/src/alert.tsx +121 -0
- package/src/aspect-ratio.tsx +39 -0
- package/src/attachment.tsx +255 -0
- package/src/avatar.tsx +131 -0
- package/src/breadcrumb.tsx +162 -0
- package/src/bubble.tsx +204 -0
- package/src/button-group.tsx +140 -0
- package/src/button.tsx +164 -0
- package/src/calendar.tsx +193 -0
- package/src/card.tsx +198 -0
- package/src/carousel.tsx +193 -0
- package/src/chart.tsx +269 -0
- package/src/checkbox-group.tsx +72 -0
- package/src/checkbox.tsx +42 -0
- package/src/chip.tsx +138 -0
- package/src/collapsible.tsx +76 -0
- package/src/command.tsx +137 -0
- package/src/context-menu.tsx +124 -0
- package/src/data-table.tsx +35 -0
- package/src/dialog.tsx +115 -0
- package/src/direction.tsx +29 -0
- package/src/drawer.tsx +104 -0
- package/src/empty.tsx +111 -0
- package/src/field.tsx +304 -0
- package/src/index.ts +1 -0
- package/src/input-date.tsx +294 -0
- package/src/input-group.tsx +189 -0
- package/src/input-otp.tsx +106 -0
- package/src/input.tsx +29 -0
- package/src/internal/recipes.tsx +131 -0
- package/src/internal/scroll-area.tsx +19 -0
- package/src/item.tsx +218 -0
- package/src/kbd.tsx +24 -0
- package/src/label.tsx +28 -0
- package/src/marker.tsx +120 -0
- package/src/menu.tsx +136 -0
- package/src/menubar.tsx +138 -0
- package/src/message-scroller.tsx +168 -0
- package/src/message.tsx +111 -0
- package/src/modal.tsx +17 -0
- package/src/navigation-menu.tsx +93 -0
- package/src/pagination.tsx +196 -0
- package/src/popover.tsx +30 -0
- package/src/progress.tsx +39 -0
- package/src/radio-group.tsx +62 -0
- package/src/resizable.tsx +111 -0
- package/src/scroll-area.tsx +32 -0
- package/src/select.tsx +225 -0
- package/src/separator.tsx +34 -0
- package/src/sidebar.tsx +405 -0
- package/src/skeleton.tsx +28 -0
- package/src/slider.tsx +59 -0
- package/src/spinner.tsx +41 -0
- package/src/styles.ts +434 -0
- package/src/switch.tsx +45 -0
- package/src/table.tsx +149 -0
- package/src/tabs.tsx +176 -0
- package/src/textarea.tsx +30 -0
- package/src/toast.tsx +416 -0
- package/src/toggle-group.tsx +128 -0
- package/src/toggle.tsx +62 -0
- package/src/toolbar.tsx +26 -0
- package/src/tooltip.tsx +51 -0
- package/src/typography.tsx +231 -0
- package/src/virtual-list.tsx +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026, Cristian Falcone
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
14
|
+
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# ajo-ui-playa
|
|
2
|
+
|
|
3
|
+
Themed Ajo component library and UnoCSS preset.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add ajo ajo-ui-playa
|
|
9
|
+
pnpm add -D unocss@66.7.2
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`ajo-ui-playa` requires `ajo ^0.1.35` and `unocss 66.7.2`.
|
|
13
|
+
|
|
14
|
+
## UnoCSS Setup
|
|
15
|
+
|
|
16
|
+
Add `playa()` to the application's UnoCSS config:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// uno.config.ts
|
|
20
|
+
import { playa } from 'ajo-ui-playa'
|
|
21
|
+
import { defineConfig } from 'unocss'
|
|
22
|
+
|
|
23
|
+
export default defineConfig({
|
|
24
|
+
presets: [playa()],
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Add the UnoCSS plugin to the application's Vite config:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// vite.config.ts
|
|
32
|
+
import { defineConfig } from 'vite'
|
|
33
|
+
import unocss from 'unocss/vite'
|
|
34
|
+
|
|
35
|
+
export default defineConfig({
|
|
36
|
+
plugins: [unocss()],
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Load the generated stylesheet from the application entry:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import 'virtual:uno.css'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### With ajo-kit
|
|
47
|
+
|
|
48
|
+
`ajo-kit` can load the stylesheet before hydration:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { kit, jsx } from 'ajo-kit/vite'
|
|
52
|
+
import { defineConfig } from 'vite'
|
|
53
|
+
import unocss from 'unocss/vite'
|
|
54
|
+
|
|
55
|
+
export default defineConfig({
|
|
56
|
+
plugins: [...kit({ css: ['virtual:uno.css'] }), unocss()],
|
|
57
|
+
esbuild: jsx,
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
Import `playa()` from the package root. Import components from family subpaths:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import Button, { buttonVariants } from 'ajo-ui-playa/button'
|
|
67
|
+
import { Card, CardContent } from 'ajo-ui-playa/card'
|
|
68
|
+
import { DataTable, type DataTableColumn } from 'ajo-ui-playa/data-table'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Family subpath imports are side-effect-free and tree-shakeable.
|
|
72
|
+
|
|
73
|
+
## Components
|
|
74
|
+
|
|
75
|
+
| Group | Family subpaths |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Actions and status | `alert`, `alert-dialog`, `button`, `button-group`, `chip`, `marker`, `spinner` |
|
|
78
|
+
| Content and layout | `aspect-ratio`, `attachment`, `breadcrumb`, `bubble`, `card`, `empty`, `item`, `kbd`, `label`, `pagination`, `scroll-area`, `separator`, `skeleton`, `table`, `typography` |
|
|
79
|
+
| Inputs and selection | `checkbox`, `checkbox-group`, `field`, `input`, `input-date`, `input-group`, `input-otp`, `radio-group`, `select`, `slider`, `switch`, `textarea`, `toggle`, `toggle-group` |
|
|
80
|
+
| Navigation and overlays | `accordion`, `collapsible`, `command`, `context-menu`, `dialog`, `direction`, `drawer`, `menu`, `menubar`, `navigation-menu`, `popover`, `sidebar`, `tabs`, `toast`, `toolbar`, `tooltip` |
|
|
81
|
+
| Data and media | `avatar`, `calendar`, `carousel`, `chart`, `data-table`, `message`, `message-scroller`, `progress`, `resizable`, `virtual-list` |
|
|
82
|
+
|
|
83
|
+
## UnoCSS Preset
|
|
84
|
+
|
|
85
|
+
`playa()` configures Wind4, Lucide icons, Playa design tokens, preflights,
|
|
86
|
+
variants, rules, and component shortcuts.
|
|
87
|
+
|
|
88
|
+
UnoCSS discovers classes from imported component families. Define application
|
|
89
|
+
shortcuts in `uno.config.ts` and add dynamically generated icon names to the
|
|
90
|
+
application safelist.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import { c as disclosureContent } from "./chunks/recipes-CXxPSYdV.js";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { Accordion as Accordion$1, AccordionContent as AccordionContent$1, AccordionItem as AccordionItem$1, AccordionTrigger as AccordionTrigger$1 } from "ajo-ui/accordion";
|
|
5
|
+
import { jsx, jsxs } from "ajo/jsx-runtime";
|
|
6
|
+
//#region packages/ajo-ui-playa/src/accordion.tsx
|
|
7
|
+
var itemBase = clsx("border-b last:border-b-0", disclosureContent);
|
|
8
|
+
var triggerBase = "flex flex-1 cursor-pointer list-none items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none focus-visible:ring-3 focus-visible:ring-ring/50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&::-webkit-details-marker]:hidden [&[data-state=open]>[data-accordion-chevron]]:rotate-180";
|
|
9
|
+
/** Root provider for accordion state. */
|
|
10
|
+
var Accordion = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsx(Accordion$1, {
|
|
11
|
+
...attrs,
|
|
12
|
+
class: classes
|
|
13
|
+
});
|
|
14
|
+
/** Accordion section rendered as a native details element. */
|
|
15
|
+
var AccordionItem = ({ children, class: classes, disabled, open: _open, value, ...attrs }) => /* @__PURE__ */ jsx(AccordionItem$1, {
|
|
16
|
+
...attrs,
|
|
17
|
+
class: clsx(itemBase, classes),
|
|
18
|
+
disabled,
|
|
19
|
+
value,
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
/** Accordion heading trigger rendered as a native summary element. */
|
|
23
|
+
var AccordionTrigger = ({ children, class: classes, "set:onclick": onClick, ...attrs }) => /* @__PURE__ */ jsxs(AccordionTrigger$1, {
|
|
24
|
+
...attrs,
|
|
25
|
+
class: clsx(triggerBase, classes),
|
|
26
|
+
"set:onclick": onClick,
|
|
27
|
+
children: [children, /* @__PURE__ */ jsx("span", {
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
"data-accordion-chevron": true,
|
|
30
|
+
class: "i-lucide-chevron-down pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200"
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
/** Accordion panel content. */
|
|
34
|
+
var AccordionContent = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx(AccordionContent$1, {
|
|
35
|
+
...attrs,
|
|
36
|
+
class: "overflow-hidden text-sm",
|
|
37
|
+
innerClass: clsx("pb-4 pt-0", classes),
|
|
38
|
+
children
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import { buttonVariants } from "./button.js";
|
|
3
|
+
import { DialogContent as DialogContent$1, DialogDescription as DialogDescription$1 } from "./dialog.js";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
6
|
+
import { Dialog, DialogClose, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "ajo-ui/dialog";
|
|
7
|
+
//#region packages/ajo-ui-playa/src/alert-dialog.tsx
|
|
8
|
+
var contentBase = "data-[size=sm]:max-w-xs sm:data-[size=default]:max-w-lg";
|
|
9
|
+
var headerBase = "grid grid-rows-[auto_1fr] place-items-center text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:[[data-slot=alert-dialog-content][data-size=default]_&]:place-items-start sm:[[data-slot=alert-dialog-content][data-size=default]_&]:text-left sm:[[data-slot=alert-dialog-content][data-size=default]_&:has([data-slot=alert-dialog-media])]:grid-rows-[auto_1fr]";
|
|
10
|
+
var footerBase = "flex flex-col-reverse gap-2 [[data-slot=alert-dialog-content][data-size=sm]_&]:grid [[data-slot=alert-dialog-content][data-size=sm]_&]:grid-cols-2 sm:flex-row sm:justify-end";
|
|
11
|
+
var titleBase = "text-lg font-semibold sm:[[data-slot=alert-dialog-content][data-size=default]:has([data-slot=alert-dialog-media])_&]:col-start-2";
|
|
12
|
+
var mediaBase = "mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:[[data-slot=alert-dialog-content][data-size=default]_&]:row-span-2 [&>svg:not([class*=size-])]:size-8";
|
|
13
|
+
/** Root provider for a modal alert dialog that requires a user response. */
|
|
14
|
+
var AlertDialog = (attrs) => /* @__PURE__ */ jsx(Dialog, {
|
|
15
|
+
...attrs,
|
|
16
|
+
modal: true,
|
|
17
|
+
"data-slot": "alert-dialog"
|
|
18
|
+
});
|
|
19
|
+
/** Button that opens the nearest AlertDialog. */
|
|
20
|
+
var AlertDialogTrigger = (attrs) => /* @__PURE__ */ jsx(DialogTrigger, {
|
|
21
|
+
...attrs,
|
|
22
|
+
"data-slot": "alert-dialog-trigger"
|
|
23
|
+
});
|
|
24
|
+
/** Native modal alert dialog panel. */
|
|
25
|
+
var AlertDialogContent = ({ class: classes, size = "default", ...attrs }) => /* @__PURE__ */ jsx(DialogContent$1, {
|
|
26
|
+
...attrs,
|
|
27
|
+
class: clsx(contentBase, classes),
|
|
28
|
+
"data-size": size,
|
|
29
|
+
"data-slot": "alert-dialog-content",
|
|
30
|
+
onPointerDownOutside: (event) => event.preventDefault(),
|
|
31
|
+
role: "alertdialog",
|
|
32
|
+
showCloseButton: false,
|
|
33
|
+
unstyled: false
|
|
34
|
+
});
|
|
35
|
+
/** Header area for alert dialog title, description, and optional media. */
|
|
36
|
+
var AlertDialogHeader = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsx(DialogHeader, {
|
|
37
|
+
...attrs,
|
|
38
|
+
class: clsx(headerBase, classes),
|
|
39
|
+
"data-slot": "alert-dialog-header"
|
|
40
|
+
});
|
|
41
|
+
/** Footer area for alert dialog cancel and action buttons. */
|
|
42
|
+
var AlertDialogFooter = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsx(DialogFooter, {
|
|
43
|
+
...attrs,
|
|
44
|
+
class: clsx(footerBase, classes),
|
|
45
|
+
"data-slot": "alert-dialog-footer"
|
|
46
|
+
});
|
|
47
|
+
/** Accessible title for AlertDialogContent. */
|
|
48
|
+
var AlertDialogTitle = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsx(DialogTitle, {
|
|
49
|
+
...attrs,
|
|
50
|
+
class: clsx(titleBase, classes),
|
|
51
|
+
"data-slot": "alert-dialog-title"
|
|
52
|
+
});
|
|
53
|
+
/** Accessible description for AlertDialogContent. */
|
|
54
|
+
var AlertDialogDescription = (attrs) => /* @__PURE__ */ jsx(DialogDescription$1, {
|
|
55
|
+
...attrs,
|
|
56
|
+
"data-slot": "alert-dialog-description"
|
|
57
|
+
});
|
|
58
|
+
/** Optional media block for an icon or image in the alert dialog header. */
|
|
59
|
+
var AlertDialogMedia = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
60
|
+
...attrs,
|
|
61
|
+
class: clsx(mediaBase, classes),
|
|
62
|
+
"data-slot": "alert-dialog-media",
|
|
63
|
+
children
|
|
64
|
+
});
|
|
65
|
+
/** Primary alert dialog action button. Closes unless its click handler prevents default. */
|
|
66
|
+
var AlertDialogAction = ({ children, class: classes, size = "default", variant = "default", ...attrs }) => /* @__PURE__ */ jsx(DialogClose, {
|
|
67
|
+
...attrs,
|
|
68
|
+
class: buttonVariants({
|
|
69
|
+
class: classes,
|
|
70
|
+
size,
|
|
71
|
+
variant
|
|
72
|
+
}),
|
|
73
|
+
"data-slot": "alert-dialog-action",
|
|
74
|
+
children
|
|
75
|
+
});
|
|
76
|
+
/** Cancel button. Closes unless its click handler prevents default. */
|
|
77
|
+
var AlertDialogCancel = ({ children, class: classes, size = "default", variant = "outline", ...attrs }) => /* @__PURE__ */ jsx(DialogClose, {
|
|
78
|
+
...attrs,
|
|
79
|
+
class: buttonVariants({
|
|
80
|
+
class: classes,
|
|
81
|
+
size,
|
|
82
|
+
variant
|
|
83
|
+
}),
|
|
84
|
+
"data-slot": "alert-dialog-cancel",
|
|
85
|
+
children
|
|
86
|
+
});
|
|
87
|
+
//#endregion
|
|
88
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogTitle, AlertDialogTrigger };
|
package/dist/alert.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
4
|
+
//#region packages/ajo-ui-playa/src/alert.tsx
|
|
5
|
+
var base = "relative grid w-full grid-cols-[0_1fr_auto] items-start gap-y-0.5 rounded-lg edge px-4 py-3 text-sm has-[>svg]:grid-cols-[1rem_1fr_auto] has-[>svg]:gap-x-3 has-[>[data-slot=alert-icon]]:grid-cols-[1rem_1fr_auto] has-[>[data-slot=alert-icon]]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current [&>[data-slot=alert-icon]]:size-4 [&>[data-slot=alert-icon]]:translate-y-0.5 [&>[data-slot=alert-icon]]:text-current";
|
|
6
|
+
var variants = {
|
|
7
|
+
default: "bg-card/80 text-card-foreground shadow-xs",
|
|
8
|
+
danger: "bg-danger/10 text-danger inset-ring-danger/25 [&_[data-slot=alert-description]]:text-danger/85",
|
|
9
|
+
success: "bg-success/10 text-success inset-ring-success/25 [&_[data-slot=alert-description]]:text-success/85",
|
|
10
|
+
warning: "bg-warning/10 text-warning inset-ring-warning/25 [&_[data-slot=alert-description]]:text-warning/85",
|
|
11
|
+
info: "bg-info/10 text-info inset-ring-info/25 [&_[data-slot=alert-description]]:text-info/85"
|
|
12
|
+
};
|
|
13
|
+
/** Returns the UnoCSS class list for an alert variant. */
|
|
14
|
+
var alertVariants = ({ class: classes, variant = "default" } = {}) => clsx(base, variants[variant], classes);
|
|
15
|
+
/** Callout for important user attention. */
|
|
16
|
+
var Alert = ({ class: classes, children, role = "alert", variant = "default", ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
17
|
+
...attrs,
|
|
18
|
+
class: alertVariants({
|
|
19
|
+
class: classes,
|
|
20
|
+
variant
|
|
21
|
+
}),
|
|
22
|
+
"data-slot": "alert",
|
|
23
|
+
"data-variant": variant,
|
|
24
|
+
role,
|
|
25
|
+
children
|
|
26
|
+
});
|
|
27
|
+
/** Title slot for `Alert`. */
|
|
28
|
+
var AlertTitle = ({ class: classes, children, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
29
|
+
...attrs,
|
|
30
|
+
class: clsx("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", classes),
|
|
31
|
+
"data-slot": "alert-title",
|
|
32
|
+
children
|
|
33
|
+
});
|
|
34
|
+
/** Description/content slot for `Alert`. */
|
|
35
|
+
var AlertDescription = ({ class: classes, children, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
36
|
+
...attrs,
|
|
37
|
+
class: clsx("col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed", classes),
|
|
38
|
+
"data-slot": "alert-description",
|
|
39
|
+
children
|
|
40
|
+
});
|
|
41
|
+
/** Action slot for `Alert`, aligned to the end on wider screens. */
|
|
42
|
+
var AlertAction = ({ class: classes, children, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
43
|
+
...attrs,
|
|
44
|
+
class: clsx("col-start-2 mt-3 flex flex-wrap gap-2 sm:col-start-3 sm:row-span-2 sm:row-start-1 sm:mt-0 sm:justify-self-end sm:ps-3", classes),
|
|
45
|
+
"data-slot": "alert-action",
|
|
46
|
+
children
|
|
47
|
+
});
|
|
48
|
+
//#endregion
|
|
49
|
+
export { Alert, Alert as default, AlertAction, AlertDescription, AlertTitle, alertVariants };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
4
|
+
import { stlx } from "ajo-ui/utils";
|
|
5
|
+
//#region packages/ajo-ui-playa/src/aspect-ratio.tsx
|
|
6
|
+
var base = "relative w-full";
|
|
7
|
+
var ratioValue = (ratio) => Number.isFinite(ratio) && ratio > 0 ? String(ratio) : "1";
|
|
8
|
+
/** Responsive box that preserves a width-to-height ratio. */
|
|
9
|
+
var AspectRatio = ({ class: classes, children, ratio, style, ...attrs }) => {
|
|
10
|
+
const value = ratioValue(ratio);
|
|
11
|
+
return /* @__PURE__ */ jsx("div", {
|
|
12
|
+
...attrs,
|
|
13
|
+
class: clsx(base, classes),
|
|
14
|
+
"data-ratio": value,
|
|
15
|
+
"data-slot": "aspect-ratio",
|
|
16
|
+
style: stlx(style, { aspectRatio: value }),
|
|
17
|
+
children
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { AspectRatio, AspectRatio as default };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import { buttonVariants } from "./button.js";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
5
|
+
//#region packages/ajo-ui-playa/src/attachment.tsx
|
|
6
|
+
var rootBase = [
|
|
7
|
+
"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl glass edge shadow-xs transition-colors",
|
|
8
|
+
"focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50",
|
|
9
|
+
"data-[state=error]:inset-ring-danger/25 data-[state=idle]:inset-ring-transparent data-[state=idle]:border data-[state=idle]:border-dashed"
|
|
10
|
+
].join(" ");
|
|
11
|
+
var rootSizes = {
|
|
12
|
+
default: "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
|
|
13
|
+
sm: "gap-2 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
|
|
14
|
+
xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1"
|
|
15
|
+
};
|
|
16
|
+
var rootOrientations = {
|
|
17
|
+
horizontal: "min-w-40 items-center",
|
|
18
|
+
vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30"
|
|
19
|
+
};
|
|
20
|
+
var mediaBase = [
|
|
21
|
+
"relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted text-foreground",
|
|
22
|
+
"group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=sm]/attachment:rounded-sm group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-sm",
|
|
23
|
+
"group-data-[state=error]/attachment:bg-danger/10 group-data-[state=error]/attachment:text-danger",
|
|
24
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4",
|
|
25
|
+
"group-data-[orientation=vertical]/attachment:[&_svg:not([class*=size-])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*=size-])]:size-3.5"
|
|
26
|
+
].join(" ");
|
|
27
|
+
var mediaVariants = {
|
|
28
|
+
icon: "",
|
|
29
|
+
image: "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 [&>img]:aspect-square [&>img]:size-full [&>img]:object-cover"
|
|
30
|
+
};
|
|
31
|
+
var contentBase = "max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1";
|
|
32
|
+
var titleBase = "block max-w-full min-w-0 truncate font-medium";
|
|
33
|
+
var descriptionBase = "mt-0.5 block max-w-full min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-danger/80";
|
|
34
|
+
var actionsBase = "relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:gap-1";
|
|
35
|
+
var triggerBase = "absolute inset-0 z-10 outline-none focus-visible:ring-3 focus-visible:ring-ring/50";
|
|
36
|
+
var groupBase = "flex min-w-0 items-start scroll-fade-x snap-x snap-mandatory scroll-px-4 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain px-4 py-1 [&>[data-slot=attachment]]:flex-none [&>[data-slot=attachment]]:snap-start";
|
|
37
|
+
/** Root attachment container for files, images, upload rows, and chat attachments. */
|
|
38
|
+
var Attachment = ({ children, class: classes, orientation = "horizontal", size = "default", state = "done", ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
39
|
+
...attrs,
|
|
40
|
+
class: clsx(rootBase, rootSizes[size], rootOrientations[orientation], classes),
|
|
41
|
+
"data-orientation": orientation,
|
|
42
|
+
"data-size": size,
|
|
43
|
+
"data-slot": "attachment",
|
|
44
|
+
"data-state": state,
|
|
45
|
+
children
|
|
46
|
+
});
|
|
47
|
+
/** Media slot for icons, thumbnails, or image previews. */
|
|
48
|
+
var AttachmentMedia = ({ children, class: classes, variant = "icon", ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
49
|
+
...attrs,
|
|
50
|
+
class: clsx(mediaBase, mediaVariants[variant], classes),
|
|
51
|
+
"data-slot": "attachment-media",
|
|
52
|
+
"data-variant": variant,
|
|
53
|
+
children
|
|
54
|
+
});
|
|
55
|
+
/** Content slot wrapping title and description. */
|
|
56
|
+
var AttachmentContent = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
57
|
+
...attrs,
|
|
58
|
+
class: clsx(contentBase, classes),
|
|
59
|
+
"data-slot": "attachment-content",
|
|
60
|
+
children
|
|
61
|
+
});
|
|
62
|
+
/** Attachment display name. */
|
|
63
|
+
var AttachmentTitle = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("span", {
|
|
64
|
+
...attrs,
|
|
65
|
+
class: clsx(titleBase, classes),
|
|
66
|
+
"data-slot": "attachment-title",
|
|
67
|
+
children
|
|
68
|
+
});
|
|
69
|
+
/** Secondary metadata such as type, size, upload status, or error reason. */
|
|
70
|
+
var AttachmentDescription = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("span", {
|
|
71
|
+
...attrs,
|
|
72
|
+
class: clsx(descriptionBase, classes),
|
|
73
|
+
"data-slot": "attachment-description",
|
|
74
|
+
children
|
|
75
|
+
});
|
|
76
|
+
/** Action container aligned to the edge of the attachment. */
|
|
77
|
+
var AttachmentActions = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
78
|
+
...attrs,
|
|
79
|
+
class: clsx(actionsBase, classes),
|
|
80
|
+
"data-slot": "attachment-actions",
|
|
81
|
+
children
|
|
82
|
+
});
|
|
83
|
+
/** Icon-sized action button for attachment operations. */
|
|
84
|
+
var AttachmentAction = ({ children, class: classes, size = "icon-xs", type = "button", variant = "ghost", ...attrs }) => /* @__PURE__ */ jsx("button", {
|
|
85
|
+
...attrs,
|
|
86
|
+
class: buttonVariants({
|
|
87
|
+
class: classes,
|
|
88
|
+
size,
|
|
89
|
+
variant
|
|
90
|
+
}),
|
|
91
|
+
"data-size": size,
|
|
92
|
+
"data-slot": "attachment-action",
|
|
93
|
+
"data-variant": variant,
|
|
94
|
+
type,
|
|
95
|
+
children
|
|
96
|
+
});
|
|
97
|
+
/** Full-card trigger layered behind actions. */
|
|
98
|
+
var AttachmentTrigger = ({ as = "button", children, class: classes, type = "button", ...attrs }) => {
|
|
99
|
+
const styles = clsx(triggerBase, classes);
|
|
100
|
+
if (as === "a") {
|
|
101
|
+
const anchor = attrs;
|
|
102
|
+
return /* @__PURE__ */ jsx("a", {
|
|
103
|
+
...anchor,
|
|
104
|
+
class: styles,
|
|
105
|
+
"data-slot": "attachment-trigger",
|
|
106
|
+
href: String(anchor.href),
|
|
107
|
+
children
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return /* @__PURE__ */ jsx("button", {
|
|
111
|
+
...attrs,
|
|
112
|
+
class: styles,
|
|
113
|
+
"data-slot": "attachment-trigger",
|
|
114
|
+
type,
|
|
115
|
+
children
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
/** Horizontally scrollable attachment row with snap points and edge fade. */
|
|
119
|
+
var AttachmentGroup = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
120
|
+
...attrs,
|
|
121
|
+
class: clsx(groupBase, classes),
|
|
122
|
+
"data-slot": "attachment-group",
|
|
123
|
+
children
|
|
124
|
+
});
|
|
125
|
+
//#endregion
|
|
126
|
+
export { Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger };
|
package/dist/avatar.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
4
|
+
import { Avatar as Avatar$1, AvatarBadge as AvatarBadge$1, AvatarFallback as AvatarFallback$1, AvatarGroup as AvatarGroup$1, AvatarGroupCount as AvatarGroupCount$1, AvatarImage as AvatarImage$1 } from "ajo-ui/avatar";
|
|
5
|
+
//#region packages/ajo-ui-playa/src/avatar.tsx
|
|
6
|
+
var avatarBase = "group/avatar relative flex size-8 shrink-0 rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6";
|
|
7
|
+
var imageBase = "absolute inset-0 aspect-square size-full rounded-full object-cover";
|
|
8
|
+
var fallbackBase = "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs group-data-[size=lg]/avatar:text-base";
|
|
9
|
+
var badgeBase = [
|
|
10
|
+
"absolute bottom-0 right-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground ring-2 ring-background select-none",
|
|
11
|
+
"[&:not(:has(>*))]:size-2.5 group-data-[size=sm]/avatar:[&:not(:has(>*))]:size-2 group-data-[size=lg]/avatar:[&:not(:has(>*))]:size-3",
|
|
12
|
+
"[&:has(>*)]:size-4 group-data-[size=lg]/avatar:[&:has(>*)]:size-5 group-data-[size=sm]/avatar:[&:has(>*)]:hidden",
|
|
13
|
+
"[&>*]:size-2.5 group-data-[size=lg]/avatar:[&>*]:size-3"
|
|
14
|
+
].join(" ");
|
|
15
|
+
var groupBase = "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background";
|
|
16
|
+
var groupCountBase = "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background [[data-slot=avatar-group]:has([data-size=lg])_&]:size-10 [[data-slot=avatar-group]:has([data-size=sm])_&]:size-6 [&>svg]:size-4 [[data-slot=avatar-group]:has([data-size=lg])_&>svg]:size-5 [[data-slot=avatar-group]:has([data-size=sm])_&>svg]:size-3";
|
|
17
|
+
/** Avatar root that wraps image, fallback, and optional badge. */
|
|
18
|
+
var Avatar = ({ children, class: classes, size = "default", ...attrs }) => /* @__PURE__ */ jsx(Avatar$1, {
|
|
19
|
+
...attrs,
|
|
20
|
+
class: clsx(avatarBase, classes),
|
|
21
|
+
size,
|
|
22
|
+
children
|
|
23
|
+
});
|
|
24
|
+
/** Avatar image. It hides itself after load errors so the fallback remains visible. */
|
|
25
|
+
var AvatarImage = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsx(AvatarImage$1, {
|
|
26
|
+
...attrs,
|
|
27
|
+
class: clsx(imageBase, classes)
|
|
28
|
+
});
|
|
29
|
+
/** Avatar fallback content shown behind the image and after image errors. */
|
|
30
|
+
var AvatarFallback = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx(AvatarFallback$1, {
|
|
31
|
+
...attrs,
|
|
32
|
+
class: clsx(fallbackBase, classes),
|
|
33
|
+
children
|
|
34
|
+
});
|
|
35
|
+
/** Small status badge positioned at the bottom-right of an avatar. */
|
|
36
|
+
var AvatarBadge = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx(AvatarBadge$1, {
|
|
37
|
+
...attrs,
|
|
38
|
+
class: clsx(badgeBase, classes),
|
|
39
|
+
children
|
|
40
|
+
});
|
|
41
|
+
/** Overlapping avatar group. */
|
|
42
|
+
var AvatarGroup = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx(AvatarGroup$1, {
|
|
43
|
+
...attrs,
|
|
44
|
+
class: clsx(groupBase, classes),
|
|
45
|
+
children
|
|
46
|
+
});
|
|
47
|
+
/** Count avatar for extra members in an avatar group. */
|
|
48
|
+
var AvatarGroupCount = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx(AvatarGroupCount$1, {
|
|
49
|
+
...attrs,
|
|
50
|
+
class: clsx(groupCountBase, classes),
|
|
51
|
+
children
|
|
52
|
+
});
|
|
53
|
+
//#endregion
|
|
54
|
+
export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { jsx, jsxs } from "ajo/jsx-runtime";
|
|
4
|
+
import { emptyChildren } from "ajo-ui/utils";
|
|
5
|
+
//#region packages/ajo-ui-playa/src/breadcrumb.tsx
|
|
6
|
+
/** Landmark wrapper for breadcrumb navigation. */
|
|
7
|
+
var Breadcrumb = ({ children, "aria-label": ariaLabel = "breadcrumb", class: classes, ...attrs }) => /* @__PURE__ */ jsx("nav", {
|
|
8
|
+
...attrs,
|
|
9
|
+
"aria-label": ariaLabel,
|
|
10
|
+
class: classes,
|
|
11
|
+
"data-slot": "breadcrumb",
|
|
12
|
+
children
|
|
13
|
+
});
|
|
14
|
+
/** Ordered breadcrumb item list. */
|
|
15
|
+
var BreadcrumbList = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("ol", {
|
|
16
|
+
...attrs,
|
|
17
|
+
class: clsx("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", classes),
|
|
18
|
+
"data-slot": "breadcrumb-list",
|
|
19
|
+
children
|
|
20
|
+
});
|
|
21
|
+
/** Single breadcrumb list item. */
|
|
22
|
+
var BreadcrumbItem = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("li", {
|
|
23
|
+
...attrs,
|
|
24
|
+
class: clsx("inline-flex items-center gap-1.5", classes),
|
|
25
|
+
"data-slot": "breadcrumb-item",
|
|
26
|
+
children
|
|
27
|
+
});
|
|
28
|
+
/** Clickable breadcrumb link. */
|
|
29
|
+
var BreadcrumbLink = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("a", {
|
|
30
|
+
...attrs,
|
|
31
|
+
class: clsx("transition-colors hover:text-foreground", classes),
|
|
32
|
+
"data-slot": "breadcrumb-link",
|
|
33
|
+
children
|
|
34
|
+
});
|
|
35
|
+
/** Current page marker inside a breadcrumb. */
|
|
36
|
+
var BreadcrumbPage = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("span", {
|
|
37
|
+
...attrs,
|
|
38
|
+
"aria-current": "page",
|
|
39
|
+
"aria-disabled": "true",
|
|
40
|
+
class: clsx("font-normal text-foreground", classes),
|
|
41
|
+
"data-slot": "breadcrumb-page",
|
|
42
|
+
role: "link",
|
|
43
|
+
children
|
|
44
|
+
});
|
|
45
|
+
/** Decorative separator between breadcrumb items. */
|
|
46
|
+
var BreadcrumbSeparator = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("li", {
|
|
47
|
+
...attrs,
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
class: clsx("inline-flex items-center justify-center [&>svg]:size-3.5", classes),
|
|
50
|
+
"data-slot": "breadcrumb-separator",
|
|
51
|
+
role: "presentation",
|
|
52
|
+
children: emptyChildren(children) ? /* @__PURE__ */ jsx("span", {
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
class: "i-lucide-chevron-right block size-3.5 shrink-0 text-muted-foreground"
|
|
55
|
+
}) : children
|
|
56
|
+
});
|
|
57
|
+
/** Collapsed breadcrumb range indicator. */
|
|
58
|
+
var BreadcrumbEllipsis = ({ class: classes, ...attrs }) => /* @__PURE__ */ jsxs("span", {
|
|
59
|
+
...attrs,
|
|
60
|
+
"aria-hidden": "true",
|
|
61
|
+
class: clsx("flex size-9 items-center justify-center", classes),
|
|
62
|
+
"data-slot": "breadcrumb-ellipsis",
|
|
63
|
+
role: "presentation",
|
|
64
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
65
|
+
"aria-hidden": "true",
|
|
66
|
+
class: "i-lucide-ellipsis size-4"
|
|
67
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
68
|
+
class: "sr-only",
|
|
69
|
+
children: "More"
|
|
70
|
+
})]
|
|
71
|
+
});
|
|
72
|
+
//#endregion
|
|
73
|
+
export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator };
|
package/dist/bubble.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { jsx } from "ajo/jsx-runtime";
|
|
4
|
+
//#region packages/ajo-ui-playa/src/bubble.tsx
|
|
5
|
+
var groupBase = [
|
|
6
|
+
"flex min-w-0 flex-col gap-1",
|
|
7
|
+
"[&>[data-slot=bubble]:not(:last-child)>[data-slot=bubble-content]]:rounded-bl-2xl",
|
|
8
|
+
"[&>[data-slot=bubble]:not(:last-child)>[data-slot=bubble-content]]:rounded-br-2xl"
|
|
9
|
+
].join(" ");
|
|
10
|
+
var rootBase = ["group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1", "group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full"].join(" ");
|
|
11
|
+
var rootVariants = {
|
|
12
|
+
default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/90",
|
|
13
|
+
secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-secondary/80",
|
|
14
|
+
muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/80",
|
|
15
|
+
tinted: "*:data-[slot=bubble-content]:bg-primary/10 *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/15",
|
|
16
|
+
outline: "*:data-[slot=bubble-content]:bg-card/80 *:data-[slot=bubble-content]:text-card-foreground *:data-[slot=bubble-content]:inset-ring *:data-[slot=bubble-content]:inset-ring-border [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground",
|
|
17
|
+
ghost: "*:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-accent [&>[data-slot=bubble-content]:is(button,a):hover]:text-accent-foreground",
|
|
18
|
+
danger: "*:data-[slot=bubble-content]:bg-danger/10 *:data-[slot=bubble-content]:text-danger *:data-[slot=bubble-content]:inset-ring *:data-[slot=bubble-content]:inset-ring-danger/25 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-danger/20"
|
|
19
|
+
};
|
|
20
|
+
var contentBase = [
|
|
21
|
+
"w-fit max-w-full min-w-0 overflow-hidden px-3.5 py-2 text-sm leading-relaxed [overflow-wrap:anywhere]",
|
|
22
|
+
"rounded-2xl rounded-bl-md",
|
|
23
|
+
"[[data-slot=bubble][data-align=end]_&]:rounded-bl-2xl [[data-slot=bubble][data-align=end]_&]:rounded-br-md",
|
|
24
|
+
"[[data-slot=message][data-align=end]_&]:rounded-bl-2xl [[data-slot=message][data-align=end]_&]:rounded-br-md",
|
|
25
|
+
"[[data-slot=bubble][data-variant=ghost]_&]:rounded-none",
|
|
26
|
+
"group-data-[align=end]/bubble:self-end",
|
|
27
|
+
"[&:is(button)]:text-left [&:is(button,a)]:transition-colors [&:is(button,a)]:outline-none [&:is(button,a)]:focus-visible:ring-3 [&:is(button,a)]:focus-visible:ring-ring/50"
|
|
28
|
+
].join(" ");
|
|
29
|
+
var reactionsBase = "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-popover text-popover-foreground edge px-1.5 py-0.5 text-sm has-[button]:p-0";
|
|
30
|
+
var reactionSides = {
|
|
31
|
+
bottom: "bottom-0 translate-y-3/4",
|
|
32
|
+
top: "top-0 -translate-y-3/4"
|
|
33
|
+
};
|
|
34
|
+
var reactionAligns = {
|
|
35
|
+
end: "right-3",
|
|
36
|
+
start: "left-3"
|
|
37
|
+
};
|
|
38
|
+
/** Groups consecutive bubbles from one speaker. */
|
|
39
|
+
var BubbleGroup = ({ children, class: classes, ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
40
|
+
...attrs,
|
|
41
|
+
class: clsx(groupBase, classes),
|
|
42
|
+
"data-slot": "bubble-group",
|
|
43
|
+
children
|
|
44
|
+
});
|
|
45
|
+
/** Presentational chat bubble wrapper. Keep message-level semantics outside this component. */
|
|
46
|
+
var Bubble = ({ align = "start", children, class: classes, variant = "default", ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
47
|
+
...attrs,
|
|
48
|
+
class: clsx(rootBase, rootVariants[variant], classes),
|
|
49
|
+
"data-align": align,
|
|
50
|
+
"data-slot": "bubble",
|
|
51
|
+
"data-variant": variant,
|
|
52
|
+
children
|
|
53
|
+
});
|
|
54
|
+
/** Bubble content surface. Use `as="button"` or `as="a"` for interactive bubbles. */
|
|
55
|
+
var BubbleContent = ({ as = "div", children, class: classes, type = "button", ...attrs }) => {
|
|
56
|
+
const styles = clsx(contentBase, classes);
|
|
57
|
+
if (as === "a") {
|
|
58
|
+
const anchor = attrs;
|
|
59
|
+
return /* @__PURE__ */ jsx("a", {
|
|
60
|
+
...anchor,
|
|
61
|
+
class: styles,
|
|
62
|
+
"data-slot": "bubble-content",
|
|
63
|
+
href: String(anchor.href),
|
|
64
|
+
children
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (as === "button") return /* @__PURE__ */ jsx("button", {
|
|
68
|
+
...attrs,
|
|
69
|
+
class: styles,
|
|
70
|
+
"data-slot": "bubble-content",
|
|
71
|
+
type,
|
|
72
|
+
children
|
|
73
|
+
});
|
|
74
|
+
return /* @__PURE__ */ jsx("div", {
|
|
75
|
+
...attrs,
|
|
76
|
+
class: styles,
|
|
77
|
+
"data-slot": "bubble-content",
|
|
78
|
+
children
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
/** Reaction row anchored to a bubble edge. */
|
|
82
|
+
var BubbleReactions = ({ align = "end", children, class: classes, side = "bottom", ...attrs }) => /* @__PURE__ */ jsx("div", {
|
|
83
|
+
...attrs,
|
|
84
|
+
class: clsx(reactionsBase, reactionSides[side], reactionAligns[align], classes),
|
|
85
|
+
"data-align": align,
|
|
86
|
+
"data-side": side,
|
|
87
|
+
"data-slot": "bubble-reactions",
|
|
88
|
+
children
|
|
89
|
+
});
|
|
90
|
+
//#endregion
|
|
91
|
+
export { Bubble, BubbleContent, BubbleGroup, BubbleReactions };
|