@pichetch08/trip-ui 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/README.md +46 -0
- package/dist/accordion.d.ts +18 -0
- package/dist/accordion.js +76 -0
- package/dist/agreement-modal.d.ts +16 -0
- package/dist/agreement-modal.js +67 -0
- package/dist/alert.d.ts +13 -0
- package/dist/alert.js +47 -0
- package/dist/auth-hero.d.ts +7 -0
- package/dist/auth-hero.js +63 -0
- package/dist/avatar.d.ts +21 -0
- package/dist/avatar.js +114 -0
- package/dist/badge.d.ts +13 -0
- package/dist/badge.js +36 -0
- package/dist/banner.d.ts +14 -0
- package/dist/banner.js +57 -0
- package/dist/breadcrumb.d.ts +15 -0
- package/dist/breadcrumb.js +37 -0
- package/dist/button.d.ts +15 -0
- package/dist/button.js +81 -0
- package/dist/card.d.ts +30 -0
- package/dist/card.js +66 -0
- package/dist/change-summary-modal.d.ts +35 -0
- package/dist/change-summary-modal.js +128 -0
- package/dist/channel-badge.d.ts +8 -0
- package/dist/channel-badge.js +17 -0
- package/dist/checkbox.d.ts +28 -0
- package/dist/checkbox.js +108 -0
- package/dist/chunk-ORMEWXMH.js +37 -0
- package/dist/color-picker.d.ts +15 -0
- package/dist/color-picker.js +159 -0
- package/dist/confirm-dialog.d.ts +23 -0
- package/dist/confirm-dialog.js +108 -0
- package/dist/copy-button.d.ts +13 -0
- package/dist/copy-button.js +69 -0
- package/dist/dashed-add-button.d.ts +8 -0
- package/dist/dashed-add-button.js +24 -0
- package/dist/data-table.d.ts +27 -0
- package/dist/data-table.js +152 -0
- package/dist/date-picker.d.ts +19 -0
- package/dist/date-picker.js +234 -0
- package/dist/date-range-picker.d.ts +25 -0
- package/dist/date-range-picker.js +456 -0
- package/dist/dev-auto-fill.d.ts +12 -0
- package/dist/dev-auto-fill.js +22 -0
- package/dist/divider.d.ts +10 -0
- package/dist/divider.js +44 -0
- package/dist/drawer.d.ts +16 -0
- package/dist/drawer.js +111 -0
- package/dist/dropdown-menu.d.ts +20 -0
- package/dist/dropdown-menu.js +94 -0
- package/dist/empty-state.d.ts +13 -0
- package/dist/empty-state.js +24 -0
- package/dist/file-upload.d.ts +32 -0
- package/dist/file-upload.js +212 -0
- package/dist/filter-tabs.d.ts +16 -0
- package/dist/filter-tabs.js +30 -0
- package/dist/footer-action-bar.d.ts +21 -0
- package/dist/footer-action-bar.js +95 -0
- package/dist/form-input.d.ts +16 -0
- package/dist/form-input.js +58 -0
- package/dist/form-textarea.d.ts +13 -0
- package/dist/form-textarea.js +41 -0
- package/dist/icon-button.d.ts +12 -0
- package/dist/icon-button.js +54 -0
- package/dist/icon-picker.d.ts +15 -0
- package/dist/icon-picker.js +311 -0
- package/dist/icon-wrapper.d.ts +15 -0
- package/dist/icon-wrapper.js +52 -0
- package/dist/image-upload.d.ts +24 -0
- package/dist/image-upload.js +122 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +155 -0
- package/dist/kbd.d.ts +15 -0
- package/dist/kbd.js +27 -0
- package/dist/mobile-preview.d.ts +36 -0
- package/dist/mobile-preview.js +167 -0
- package/dist/modal.d.ts +19 -0
- package/dist/modal.js +110 -0
- package/dist/multi-select.d.ts +30 -0
- package/dist/multi-select.js +261 -0
- package/dist/number-input.d.ts +21 -0
- package/dist/number-input.js +129 -0
- package/dist/otp-input.d.ts +13 -0
- package/dist/otp-input.js +114 -0
- package/dist/page-header.d.ts +15 -0
- package/dist/page-header.js +43 -0
- package/dist/page-state.d.ts +14 -0
- package/dist/page-state.js +29 -0
- package/dist/pagination.d.ts +20 -0
- package/dist/pagination.js +87 -0
- package/dist/popover.d.ts +11 -0
- package/dist/popover.js +70 -0
- package/dist/preview-drawer.d.ts +33 -0
- package/dist/preview-drawer.js +74 -0
- package/dist/progress-bar.d.ts +15 -0
- package/dist/progress-bar.js +56 -0
- package/dist/qr-code-display.d.ts +10 -0
- package/dist/qr-code-display.js +43 -0
- package/dist/radio-group.d.ts +19 -0
- package/dist/radio-group.js +78 -0
- package/dist/rating.d.ts +12 -0
- package/dist/rating.js +123 -0
- package/dist/rich-editor.d.ts +13 -0
- package/dist/rich-editor.js +97 -0
- package/dist/search-bar.d.ts +14 -0
- package/dist/search-bar.js +64 -0
- package/dist/section-header.d.ts +12 -0
- package/dist/section-header.js +41 -0
- package/dist/segmented-control.d.ts +24 -0
- package/dist/segmented-control.js +38 -0
- package/dist/select-picker.d.ts +24 -0
- package/dist/select-picker.js +157 -0
- package/dist/skeleton.d.ts +14 -0
- package/dist/skeleton.js +53 -0
- package/dist/slider.d.ts +17 -0
- package/dist/slider.js +151 -0
- package/dist/spinner.d.ts +13 -0
- package/dist/spinner.js +38 -0
- package/dist/stat-card.d.ts +20 -0
- package/dist/stat-card.js +87 -0
- package/dist/stats-summary.d.ts +13 -0
- package/dist/stats-summary.js +28 -0
- package/dist/status-badge.d.ts +19 -0
- package/dist/status-badge.js +41 -0
- package/dist/stepper.d.ts +12 -0
- package/dist/stepper.js +89 -0
- package/dist/tabs.d.ts +18 -0
- package/dist/tabs.js +70 -0
- package/dist/tag.d.ts +23 -0
- package/dist/tag.js +158 -0
- package/dist/time-picker.d.ts +19 -0
- package/dist/time-picker.js +222 -0
- package/dist/timeline.d.ts +15 -0
- package/dist/timeline.js +49 -0
- package/dist/toast.d.ts +18 -0
- package/dist/toast.js +108 -0
- package/dist/toggle-switch.d.ts +12 -0
- package/dist/toggle-switch.js +34 -0
- package/dist/tooltip.d.ts +9 -0
- package/dist/tooltip.js +69 -0
- package/dist/trip-day-map-lazy.d.ts +15 -0
- package/dist/trip-day-map-lazy.js +16 -0
- package/dist/trip-day-map.d.ts +15 -0
- package/dist/trip-day-map.js +62 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @pichetch08/trip-ui
|
|
2
|
+
|
|
3
|
+
Shared React component library for Trip applications, built with Tailwind v4 and Material Design 3 tokens.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pichetch08/trip-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Peer dependencies
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install react react-dom clsx tailwind-merge
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> `next` is optional — only required if you use Next.js-specific components (e.g. `TripDayMapLazy`).
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Button, Modal, TimePicker, RichEditor } from "@pichetch08/trip-ui";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
All components are tree-shakeable. Import only what you need.
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- React ≥ 19
|
|
30
|
+
- Tailwind CSS v4 configured in your project with the MD3 design tokens
|
|
31
|
+
- Material Symbols icon font loaded in your app
|
|
32
|
+
|
|
33
|
+
## Components
|
|
34
|
+
|
|
35
|
+
Over 70 shared components including:
|
|
36
|
+
|
|
37
|
+
- **Form**: `TextField`, `Select`, `TimePicker`, `DatePicker`, `NumberInput`, `Slider`, `RichEditor`, `FileUpload`, `OtpInput`, `TagGroup`, `RadioGroup`, `SegmentedControl`, `MultiSelect`
|
|
38
|
+
- **Feedback**: `Modal`, `Drawer`, `PreviewDrawer`, `Toast`, `Alert`, `Spinner`, `ProgressBar`, `Skeleton`, `PageState`
|
|
39
|
+
- **Display**: `Tag`, `StatusBadge`, `StatCard`, `Tooltip`, `Popover`, `Timeline`, `Stepper`, `Rating`, `Tabs`
|
|
40
|
+
- **Layout**: `SectionHeader`, `StatsSummary`, `MobilePreview`
|
|
41
|
+
- **Maps**: `TripDayMap`, `TripDayMapLazy`
|
|
42
|
+
- **Misc**: `QrCodeDisplay`, `SearchBar`, `Kbd`
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface AccordionItem {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
badge?: string;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
interface AccordionProps {
|
|
12
|
+
items: AccordionItem[];
|
|
13
|
+
defaultOpen?: string[];
|
|
14
|
+
allowMultiple?: boolean;
|
|
15
|
+
}
|
|
16
|
+
declare function Accordion({ items, defaultOpen, allowMultiple, }: AccordionProps): react_jsx_runtime.JSX.Element;
|
|
17
|
+
|
|
18
|
+
export { Accordion, type AccordionItem };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "./chunk-ORMEWXMH.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
function Accordion({
|
|
6
|
+
items,
|
|
7
|
+
defaultOpen = [],
|
|
8
|
+
allowMultiple = false
|
|
9
|
+
}) {
|
|
10
|
+
const [openIds, setOpenIds] = useState(new Set(defaultOpen));
|
|
11
|
+
function toggle(id) {
|
|
12
|
+
setOpenIds((prev) => {
|
|
13
|
+
const next = new Set(prev);
|
|
14
|
+
if (next.has(id)) {
|
|
15
|
+
next.delete(id);
|
|
16
|
+
} else {
|
|
17
|
+
if (!allowMultiple) {
|
|
18
|
+
next.clear();
|
|
19
|
+
}
|
|
20
|
+
next.add(id);
|
|
21
|
+
}
|
|
22
|
+
return next;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { children: items.map((item) => {
|
|
26
|
+
const isOpen = openIds.has(item.id);
|
|
27
|
+
return /* @__PURE__ */ jsxs(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
className: "rounded-2xl border border-outline-variant/30 bg-surface shadow-sm overflow-hidden mb-3",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ jsxs(
|
|
33
|
+
"button",
|
|
34
|
+
{
|
|
35
|
+
id: `accordion-btn-${item.id}`,
|
|
36
|
+
type: "button",
|
|
37
|
+
onClick: () => toggle(item.id),
|
|
38
|
+
"aria-expanded": isOpen,
|
|
39
|
+
"aria-controls": `accordion-panel-${item.id}`,
|
|
40
|
+
className: "w-full flex items-center gap-3 px-5 py-4 text-left hover:bg-surface-container-low/50 active:bg-surface-container-low transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-inset",
|
|
41
|
+
children: [
|
|
42
|
+
item.icon && /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-xl text-on-surface-variant", children: item.icon }),
|
|
43
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
44
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-on-surface block", children: item.title }),
|
|
45
|
+
item.subtitle && /* @__PURE__ */ jsx("span", { className: "text-xs text-on-surface-variant block mt-0.5", children: item.subtitle })
|
|
46
|
+
] }),
|
|
47
|
+
item.badge && !isOpen && /* @__PURE__ */ jsx("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-0.5 rounded-full shrink-0", children: item.badge }),
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
"span",
|
|
50
|
+
{
|
|
51
|
+
className: `material-symbols-outlined text-xl text-on-surface-variant shrink-0 transition-transform duration-300 ${isOpen ? "rotate-180" : "rotate-0"}`,
|
|
52
|
+
children: "expand_more"
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
/* @__PURE__ */ jsx(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
id: `accordion-panel-${item.id}`,
|
|
62
|
+
role: "region",
|
|
63
|
+
"aria-labelledby": `accordion-btn-${item.id}`,
|
|
64
|
+
className: `grid transition-all duration-300 ease-in-out ${isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"}`,
|
|
65
|
+
children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "px-5 pb-5 pt-1", children: item.children }) })
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
item.id
|
|
71
|
+
);
|
|
72
|
+
}) });
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
Accordion
|
|
76
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface AgreementModalProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onAccept: () => void;
|
|
5
|
+
title: string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
scrollHintText?: string;
|
|
8
|
+
scrollDownText?: string;
|
|
9
|
+
readCompleteText?: string;
|
|
10
|
+
closeLabel?: string;
|
|
11
|
+
acceptLabel?: string;
|
|
12
|
+
closeAriaLabel?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function AgreementModal({ open, onClose, onAccept, title, children, scrollHintText, scrollDownText, readCompleteText, closeLabel, acceptLabel, closeAriaLabel, }: AgreementModalProps): React.ReactNode;
|
|
15
|
+
|
|
16
|
+
export { AgreementModal };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "./chunk-ORMEWXMH.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useRef, useState, useEffect, useCallback } from "react";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
import { IconButton } from "./icon-button";
|
|
7
|
+
function AgreementModal({
|
|
8
|
+
open,
|
|
9
|
+
onClose,
|
|
10
|
+
onAccept,
|
|
11
|
+
title,
|
|
12
|
+
children,
|
|
13
|
+
scrollHintText = "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E40\u0E25\u0E37\u0E48\u0E2D\u0E19\u0E2D\u0E48\u0E32\u0E19\u0E08\u0E19\u0E08\u0E1A\u0E01\u0E48\u0E2D\u0E19\u0E01\u0E14\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A",
|
|
14
|
+
scrollDownText = "\u0E40\u0E25\u0E37\u0E48\u0E2D\u0E19\u0E25\u0E07\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E2D\u0E48\u0E32\u0E19\u0E15\u0E48\u0E2D",
|
|
15
|
+
readCompleteText = "\u0E2D\u0E48\u0E32\u0E19\u0E04\u0E23\u0E1A\u0E41\u0E25\u0E49\u0E27",
|
|
16
|
+
closeLabel = "\u0E1B\u0E34\u0E14",
|
|
17
|
+
acceptLabel = "\u0E09\u0E31\u0E19\u0E44\u0E14\u0E49\u0E2D\u0E48\u0E32\u0E19\u0E41\u0E25\u0E30\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A",
|
|
18
|
+
closeAriaLabel = "\u0E1B\u0E34\u0E14"
|
|
19
|
+
}) {
|
|
20
|
+
const scrollRef = useRef(null);
|
|
21
|
+
const [scrolledToBottom, setScrolledToBottom] = useState(false);
|
|
22
|
+
const handleScroll = useCallback(() => {
|
|
23
|
+
const el = scrollRef.current;
|
|
24
|
+
if (!el) return;
|
|
25
|
+
const isBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40;
|
|
26
|
+
if (isBottom) setScrolledToBottom(true);
|
|
27
|
+
}, []);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (open) setScrolledToBottom(false);
|
|
30
|
+
}, [open]);
|
|
31
|
+
if (!open) return null;
|
|
32
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-100 flex items-center justify-center p-4", children: [
|
|
33
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm cursor-pointer", onClick: onClose }),
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "relative bg-surface rounded-2xl shadow-2xl w-full max-w-2xl max-h-[85vh] flex flex-col overflow-hidden", children: [
|
|
35
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-outline-variant", children: [
|
|
36
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-on-surface", children: title }),
|
|
37
|
+
/* @__PURE__ */ jsx(IconButton, { icon: "close", variant: "ghost", size: "sm", onClick: onClose, "aria-label": closeAriaLabel })
|
|
38
|
+
] }),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
ref: scrollRef,
|
|
43
|
+
onScroll: handleScroll,
|
|
44
|
+
className: "flex-1 overflow-y-auto px-6 py-6 text-sm text-on-surface-variant leading-relaxed",
|
|
45
|
+
children
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
!scrolledToBottom && /* @__PURE__ */ jsx("div", { className: "absolute bottom-18 left-0 right-0 h-16 bg-linear-to-t from-white to-transparent pointer-events-none flex items-end justify-center pb-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs text-on-surface-variant animate-bounce", children: [
|
|
49
|
+
/* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm", children: "keyboard_arrow_down" }),
|
|
50
|
+
scrollDownText
|
|
51
|
+
] }) }),
|
|
52
|
+
/* @__PURE__ */ jsxs("div", { className: "px-6 py-4 border-t border-outline-variant flex items-center justify-between gap-3", children: [
|
|
53
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-on-surface-variant", children: scrolledToBottom ? /* @__PURE__ */ jsxs("span", { className: "text-green-600 flex items-center gap-1", children: [
|
|
54
|
+
/* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm", children: "check_circle" }),
|
|
55
|
+
readCompleteText
|
|
56
|
+
] }) : scrollHintText }),
|
|
57
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
58
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: onClose, children: closeLabel }),
|
|
59
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onAccept, disabled: !scrolledToBottom, children: acceptLabel })
|
|
60
|
+
] })
|
|
61
|
+
] })
|
|
62
|
+
] })
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
AgreementModal
|
|
67
|
+
};
|
package/dist/alert.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type AlertVariant = "info" | "success" | "warning" | "error";
|
|
2
|
+
interface AlertProps {
|
|
3
|
+
variant: AlertVariant;
|
|
4
|
+
title?: string;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
className?: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
closeAriaLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
declare function Alert({ variant, title, children, onClose, className, icon, closeAriaLabel, }: AlertProps): React.ReactNode;
|
|
12
|
+
|
|
13
|
+
export { Alert, type AlertVariant };
|
package/dist/alert.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "./chunk-ORMEWXMH.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
const VARIANT_STYLES = {
|
|
4
|
+
info: { container: "bg-blue-50 border border-blue-200 text-blue-800", icon: "text-blue-500", defaultIcon: "info" },
|
|
5
|
+
success: { container: "bg-emerald-50 border border-emerald-200 text-emerald-800", icon: "text-emerald-500", defaultIcon: "check_circle" },
|
|
6
|
+
warning: { container: "bg-amber-50 border border-amber-200 text-amber-800", icon: "text-amber-500", defaultIcon: "warning" },
|
|
7
|
+
error: { container: "bg-red-50 border border-red-200 text-red-800", icon: "text-red-500", defaultIcon: "error" }
|
|
8
|
+
};
|
|
9
|
+
function Alert({
|
|
10
|
+
variant,
|
|
11
|
+
title,
|
|
12
|
+
children,
|
|
13
|
+
onClose,
|
|
14
|
+
className = "",
|
|
15
|
+
icon,
|
|
16
|
+
closeAriaLabel = "Close"
|
|
17
|
+
}) {
|
|
18
|
+
const styles = VARIANT_STYLES[variant];
|
|
19
|
+
const resolvedIcon = icon != null ? icon : styles.defaultIcon;
|
|
20
|
+
return /* @__PURE__ */ jsxs(
|
|
21
|
+
"div",
|
|
22
|
+
{
|
|
23
|
+
className: `flex items-start gap-3 p-4 rounded-xl ${styles.container} ${className}`,
|
|
24
|
+
role: "alert",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ jsx("span", { className: `material-symbols-outlined text-xl shrink-0 ${styles.icon}`, "aria-hidden": "true", children: resolvedIcon }),
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
28
|
+
title && /* @__PURE__ */ jsx("p", { className: "font-semibold text-sm", children: title }),
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm mt-0.5 opacity-90", children })
|
|
30
|
+
] }),
|
|
31
|
+
onClose && /* @__PURE__ */ jsx(
|
|
32
|
+
"button",
|
|
33
|
+
{
|
|
34
|
+
type: "button",
|
|
35
|
+
onClick: onClose,
|
|
36
|
+
className: "shrink-0 ml-auto -mt-0.5 p-0.5 rounded-md opacity-60 hover:opacity-100 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-current",
|
|
37
|
+
"aria-label": closeAriaLabel,
|
|
38
|
+
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-xl", "aria-hidden": "true", children: "close" })
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
Alert
|
|
47
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import "./chunk-ORMEWXMH.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
function AuthHero({ imageUrl, overlayOpacity = 0.35 }) {
|
|
4
|
+
if (imageUrl) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 w-full h-full overflow-hidden", children: [
|
|
6
|
+
/* @__PURE__ */ jsx(
|
|
7
|
+
"img",
|
|
8
|
+
{
|
|
9
|
+
src: imageUrl,
|
|
10
|
+
alt: "",
|
|
11
|
+
"aria-hidden": "true",
|
|
12
|
+
className: "absolute inset-0 w-full h-full object-cover"
|
|
13
|
+
}
|
|
14
|
+
),
|
|
15
|
+
/* @__PURE__ */ jsx(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: "absolute inset-0",
|
|
19
|
+
style: { backgroundColor: `rgba(0,0,0,${overlayOpacity})` }
|
|
20
|
+
}
|
|
21
|
+
),
|
|
22
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0 h-1/2 bg-linear-to-t from-black/40 to-transparent" })
|
|
23
|
+
] });
|
|
24
|
+
}
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 w-full h-full overflow-hidden", children: [
|
|
26
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-linear-to-br from-blue-500 via-blue-700 to-indigo-900" }),
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
className: "absolute inset-0 opacity-50",
|
|
31
|
+
style: {
|
|
32
|
+
background: "radial-gradient(circle at 30% 20%, rgba(255,255,255,0.25) 0%, transparent 50%)"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
/* @__PURE__ */ jsxs(
|
|
37
|
+
"svg",
|
|
38
|
+
{
|
|
39
|
+
className: "absolute inset-0 w-full h-full opacity-[0.08]",
|
|
40
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
41
|
+
"aria-hidden": "true",
|
|
42
|
+
children: [
|
|
43
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("pattern", { id: "hero-dots", x: "0", y: "0", width: "32", height: "32", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx("circle", { cx: "2", cy: "2", r: "1", fill: "white" }) }) }),
|
|
44
|
+
/* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: "url(#hero-dots)" })
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
"svg",
|
|
50
|
+
{
|
|
51
|
+
className: "absolute -right-20 -bottom-10 w-[500px] h-[500px] opacity-10 rotate-[-15deg]",
|
|
52
|
+
viewBox: "0 0 24 24",
|
|
53
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
54
|
+
fill: "white",
|
|
55
|
+
"aria-hidden": "true",
|
|
56
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z" })
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
] });
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
AuthHero
|
|
63
|
+
};
|
package/dist/avatar.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
2
|
+
interface AvatarProps {
|
|
3
|
+
src?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
size?: AvatarSize;
|
|
6
|
+
className?: string;
|
|
7
|
+
online?: boolean;
|
|
8
|
+
unknownUserLabel?: string;
|
|
9
|
+
onlineLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
interface AvatarGroupProps {
|
|
12
|
+
avatars: Pick<AvatarProps, "src" | "name">[];
|
|
13
|
+
size?: AvatarSize;
|
|
14
|
+
max?: number;
|
|
15
|
+
className?: string;
|
|
16
|
+
moreLabel?: (n: number) => string;
|
|
17
|
+
}
|
|
18
|
+
declare function Avatar({ src, name, size, className, online, unknownUserLabel, onlineLabel, }: AvatarProps): React.ReactNode;
|
|
19
|
+
declare function AvatarGroup({ avatars, size, max, className, moreLabel, }: AvatarGroupProps): React.ReactNode;
|
|
20
|
+
|
|
21
|
+
export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize };
|
package/dist/avatar.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "./chunk-ORMEWXMH.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
const SIZE_CLASSES = {
|
|
5
|
+
xs: "w-6 h-6",
|
|
6
|
+
sm: "w-8 h-8",
|
|
7
|
+
md: "w-10 h-10",
|
|
8
|
+
lg: "w-12 h-12",
|
|
9
|
+
xl: "w-16 h-16"
|
|
10
|
+
};
|
|
11
|
+
const TEXT_CLASSES = {
|
|
12
|
+
xs: "text-[10px]",
|
|
13
|
+
sm: "text-xs",
|
|
14
|
+
md: "text-sm",
|
|
15
|
+
lg: "text-base",
|
|
16
|
+
xl: "text-xl"
|
|
17
|
+
};
|
|
18
|
+
const ICON_CLASSES = {
|
|
19
|
+
xs: "text-sm",
|
|
20
|
+
sm: "text-base",
|
|
21
|
+
md: "text-xl",
|
|
22
|
+
lg: "text-2xl",
|
|
23
|
+
xl: "text-3xl"
|
|
24
|
+
};
|
|
25
|
+
function getInitials(name) {
|
|
26
|
+
const parts = name.trim().split(/\s+/);
|
|
27
|
+
const letters = parts.map((p) => {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
return (_b = (_a = p[0]) == null ? void 0 : _a.toUpperCase()) != null ? _b : "";
|
|
30
|
+
}).filter(Boolean);
|
|
31
|
+
return letters.slice(0, 2).join("");
|
|
32
|
+
}
|
|
33
|
+
function Avatar({
|
|
34
|
+
src,
|
|
35
|
+
name,
|
|
36
|
+
size = "md",
|
|
37
|
+
className = "",
|
|
38
|
+
online = false,
|
|
39
|
+
unknownUserLabel = "Unknown user",
|
|
40
|
+
onlineLabel = "Online"
|
|
41
|
+
}) {
|
|
42
|
+
const sizeClass = SIZE_CLASSES[size];
|
|
43
|
+
const textClass = TEXT_CLASSES[size];
|
|
44
|
+
const iconClass = ICON_CLASSES[size];
|
|
45
|
+
return /* @__PURE__ */ jsxs("div", { className: `relative inline-flex shrink-0 ${sizeClass} ${className}`, children: [
|
|
46
|
+
src ? /* @__PURE__ */ jsx(
|
|
47
|
+
"img",
|
|
48
|
+
{
|
|
49
|
+
src,
|
|
50
|
+
alt: name != null ? name : "Avatar",
|
|
51
|
+
className: `${sizeClass} rounded-full object-cover`
|
|
52
|
+
}
|
|
53
|
+
) : name ? /* @__PURE__ */ jsx(
|
|
54
|
+
"span",
|
|
55
|
+
{
|
|
56
|
+
className: `${sizeClass} rounded-full bg-primary-container text-(--on-primary-container) font-bold flex items-center justify-center ${textClass} select-none`,
|
|
57
|
+
"aria-label": name,
|
|
58
|
+
children: getInitials(name)
|
|
59
|
+
}
|
|
60
|
+
) : /* @__PURE__ */ jsx(
|
|
61
|
+
"span",
|
|
62
|
+
{
|
|
63
|
+
className: `${sizeClass} rounded-full bg-surface-container text-on-surface-variant flex items-center justify-center`,
|
|
64
|
+
"aria-label": unknownUserLabel,
|
|
65
|
+
children: /* @__PURE__ */ jsx("span", { className: `material-symbols-outlined ${iconClass} leading-none`, "aria-hidden": "true", children: "person" })
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
online && /* @__PURE__ */ jsx(
|
|
69
|
+
"span",
|
|
70
|
+
{
|
|
71
|
+
className: "absolute bottom-0 right-0 w-2.5 h-2.5 rounded-full bg-emerald-500 ring-2 ring-white",
|
|
72
|
+
"aria-label": onlineLabel
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
] });
|
|
76
|
+
}
|
|
77
|
+
function AvatarGroup({
|
|
78
|
+
avatars,
|
|
79
|
+
size = "md",
|
|
80
|
+
max = 4,
|
|
81
|
+
className = "",
|
|
82
|
+
moreLabel = (n) => `${n} more`
|
|
83
|
+
}) {
|
|
84
|
+
const visible = avatars.slice(0, max);
|
|
85
|
+
const overflow = avatars.length - visible.length;
|
|
86
|
+
const sizeClass = SIZE_CLASSES[size];
|
|
87
|
+
const textClass = TEXT_CLASSES[size];
|
|
88
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex items-center ${className}`, children: [
|
|
89
|
+
visible.map((avatar, i) => /* @__PURE__ */ jsx("div", { className: i > 0 ? "-ml-2" : "", children: /* @__PURE__ */ jsx(
|
|
90
|
+
Avatar,
|
|
91
|
+
{
|
|
92
|
+
src: avatar.src,
|
|
93
|
+
name: avatar.name,
|
|
94
|
+
size,
|
|
95
|
+
className: "ring-2 ring-white"
|
|
96
|
+
}
|
|
97
|
+
) }, i)),
|
|
98
|
+
overflow > 0 && /* @__PURE__ */ jsx("div", { className: "-ml-2", children: /* @__PURE__ */ jsxs(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
className: `${sizeClass} rounded-full bg-surface-container text-on-surface-variant font-bold flex items-center justify-center ${textClass} ring-2 ring-white select-none`,
|
|
102
|
+
"aria-label": moreLabel(overflow),
|
|
103
|
+
children: [
|
|
104
|
+
"+",
|
|
105
|
+
overflow
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
) })
|
|
109
|
+
] });
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
Avatar,
|
|
113
|
+
AvatarGroup
|
|
114
|
+
};
|
package/dist/badge.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type BadgeVariant = "default" | "primary" | "secondary" | "success" | "warning" | "error" | "info";
|
|
4
|
+
type BadgeSize = "sm" | "md" | "lg";
|
|
5
|
+
interface BadgeProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
variant?: BadgeVariant;
|
|
8
|
+
size?: BadgeSize;
|
|
9
|
+
icon?: string;
|
|
10
|
+
}
|
|
11
|
+
declare function Badge({ children, variant, size, icon }: BadgeProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { Badge };
|
package/dist/badge.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "./chunk-ORMEWXMH.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
function Badge({ children, variant = "default", size = "md", icon }) {
|
|
4
|
+
const variantClasses = {
|
|
5
|
+
default: "bg-surface-container text-on-surface-variant",
|
|
6
|
+
primary: "bg-primary-container text-(--on-primary-container)",
|
|
7
|
+
secondary: "bg-(--secondary-container) text-(--on-secondary-container)",
|
|
8
|
+
success: "bg-success/10 text-success",
|
|
9
|
+
warning: "bg-warning/10 text-warning",
|
|
10
|
+
error: "bg-error/10 text-error",
|
|
11
|
+
info: "bg-info/10 text-info"
|
|
12
|
+
};
|
|
13
|
+
const sizeClasses = {
|
|
14
|
+
sm: "px-2 py-0.5 text-[10px]",
|
|
15
|
+
md: "px-3 py-1 text-xs",
|
|
16
|
+
lg: "px-4 py-1.5 text-sm"
|
|
17
|
+
};
|
|
18
|
+
const iconSizeClasses = {
|
|
19
|
+
sm: "text-xs",
|
|
20
|
+
md: "text-sm",
|
|
21
|
+
lg: "text-base"
|
|
22
|
+
};
|
|
23
|
+
return /* @__PURE__ */ jsxs(
|
|
24
|
+
"span",
|
|
25
|
+
{
|
|
26
|
+
className: `inline-flex items-center gap-1.5 rounded-full font-medium transition-colors ${sizeClasses[size]} ${variantClasses[variant]}`,
|
|
27
|
+
children: [
|
|
28
|
+
icon && /* @__PURE__ */ jsx("span", { className: `material-symbols-outlined ${iconSizeClasses[size]}`, "aria-hidden": "true", children: icon }),
|
|
29
|
+
children
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
Badge
|
|
36
|
+
};
|
package/dist/banner.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type BannerVariant = "info" | "success" | "warning" | "danger";
|
|
2
|
+
interface BannerProps {
|
|
3
|
+
variant?: BannerVariant;
|
|
4
|
+
icon?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
onDismiss?: () => void;
|
|
8
|
+
action?: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
closeAriaLabel?: string;
|
|
11
|
+
}
|
|
12
|
+
declare function Banner({ variant, icon, title, children, onDismiss, action, className, closeAriaLabel, }: BannerProps): React.ReactNode;
|
|
13
|
+
|
|
14
|
+
export { Banner, type BannerVariant };
|
package/dist/banner.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "./chunk-ORMEWXMH.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
const VARIANTS = {
|
|
5
|
+
info: { wrap: "bg-info/10 border-info/30", iconColor: "text-info", titleColor: "text-info" },
|
|
6
|
+
success: { wrap: "bg-success/10 border-success/30", iconColor: "text-success", titleColor: "text-success" },
|
|
7
|
+
warning: { wrap: "bg-warning/10 border-warning/30", iconColor: "text-warning", titleColor: "text-warning" },
|
|
8
|
+
danger: { wrap: "bg-error/10 border-error/30", iconColor: "text-error", titleColor: "text-error" }
|
|
9
|
+
};
|
|
10
|
+
const DEFAULT_ICON = {
|
|
11
|
+
info: "info",
|
|
12
|
+
success: "check_circle",
|
|
13
|
+
warning: "warning",
|
|
14
|
+
danger: "error"
|
|
15
|
+
};
|
|
16
|
+
function Banner({
|
|
17
|
+
variant = "info",
|
|
18
|
+
icon,
|
|
19
|
+
title,
|
|
20
|
+
children,
|
|
21
|
+
onDismiss,
|
|
22
|
+
action,
|
|
23
|
+
className = "",
|
|
24
|
+
closeAriaLabel = "\u0E1B\u0E34\u0E14"
|
|
25
|
+
}) {
|
|
26
|
+
const v = VARIANTS[variant];
|
|
27
|
+
const resolvedIcon = icon != null ? icon : DEFAULT_ICON[variant];
|
|
28
|
+
return /* @__PURE__ */ jsxs("div", { className: `border rounded-2xl p-4 flex items-start gap-3 ${v.wrap} ${className}`, children: [
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
"span",
|
|
31
|
+
{
|
|
32
|
+
className: `material-symbols-outlined mt-0.5 text-2xl ${v.iconColor}`,
|
|
33
|
+
style: { fontVariationSettings: "'FILL' 1" },
|
|
34
|
+
"aria-hidden": "true",
|
|
35
|
+
children: resolvedIcon
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
39
|
+
title && /* @__PURE__ */ jsx("p", { className: `text-sm font-bold ${v.titleColor}`, children: title }),
|
|
40
|
+
children && (typeof children === "string" ? /* @__PURE__ */ jsx("p", { className: `text-xs ${v.titleColor} opacity-80 ${title ? "mt-1" : ""} leading-relaxed`, children }) : /* @__PURE__ */ jsx("div", { className: title ? "mt-1" : "", children }))
|
|
41
|
+
] }),
|
|
42
|
+
action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }),
|
|
43
|
+
onDismiss && /* @__PURE__ */ jsx(
|
|
44
|
+
"button",
|
|
45
|
+
{
|
|
46
|
+
type: "button",
|
|
47
|
+
onClick: onDismiss,
|
|
48
|
+
className: `shrink-0 p-1 rounded ${v.iconColor} hover:opacity-70 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-current`,
|
|
49
|
+
"aria-label": closeAriaLabel,
|
|
50
|
+
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-lg", "aria-hidden": "true", children: "close" })
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
Banner
|
|
57
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
}
|
|
7
|
+
interface BreadcrumbProps {
|
|
8
|
+
items: BreadcrumbItem[];
|
|
9
|
+
className?: string;
|
|
10
|
+
navAriaLabel?: string;
|
|
11
|
+
homeAriaLabel?: string;
|
|
12
|
+
}
|
|
13
|
+
declare function Breadcrumb({ items, className, navAriaLabel, homeAriaLabel }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
|
|
14
|
+
|
|
15
|
+
export { Breadcrumb, type BreadcrumbItem };
|