@revealui/presentation 0.2.0 → 0.3.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 +146 -42
- package/dist/Box-DC3F8eRf.js +430 -0
- package/dist/Box-DC3F8eRf.js.map +1 -0
- package/dist/Text-jQVi12Hi.js +218 -0
- package/dist/Text-jQVi12Hi.js.map +1 -0
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +134 -2803
- package/dist/client.js.map +1 -1
- package/dist/components/BuiltWithRevealUI.d.ts +12 -0
- package/dist/components/BuiltWithRevealUI.d.ts.map +1 -0
- package/dist/components/Button.d.ts +2 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Card.d.ts +18 -6
- package/dist/components/Card.d.ts.map +1 -1
- package/dist/components/Checkbox.d.ts +6 -3
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/FormLabel.d.ts +5 -1
- package/dist/components/FormLabel.d.ts.map +1 -1
- package/dist/components/Input.d.ts +4 -2
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Label.d.ts +7 -2
- package/dist/components/Label.d.ts.map +1 -1
- package/dist/components/Pagination.d.ts +12 -23
- package/dist/components/Pagination.d.ts.map +1 -1
- package/dist/components/Select.d.ts +36 -13
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Textarea.d.ts +4 -2
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/accordion.d.ts.map +1 -1
- package/dist/components/alert.d.ts.map +1 -1
- package/dist/components/auth-layout.d.ts +7 -2
- package/dist/components/auth-layout.d.ts.map +1 -1
- package/dist/components/avatar-group.d.ts.map +1 -1
- package/dist/components/avatar.d.ts +6 -5
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/badge.d.ts +5 -5
- package/dist/components/badge.d.ts.map +1 -1
- package/dist/components/breadcrumb.d.ts.map +1 -1
- package/dist/components/button-headless.d.ts +2 -1
- package/dist/components/button-headless.d.ts.map +1 -1
- package/dist/components/callout.d.ts.map +1 -1
- package/dist/components/checkbox-headless.d.ts.map +1 -1
- package/dist/components/code-block.d.ts.map +1 -1
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/empty-state.d.ts.map +1 -1
- package/dist/components/fieldset.d.ts.map +1 -1
- package/dist/components/heading.d.ts.map +1 -1
- package/dist/components/index.d.ts +19 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input-headless.d.ts +5 -3
- package/dist/components/input-headless.d.ts.map +1 -1
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/link.d.ts +3 -2
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/listbox.d.ts.map +1 -1
- package/dist/components/navbar.d.ts +5 -5
- package/dist/components/navbar.d.ts.map +1 -1
- package/dist/components/pricing-table.d.ts +23 -0
- package/dist/components/pricing-table.d.ts.map +1 -0
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/radio.d.ts.map +1 -1
- package/dist/components/rating.d.ts.map +1 -1
- package/dist/components/select-headless.d.ts +5 -2
- package/dist/components/select-headless.d.ts.map +1 -1
- package/dist/components/sidebar-layout.d.ts.map +1 -1
- package/dist/components/sidebar.d.ts +5 -5
- package/dist/components/sidebar.d.ts.map +1 -1
- package/dist/components/skeleton.d.ts.map +1 -1
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/stacked-layout.d.ts.map +1 -1
- package/dist/components/stat.d.ts.map +1 -1
- package/dist/components/stepper.d.ts.map +1 -1
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/text.d.ts.map +1 -1
- package/dist/components/textarea-headless.d.ts +5 -2
- package/dist/components/textarea-headless.d.ts.map +1 -1
- package/dist/components/timeline.d.ts.map +1 -1
- package/dist/components/toast.d.ts.map +1 -1
- package/dist/components/tooltip.d.ts +7 -5
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/use-click-outside.d.ts.map +1 -1
- package/dist/hooks/use-close-context.d.ts.map +1 -1
- package/dist/hooks/use-controllable-state.d.ts.map +1 -1
- package/dist/hooks/use-data-interactive.d.ts.map +1 -1
- package/dist/hooks/use-field-context.d.ts.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts.map +1 -1
- package/dist/hooks/use-layout-animation.d.ts.map +1 -1
- package/dist/hooks/use-popover.d.ts.map +1 -1
- package/dist/hooks/use-roving-tabindex.d.ts.map +1 -1
- package/dist/hooks/use-toggle.d.ts.map +1 -1
- package/dist/hooks/use-transition.d.ts.map +1 -1
- package/dist/hooks/use-type-ahead.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +206 -65
- package/dist/index.js.map +1 -1
- package/dist/primitives/Box.d.ts +3 -1
- package/dist/primitives/Box.d.ts.map +1 -1
- package/dist/primitives/Flex.d.ts +3 -1
- package/dist/primitives/Flex.d.ts.map +1 -1
- package/dist/primitives/Grid.d.ts +3 -1
- package/dist/primitives/Grid.d.ts.map +1 -1
- package/dist/primitives/Heading.d.ts +3 -1
- package/dist/primitives/Heading.d.ts.map +1 -1
- package/dist/primitives/Slot.d.ts +3 -1
- package/dist/primitives/Slot.d.ts.map +1 -1
- package/dist/primitives/Text.d.ts +3 -1
- package/dist/primitives/Text.d.ts.map +1 -1
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -13
- package/dist/tooltip-DQYjYWbe.js +5085 -0
- package/dist/tooltip-DQYjYWbe.js.map +1 -0
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +7 -4
- package/dist/Box-DDhRNK02.js +0 -45
- package/dist/Box-DDhRNK02.js.map +0 -1
- package/dist/Text-BIym7IhD.js +0 -425
- package/dist/Text-BIym7IhD.js.map +0 -1
- package/dist/tooltip-oH4lAnkn.js +0 -2277
- package/dist/tooltip-oH4lAnkn.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,65 +1,169 @@
|
|
|
1
1
|
# @revealui/presentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
50+ native UI components for RevealUI — built with React 19, Tailwind CSS v4, and CVA. Zero external UI library dependencies (only clsx + class-variance-authority).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **48 Components** — Forms, data display, feedback, navigation, media, and layout
|
|
8
|
+
- **6 Primitives** — Low-level building blocks (Box, Flex, Grid, Heading, Text, Slot)
|
|
9
|
+
- **14 Hooks** — Focus trap, click outside, popover, roving tabindex, scroll lock, and more
|
|
10
|
+
- **Headless + Styled** — Many components ship both unstyled (headless) and styled (CVA) variants
|
|
11
|
+
- **Accessible** — WCAG 2.1 patterns with proper ARIA attributes
|
|
12
|
+
- **React 19** — Server components, hooks, and modern patterns
|
|
13
|
+
- **Tailwind CSS v4** — Native v4 utility classes, no v3 compat layer
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
- `apps/mainframe` - Public-facing web application
|
|
11
|
-
- Future applications
|
|
15
|
+
## Installation
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
packages/presentation/
|
|
17
|
-
├── src/
|
|
18
|
-
│ ├── components/ # High-level, styled components
|
|
19
|
-
│ ├── primitives/ # Low-level, base components
|
|
20
|
-
│ └── index.ts # Main entry point
|
|
21
|
-
├── package.json
|
|
22
|
-
├── tsconfig.json
|
|
23
|
-
└── README.md
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @revealui/presentation
|
|
24
19
|
```
|
|
25
20
|
|
|
26
21
|
## Usage
|
|
27
22
|
|
|
28
|
-
### In Apps
|
|
29
|
-
|
|
30
23
|
```typescript
|
|
31
|
-
|
|
32
|
-
import {
|
|
33
|
-
|
|
34
|
-
// Or import specific modules
|
|
35
|
-
import { Button } from '@revealui/presentation/components';
|
|
24
|
+
import { Button, Card, Input, Badge } from '@revealui/presentation'
|
|
25
|
+
import { Box, Flex } from '@revealui/presentation/primitives'
|
|
26
|
+
import { useClickOutside, useFocusTrap } from '@revealui/presentation/hooks'
|
|
36
27
|
```
|
|
37
28
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
29
|
+
## Components (48)
|
|
30
|
+
|
|
31
|
+
### Layout
|
|
32
|
+
| Component | Description |
|
|
33
|
+
|-----------|-------------|
|
|
34
|
+
| AuthLayout | Authentication page layout |
|
|
35
|
+
| SidebarLayout | Sidebar + content layout |
|
|
36
|
+
| StackedLayout | Stacked page layout |
|
|
37
|
+
| Navbar | Top navigation bar |
|
|
38
|
+
| Sidebar | Side navigation |
|
|
39
|
+
|
|
40
|
+
### Form Controls
|
|
41
|
+
| Component | Description |
|
|
42
|
+
|-----------|-------------|
|
|
43
|
+
| Button / ButtonCVA | Action trigger (headless + styled) |
|
|
44
|
+
| Input / InputCVA | Text input (headless + styled) |
|
|
45
|
+
| Textarea / TextareaCVA | Multi-line text (headless + styled) |
|
|
46
|
+
| Checkbox / CheckboxCVA | Checkbox (headless + styled) |
|
|
47
|
+
| Select / SelectCVA | Dropdown select with subcomponents |
|
|
48
|
+
| Combobox | Searchable select |
|
|
49
|
+
| Listbox | List selection |
|
|
50
|
+
| Radio | Radio group |
|
|
51
|
+
| Switch | Toggle switch |
|
|
52
|
+
| Label / FormLabel | Form labels |
|
|
53
|
+
| Fieldset | Form field grouping |
|
|
54
|
+
|
|
55
|
+
### Data Display
|
|
56
|
+
| Component | Description |
|
|
57
|
+
|-----------|-------------|
|
|
58
|
+
| Card | Content container (header, title, description, content, footer) |
|
|
59
|
+
| Table | Data table |
|
|
60
|
+
| Pagination | Page navigation |
|
|
61
|
+
| Badge | Status indicator |
|
|
62
|
+
| Text | Styled text |
|
|
63
|
+
| Heading | Section heading |
|
|
64
|
+
| Divider | Horizontal rule |
|
|
65
|
+
| DescriptionList | Key-value pairs |
|
|
66
|
+
| Breadcrumb | Navigation trail |
|
|
67
|
+
|
|
68
|
+
### Feedback
|
|
69
|
+
| Component | Description |
|
|
70
|
+
|-----------|-------------|
|
|
71
|
+
| Alert | Inline alert message |
|
|
72
|
+
| Callout | Highlighted information |
|
|
73
|
+
| Toast | Temporary notification (with provider + hook) |
|
|
74
|
+
| Tooltip | Hover information |
|
|
75
|
+
| Progress | Progress bar |
|
|
76
|
+
| Slider | Range input |
|
|
77
|
+
| Skeleton | Loading placeholder |
|
|
78
|
+
| EmptyState | No-data placeholder |
|
|
79
|
+
| Stat | Metric display (with StatGroup) |
|
|
80
|
+
| Rating | Star rating |
|
|
81
|
+
|
|
82
|
+
### Navigation
|
|
83
|
+
| Component | Description |
|
|
84
|
+
|-----------|-------------|
|
|
85
|
+
| Accordion | Collapsible sections |
|
|
86
|
+
| Tabs | Tab panels |
|
|
87
|
+
| Stepper | Step-by-step progress |
|
|
88
|
+
| Timeline | Chronological events |
|
|
89
|
+
| Dropdown | Action menu |
|
|
90
|
+
| Drawer | Slide-out panel |
|
|
91
|
+
| Dialog | Modal dialog |
|
|
92
|
+
|
|
93
|
+
### Media & Misc
|
|
94
|
+
| Component | Description |
|
|
95
|
+
|-----------|-------------|
|
|
96
|
+
| Avatar / AvatarGroup | User avatars |
|
|
97
|
+
| CodeBlock | Syntax-highlighted code |
|
|
98
|
+
| Kbd / KbdShortcut | Keyboard shortcut display |
|
|
99
|
+
| Link | Styled anchor |
|
|
100
|
+
|
|
101
|
+
## Primitives (6)
|
|
102
|
+
|
|
103
|
+
| Primitive | Description |
|
|
104
|
+
|-----------|-------------|
|
|
105
|
+
| Box | Generic container |
|
|
106
|
+
| Flex | Flexbox layout |
|
|
107
|
+
| Grid | CSS Grid layout |
|
|
108
|
+
| Heading | Semantic heading |
|
|
109
|
+
| Text | Text content |
|
|
110
|
+
| Slot | Component composition utility |
|
|
111
|
+
|
|
112
|
+
## Hooks (14)
|
|
113
|
+
|
|
114
|
+
| Hook | Purpose |
|
|
115
|
+
|------|---------|
|
|
116
|
+
| useClickOutside | Detect clicks outside an element |
|
|
117
|
+
| useCloseContext | Shared close handler context |
|
|
118
|
+
| useControllableState | Controlled/uncontrolled state |
|
|
119
|
+
| useDataInteractive | Interactive element data attributes |
|
|
120
|
+
| useEscapeKey | Escape key handler |
|
|
121
|
+
| useFieldContext | Form field context (label, error, description) |
|
|
122
|
+
| useFocusTrap | Trap focus within an element |
|
|
123
|
+
| useLayoutAnimation | Animated layout transitions |
|
|
124
|
+
| usePopover | Popover positioning |
|
|
125
|
+
| useRovingTabindex | Keyboard navigation in groups |
|
|
126
|
+
| useScrollLock | Prevent body scroll |
|
|
127
|
+
| useToggle | Boolean toggle state |
|
|
128
|
+
| useTransition | CSS transitions |
|
|
129
|
+
| useTypeAhead | Type-ahead search in lists |
|
|
130
|
+
|
|
131
|
+
## Exports
|
|
132
|
+
|
|
133
|
+
| Subpath | Contents |
|
|
134
|
+
|---------|----------|
|
|
135
|
+
| `@revealui/presentation` | All components, primitives, and hooks |
|
|
136
|
+
| `@revealui/presentation/server` | Server components |
|
|
137
|
+
| `@revealui/presentation/client` | Client components |
|
|
138
|
+
| `@revealui/presentation/components` | Components only |
|
|
139
|
+
| `@revealui/presentation/primitives` | Primitives only |
|
|
140
|
+
| `@revealui/presentation/hooks` | Hooks only |
|
|
53
141
|
|
|
54
142
|
## Development
|
|
55
143
|
|
|
56
144
|
```bash
|
|
57
145
|
# Build
|
|
58
|
-
pnpm
|
|
146
|
+
pnpm build
|
|
59
147
|
|
|
60
148
|
# Type check
|
|
61
|
-
pnpm
|
|
149
|
+
pnpm typecheck
|
|
62
150
|
|
|
63
151
|
# Watch mode
|
|
64
|
-
pnpm
|
|
152
|
+
pnpm dev
|
|
65
153
|
```
|
|
154
|
+
|
|
155
|
+
## Adding Components
|
|
156
|
+
|
|
157
|
+
1. Create component in `src/components/` (styled) or `src/primitives/` (unstyled)
|
|
158
|
+
2. Export from the respective `index.ts`
|
|
159
|
+
3. Use CVA for variant-based styling
|
|
160
|
+
4. Follow WCAG 2.1 accessibility patterns
|
|
161
|
+
|
|
162
|
+
## Related
|
|
163
|
+
|
|
164
|
+
- [Core Package](../core/README.md) — CMS engine (uses presentation components)
|
|
165
|
+
- [Architecture Guide](../../docs/ARCHITECTURE.md)
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
function r(e) {
|
|
4
|
+
var t, f, n = "";
|
|
5
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
6
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
7
|
+
var o = e.length;
|
|
8
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
9
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
10
|
+
return n;
|
|
11
|
+
}
|
|
12
|
+
function clsx() {
|
|
13
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
14
|
+
return n;
|
|
15
|
+
}
|
|
16
|
+
const falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
|
|
17
|
+
const cx = clsx;
|
|
18
|
+
const cva = (base, config) => (props) => {
|
|
19
|
+
var _config_compoundVariants;
|
|
20
|
+
if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
21
|
+
const { variants, defaultVariants } = config;
|
|
22
|
+
const getVariantClassNames = Object.keys(variants).map((variant) => {
|
|
23
|
+
const variantProp = props === null || props === void 0 ? void 0 : props[variant];
|
|
24
|
+
const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
|
|
25
|
+
if (variantProp === null) return null;
|
|
26
|
+
const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
|
|
27
|
+
return variants[variant][variantKey];
|
|
28
|
+
});
|
|
29
|
+
const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
|
|
30
|
+
let [key, value] = param;
|
|
31
|
+
if (value === void 0) {
|
|
32
|
+
return acc;
|
|
33
|
+
}
|
|
34
|
+
acc[key] = value;
|
|
35
|
+
return acc;
|
|
36
|
+
}, {});
|
|
37
|
+
const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param) => {
|
|
38
|
+
let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;
|
|
39
|
+
return Object.entries(compoundVariantOptions).every((param2) => {
|
|
40
|
+
let [key, value] = param2;
|
|
41
|
+
return Array.isArray(value) ? value.includes({
|
|
42
|
+
...defaultVariants,
|
|
43
|
+
...propsWithoutUndefined
|
|
44
|
+
}[key]) : {
|
|
45
|
+
...defaultVariants,
|
|
46
|
+
...propsWithoutUndefined
|
|
47
|
+
}[key] === value;
|
|
48
|
+
}) ? [
|
|
49
|
+
...acc,
|
|
50
|
+
cvClass,
|
|
51
|
+
cvClassName
|
|
52
|
+
] : acc;
|
|
53
|
+
}, []);
|
|
54
|
+
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
55
|
+
};
|
|
56
|
+
function cn(...inputs) {
|
|
57
|
+
const classes = [];
|
|
58
|
+
for (const input of inputs.flat()) {
|
|
59
|
+
if (!input) continue;
|
|
60
|
+
if (typeof input === "string" || typeof input === "number") {
|
|
61
|
+
classes.push(String(input));
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (typeof input === "object") {
|
|
65
|
+
for (const [key, value] of Object.entries(input)) {
|
|
66
|
+
if (value) {
|
|
67
|
+
classes.push(key);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return classes.join(" ").trim();
|
|
73
|
+
}
|
|
74
|
+
function Slot({ children, asChild, ref, ...slotProps }) {
|
|
75
|
+
if (asChild && React.isValidElement(children)) {
|
|
76
|
+
return React.cloneElement(children, {
|
|
77
|
+
...slotProps,
|
|
78
|
+
...children.props,
|
|
79
|
+
ref
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ jsx("div", { ...slotProps, ref, children });
|
|
83
|
+
}
|
|
84
|
+
const buttonVariants = cva(
|
|
85
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
86
|
+
{
|
|
87
|
+
defaultVariants: {
|
|
88
|
+
size: "default",
|
|
89
|
+
variant: "default"
|
|
90
|
+
},
|
|
91
|
+
variants: {
|
|
92
|
+
size: {
|
|
93
|
+
clear: "",
|
|
94
|
+
default: "h-10 px-4 py-2",
|
|
95
|
+
icon: "size-10",
|
|
96
|
+
lg: "h-11 rounded px-8",
|
|
97
|
+
sm: "h-9 rounded px-3"
|
|
98
|
+
},
|
|
99
|
+
variant: {
|
|
100
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
101
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
102
|
+
ghost: "hover:bg-card hover:text-accent-foreground",
|
|
103
|
+
link: "text-primary items-start justify-start underline-offset-4 hover:underline",
|
|
104
|
+
outline: "border border-border bg-background hover:bg-card hover:text-accent-foreground",
|
|
105
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
106
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
function Button({ asChild = false, className, size, variant, ref, ...props }) {
|
|
112
|
+
const Comp = asChild ? Slot : "button";
|
|
113
|
+
return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ className, size, variant })), ref, ...props });
|
|
114
|
+
}
|
|
115
|
+
const ChevronLeft = ({ className }) => {
|
|
116
|
+
return /* @__PURE__ */ jsxs(
|
|
117
|
+
"svg",
|
|
118
|
+
{
|
|
119
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
120
|
+
fill: "none",
|
|
121
|
+
viewBox: "0 0 24 24",
|
|
122
|
+
strokeWidth: 1.5,
|
|
123
|
+
stroke: "currentColor",
|
|
124
|
+
className: cn("size-6", className),
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ jsx("title", { children: "Previous page" }),
|
|
127
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5 8.25 12l7.5-7.5" })
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
const ChevronRight = ({ className }) => {
|
|
133
|
+
return /* @__PURE__ */ jsxs(
|
|
134
|
+
"svg",
|
|
135
|
+
{
|
|
136
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
137
|
+
fill: "none",
|
|
138
|
+
viewBox: "0 0 24 24",
|
|
139
|
+
strokeWidth: 1.5,
|
|
140
|
+
stroke: "currentColor",
|
|
141
|
+
className: cn("size-6", className),
|
|
142
|
+
children: [
|
|
143
|
+
/* @__PURE__ */ jsx("title", { children: "Next page" }),
|
|
144
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m8.25 4.5 7.5 7.5-7.5 7.5" })
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
const MoreHorizontal = ({ className }) => {
|
|
150
|
+
return /* @__PURE__ */ jsxs(
|
|
151
|
+
"svg",
|
|
152
|
+
{
|
|
153
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
154
|
+
fill: "none",
|
|
155
|
+
viewBox: "0 0 24 6",
|
|
156
|
+
className: cn("size-6", className),
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ jsx("title", { children: "More pages" }),
|
|
159
|
+
/* @__PURE__ */ jsx("circle", { cx: "6", cy: "3", r: "3", fill: "currentColor" }),
|
|
160
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "3", r: "3", fill: "currentColor" }),
|
|
161
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "3", r: "3", fill: "currentColor" })
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
const Pagination = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
167
|
+
"nav",
|
|
168
|
+
{
|
|
169
|
+
"aria-label": "pagination",
|
|
170
|
+
className: cn("mx-auto flex w-full justify-center", className),
|
|
171
|
+
...props
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
function PaginationContent({
|
|
175
|
+
className,
|
|
176
|
+
ref,
|
|
177
|
+
...props
|
|
178
|
+
}) {
|
|
179
|
+
return /* @__PURE__ */ jsx("ul", { className: cn("flex flex-row items-center gap-1", className), ref, ...props });
|
|
180
|
+
}
|
|
181
|
+
function PaginationItem({
|
|
182
|
+
className,
|
|
183
|
+
ref,
|
|
184
|
+
...props
|
|
185
|
+
}) {
|
|
186
|
+
return /* @__PURE__ */ jsx("li", { className: cn("", className), ref, ...props });
|
|
187
|
+
}
|
|
188
|
+
const PaginationLink = ({
|
|
189
|
+
className,
|
|
190
|
+
isActive,
|
|
191
|
+
size = "icon",
|
|
192
|
+
disabled,
|
|
193
|
+
...props
|
|
194
|
+
}) => /* @__PURE__ */ jsx(
|
|
195
|
+
"button",
|
|
196
|
+
{
|
|
197
|
+
"aria-current": isActive ? "page" : void 0,
|
|
198
|
+
"aria-disabled": disabled ? true : void 0,
|
|
199
|
+
disabled,
|
|
200
|
+
className: cn(
|
|
201
|
+
buttonVariants({
|
|
202
|
+
size,
|
|
203
|
+
variant: isActive ? "outline" : "ghost"
|
|
204
|
+
}),
|
|
205
|
+
className
|
|
206
|
+
),
|
|
207
|
+
...props
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
const PaginationPrevious = ({ className, ...props }) => /* @__PURE__ */ jsxs(
|
|
211
|
+
PaginationLink,
|
|
212
|
+
{
|
|
213
|
+
"aria-label": "Go to previous page",
|
|
214
|
+
className: cn("gap-1 pl-2.5", className),
|
|
215
|
+
size: "default",
|
|
216
|
+
...props,
|
|
217
|
+
children: [
|
|
218
|
+
/* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" }),
|
|
219
|
+
/* @__PURE__ */ jsx("span", { children: "Previous" })
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
const PaginationNext = ({ className, ...props }) => /* @__PURE__ */ jsxs(
|
|
224
|
+
PaginationLink,
|
|
225
|
+
{
|
|
226
|
+
"aria-label": "Go to next page",
|
|
227
|
+
className: cn("gap-1 pr-2.5", className),
|
|
228
|
+
size: "default",
|
|
229
|
+
...props,
|
|
230
|
+
children: [
|
|
231
|
+
/* @__PURE__ */ jsx("span", { children: "Next" }),
|
|
232
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "size-4" })
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
const PaginationEllipsis = ({ className, ...props }) => /* @__PURE__ */ jsxs(
|
|
237
|
+
"span",
|
|
238
|
+
{
|
|
239
|
+
"aria-hidden": true,
|
|
240
|
+
className: cn("flex h-9 w-9 items-center justify-center", className),
|
|
241
|
+
...props,
|
|
242
|
+
children: [
|
|
243
|
+
/* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" }),
|
|
244
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "More pages" })
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
function CheckIcon() {
|
|
249
|
+
return /* @__PURE__ */ jsx(
|
|
250
|
+
"svg",
|
|
251
|
+
{
|
|
252
|
+
className: "h-4 w-4 shrink-0 text-blue-600 mt-0.5",
|
|
253
|
+
fill: "currentColor",
|
|
254
|
+
viewBox: "0 0 20 20",
|
|
255
|
+
"aria-hidden": "true",
|
|
256
|
+
children: /* @__PURE__ */ jsx(
|
|
257
|
+
"path",
|
|
258
|
+
{
|
|
259
|
+
fillRule: "evenodd",
|
|
260
|
+
d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",
|
|
261
|
+
clipRule: "evenodd"
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
function PricingTable({
|
|
268
|
+
tiers,
|
|
269
|
+
currentTier,
|
|
270
|
+
compact = false,
|
|
271
|
+
onSelectTier,
|
|
272
|
+
className
|
|
273
|
+
}) {
|
|
274
|
+
if (compact) {
|
|
275
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-4 sm:flex-row", className), children: tiers.map((tier) => /* @__PURE__ */ jsx(
|
|
276
|
+
PricingCardCompact,
|
|
277
|
+
{
|
|
278
|
+
tier,
|
|
279
|
+
isCurrent: tier.id === currentTier,
|
|
280
|
+
onSelect: onSelectTier
|
|
281
|
+
},
|
|
282
|
+
tier.id
|
|
283
|
+
)) });
|
|
284
|
+
}
|
|
285
|
+
return /* @__PURE__ */ jsx(
|
|
286
|
+
"div",
|
|
287
|
+
{
|
|
288
|
+
className: cn(
|
|
289
|
+
"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4",
|
|
290
|
+
tiers.length === 3 && "lg:grid-cols-3",
|
|
291
|
+
tiers.length === 2 && "lg:grid-cols-2 max-w-3xl mx-auto",
|
|
292
|
+
className
|
|
293
|
+
),
|
|
294
|
+
children: tiers.map((tier) => /* @__PURE__ */ jsx(
|
|
295
|
+
PricingCardFull,
|
|
296
|
+
{
|
|
297
|
+
tier,
|
|
298
|
+
isCurrent: tier.id === currentTier,
|
|
299
|
+
onSelect: onSelectTier
|
|
300
|
+
},
|
|
301
|
+
tier.id
|
|
302
|
+
))
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
function PricingCardFull({
|
|
307
|
+
tier,
|
|
308
|
+
isCurrent,
|
|
309
|
+
onSelect
|
|
310
|
+
}) {
|
|
311
|
+
const isHighlighted = tier.highlighted && !isCurrent;
|
|
312
|
+
return /* @__PURE__ */ jsxs(
|
|
313
|
+
"div",
|
|
314
|
+
{
|
|
315
|
+
className: cn(
|
|
316
|
+
"relative rounded-2xl bg-white p-8 shadow-lg dark:bg-zinc-900",
|
|
317
|
+
isHighlighted ? "ring-2 ring-blue-600" : isCurrent ? "ring-2 ring-emerald-500" : "ring-1 ring-zinc-200 dark:ring-zinc-800"
|
|
318
|
+
),
|
|
319
|
+
children: [
|
|
320
|
+
isHighlighted && /* @__PURE__ */ jsx("div", { className: "absolute -top-4 left-0 right-0 mx-auto w-32 rounded-full bg-gradient-to-r from-blue-600 to-indigo-600 px-3 py-1.5 text-sm font-semibold text-white text-center shadow-lg", children: "Most Popular" }),
|
|
321
|
+
isCurrent && /* @__PURE__ */ jsx("div", { className: "absolute -top-4 left-0 right-0 mx-auto w-32 rounded-full bg-emerald-600 px-3 py-1.5 text-sm font-semibold text-white text-center shadow-lg", children: "Current Plan" }),
|
|
322
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
323
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-bold tracking-tight text-zinc-900 dark:text-white", children: tier.name }),
|
|
324
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-zinc-600 dark:text-zinc-400", children: tier.description }),
|
|
325
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-6 flex items-baseline gap-x-1", children: [
|
|
326
|
+
/* @__PURE__ */ jsx("span", { className: "text-4xl font-bold tracking-tight text-zinc-900 dark:text-white", children: tier.price ?? "—" }),
|
|
327
|
+
tier.period && /* @__PURE__ */ jsx("span", { className: "text-sm text-zinc-600 dark:text-zinc-400", children: tier.period })
|
|
328
|
+
] })
|
|
329
|
+
] }),
|
|
330
|
+
/* @__PURE__ */ jsx("ul", { className: "mb-8 space-y-3", children: tier.features.map((feature) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-x-3", children: [
|
|
331
|
+
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
332
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-zinc-600 dark:text-zinc-400", children: feature })
|
|
333
|
+
] }, feature)) }),
|
|
334
|
+
onSelect ? /* @__PURE__ */ jsx(
|
|
335
|
+
"button",
|
|
336
|
+
{
|
|
337
|
+
type: "button",
|
|
338
|
+
onClick: () => onSelect(tier.id),
|
|
339
|
+
disabled: isCurrent,
|
|
340
|
+
className: cn(
|
|
341
|
+
"block w-full rounded-md px-6 py-3 text-center text-sm font-semibold transition-colors",
|
|
342
|
+
isCurrent ? "cursor-default bg-emerald-50 text-emerald-700 dark:bg-emerald-900/20 dark:text-emerald-400" : isHighlighted ? "bg-blue-600 text-white hover:bg-blue-500 shadow-sm" : "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
|
|
343
|
+
),
|
|
344
|
+
children: isCurrent ? "Current Plan" : tier.cta
|
|
345
|
+
}
|
|
346
|
+
) : /* @__PURE__ */ jsx(
|
|
347
|
+
"a",
|
|
348
|
+
{
|
|
349
|
+
href: tier.ctaHref,
|
|
350
|
+
className: cn(
|
|
351
|
+
"block w-full rounded-md px-6 py-3 text-center text-sm font-semibold transition-colors",
|
|
352
|
+
isHighlighted ? "bg-blue-600 text-white hover:bg-blue-500 shadow-sm" : "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
|
|
353
|
+
),
|
|
354
|
+
children: tier.cta
|
|
355
|
+
}
|
|
356
|
+
)
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
function PricingCardCompact({
|
|
362
|
+
tier,
|
|
363
|
+
isCurrent,
|
|
364
|
+
onSelect
|
|
365
|
+
}) {
|
|
366
|
+
return /* @__PURE__ */ jsxs(
|
|
367
|
+
"div",
|
|
368
|
+
{
|
|
369
|
+
className: cn(
|
|
370
|
+
"flex-1 rounded-xl p-5 shadow-sm dark:bg-zinc-900",
|
|
371
|
+
isCurrent ? "ring-2 ring-emerald-500 bg-emerald-50/50 dark:bg-emerald-900/10" : tier.highlighted ? "ring-2 ring-blue-600 bg-blue-50/50 dark:bg-blue-900/10" : "ring-1 ring-zinc-200 bg-white dark:ring-zinc-800"
|
|
372
|
+
),
|
|
373
|
+
children: [
|
|
374
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
375
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-bold text-zinc-900 dark:text-white", children: tier.name }),
|
|
376
|
+
isCurrent && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-emerald-100 px-2 py-0.5 text-xs font-medium text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", children: "Current" })
|
|
377
|
+
] }),
|
|
378
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 flex items-baseline gap-x-1", children: [
|
|
379
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-zinc-900 dark:text-white", children: tier.price ?? "—" }),
|
|
380
|
+
tier.period && /* @__PURE__ */ jsx("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: tier.period })
|
|
381
|
+
] }),
|
|
382
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400 line-clamp-2", children: tier.description }),
|
|
383
|
+
onSelect ? /* @__PURE__ */ jsx(
|
|
384
|
+
"button",
|
|
385
|
+
{
|
|
386
|
+
type: "button",
|
|
387
|
+
onClick: () => onSelect(tier.id),
|
|
388
|
+
disabled: isCurrent,
|
|
389
|
+
className: cn(
|
|
390
|
+
"mt-3 block w-full rounded-md px-3 py-2 text-center text-xs font-semibold transition-colors",
|
|
391
|
+
isCurrent ? "cursor-default bg-emerald-50 text-emerald-700 dark:bg-emerald-900/20 dark:text-emerald-400" : tier.highlighted ? "bg-blue-600 text-white hover:bg-blue-500" : "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
|
|
392
|
+
),
|
|
393
|
+
children: isCurrent ? "Current" : tier.cta
|
|
394
|
+
}
|
|
395
|
+
) : /* @__PURE__ */ jsx(
|
|
396
|
+
"a",
|
|
397
|
+
{
|
|
398
|
+
href: tier.ctaHref,
|
|
399
|
+
className: cn(
|
|
400
|
+
"mt-3 block w-full rounded-md px-3 py-2 text-center text-xs font-semibold transition-colors",
|
|
401
|
+
tier.highlighted ? "bg-blue-600 text-white hover:bg-blue-500" : "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
|
|
402
|
+
),
|
|
403
|
+
children: tier.cta
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
function Box({ as: Component = "div", className, ref, ...props }) {
|
|
411
|
+
return /* @__PURE__ */ jsx(Component, { ref, className: cn(className), ...props });
|
|
412
|
+
}
|
|
413
|
+
export {
|
|
414
|
+
Box as B,
|
|
415
|
+
Pagination as P,
|
|
416
|
+
Slot as S,
|
|
417
|
+
Button as a,
|
|
418
|
+
PaginationContent as b,
|
|
419
|
+
PaginationEllipsis as c,
|
|
420
|
+
PaginationItem as d,
|
|
421
|
+
PaginationLink as e,
|
|
422
|
+
PaginationNext as f,
|
|
423
|
+
PaginationPrevious as g,
|
|
424
|
+
PricingTable as h,
|
|
425
|
+
buttonVariants as i,
|
|
426
|
+
cn as j,
|
|
427
|
+
cva as k,
|
|
428
|
+
clsx as l
|
|
429
|
+
};
|
|
430
|
+
//# sourceMappingURL=Box-DC3F8eRf.js.map
|