@mikenotthepope/substrateui 0.1.2 → 0.1.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to SubstrateUI will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-04-04
9
+
10
+ ### Added
11
+ - Initial release
12
+ - 75 UI components built on Radix UI primitives
13
+ - 3-layer OKLCH color token system (raw palette → semantic → Tailwind utilities)
14
+ - Dark mode via semantic token swap (`.dark` class)
15
+ - Layout primitives: Stack, Cluster, Grid, Center, Divider, Spacer
16
+ - Form patterns: Field (with context), FormSection, FormActions, Fieldset
17
+ - App shell organisms: AppShell, PageHeader, PageBody, PageTabs, StatCard
18
+ - Typography system: H1-H4, P, Lead, Large, Small, Muted, Code, Mono
19
+ - Data display: DataTable with sorting, filtering, pagination, row selection
20
+ - Custom components: Combobox (single/multi), SearchField, InputGroup, ButtonGroup, DatePicker, Kbd, Spinner, Empty, NativeSelect, Item
21
+ - Tailwind CSS v4 native (`@theme inline`, CSS-first configuration)
22
+ - Full TypeScript support with exported types
23
+ - Tree-shakeable ESM exports via three entry points
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 mikenotthepope
3
+ Copyright (c) 2025 SubstrateUI
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,226 +1,159 @@
1
- # Substrate UI
1
+ # SubstrateUI
2
2
 
3
- A neobrutalist React component library with bold borders, hard shadows, and high contrast design. Built on [Radix UI](https://www.radix-ui.com/) primitives and [Tailwind CSS v4](https://tailwindcss.com/).
3
+ A chunky, opinionated design system for Next.js OKLCH tokens, Tailwind CSS v4, Radix UI primitives.
4
4
 
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg)](LICENSE)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-strict-black.svg)](https://www.typescriptlang.org/)
7
- [![React 19](https://img.shields.io/badge/React-19-black.svg)](https://react.dev/)
5
+ [![npm version](https://img.shields.io/npm/v/substrateui.svg)](https://www.npmjs.com/package/substrateui)
6
+ [![license](https://img.shields.io/npm/l/substrateui.svg)](https://github.com/substrateui/substrateui/blob/main/LICENSE)
8
7
 
9
- **[Documentation & Demos](https://www.substrateui.dev)** | **[Storybook](https://www.substrateui.dev)** | **[npm](https://www.npmjs.com/package/@mikenotthepope/substrateui)**
8
+ <!-- Replace <OWNER>/<REPO> with the GitHub owner/repo once the repo is pushed,
9
+ and <VERCEL-PRODUCTION-URL> with the production URL after Vercel deploys. -->
10
+ ## Status
10
11
 
11
- ---
12
+ [![CI](https://github.com/<OWNER>/<REPO>/actions/workflows/ci.yml/badge.svg)](https://github.com/<OWNER>/<REPO>/actions/workflows/ci.yml)
12
13
 
13
- ## Why Substrate UI?
14
+ - **Docs:** <VERCEL-PRODUCTION-URL>
15
+ - **Storybook:** https://substrateui.dev/storybook/ — run locally with `bun run storybook`
16
+ - **npm:** `@substrateui/core` (not yet published)
14
17
 
15
- Most component libraries optimize for invisibility — neutral colors, subtle shadows, rounded everything. Substrate UI goes the other direction: **hard pixel-offset shadows, bold borders, and sharp corners by default.** It's opinionated about aesthetics but flexible about theming, built on Radix UI so accessibility comes free.
18
+ ## Features
16
19
 
17
- - **57 UI primitives** Button, Dialog, Tabs, Select, DataTable, and more
18
- - **12 landing page components** Hero, Pricing, FAQ, Testimonials, and more
19
- - **5 composite layouts** NavBar, CardGrid, SectionNav, SimplePage, TwoColumnLayout
20
- - **Light & dark themes** with CSS custom properties
21
- - **Tree-shakeable** ESM + CJS builds
22
- - **Full TypeScript** support with exported types
20
+ - 75 components from atomic Button to organism App Shell
21
+ - 3-layer OKLCH color system: raw palette semantic tokens Tailwind utilities
22
+ - Dark mode as a token swap zero component changes
23
+ - Chunky 2px borders and press-down animations
24
+ - CVD-safe plum + amber color pairing
25
+ - WCAG AA contrast verified on every token pairing — see [contrast report](./audit-contrast-report.md)
26
+ - Built for Tailwind CSS v4 (`@theme inline`, CSS-first config)
27
+ - Full TypeScript support with exported types
28
+ - Tree-shakeable ESM exports
23
29
 
24
30
  ## Quick Start
25
31
 
26
- ### Install
27
-
28
32
  ```bash
29
- npm install @mikenotthepope/substrateui
33
+ npm install substrateui
30
34
  ```
31
35
 
32
- Requires `react` and `react-dom` v19+ as peer dependencies.
33
-
34
- ### Import the stylesheet
35
-
36
- Add the base stylesheet once in your app root. This provides all design tokens and component styles.
37
-
38
- ```tsx
39
- // app/layout.tsx (Next.js) or src/main.tsx (Vite)
40
- import "@mikenotthepope/substrateui/styles";
41
- ```
36
+ ### CSS Setup
42
37
 
43
- ### Use components
44
-
45
- ```tsx
46
- import { Button, Card, Text } from "@mikenotthepope/substrateui";
47
-
48
- export function Example() {
49
- return (
50
- <Card>
51
- <Card.Header>
52
- <Text variant="h3">Hello</Text>
53
- </Card.Header>
54
- <Card.Body>
55
- <Text>Neobrutalist components, ready to go.</Text>
56
- <Button>Get Started</Button>
57
- </Card.Body>
58
- </Card>
59
- );
60
- }
38
+ ```css
39
+ /* globals.css */
40
+ @import "tailwindcss";
41
+ @import "tw-animate-css";
42
+ @import "substrateui/styles.css";
43
+ @source "../node_modules/substrateui";
61
44
  ```
62
45
 
63
- ## Fonts
64
-
65
- Substrate UI uses three font families via CSS custom properties:
66
-
67
- | Token | Default Font | Purpose |
68
- | -------------- | --------------- | ---------- |
69
- | `--font-head` | Bricolage Grotesque | Headings |
70
- | `--font-sans` | Space Grotesk | Body text |
71
- | `--font-mono` | Space Mono | Code |
72
-
73
- **Next.js:**
46
+ ### Font Setup (recommended)
74
47
 
75
48
  ```tsx
76
- import { Space_Grotesk, Bricolage_Grotesque, Space_Mono } from "next/font/google";
49
+ // layout.tsx
50
+ import { DM_Sans, DM_Mono } from "next/font/google"
77
51
 
78
- const sans = Space_Grotesk({ variable: "--font-sans", subsets: ["latin"], weight: "400" });
79
- const head = Bricolage_Grotesque({ variable: "--font-head", subsets: ["latin"], weight: ["400", "700", "800"] });
80
- const mono = Space_Mono({ variable: "--font-mono", subsets: ["latin"], weight: "400" });
52
+ const sans = DM_Sans({ subsets: ["latin"], variable: "--font-sans" })
53
+ const mono = DM_Mono({ weight: ["400", "500"], subsets: ["latin"], variable: "--font-mono" })
81
54
 
82
- export default function RootLayout({ children }) {
55
+ export default function Layout({ children }: { children: React.ReactNode }) {
83
56
  return (
84
- <html className={`${sans.variable} ${head.variable} ${mono.variable}`}>
57
+ <html className={`${sans.variable} ${mono.variable}`}>
85
58
  <body>{children}</body>
86
59
  </html>
87
- );
60
+ )
88
61
  }
89
62
  ```
90
63
 
91
- **Plain HTML / Vite:**
92
-
93
- ```html
94
- <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;700;800&family=Space+Grotesk:wght@400;500;700&family=Space+Mono&display=swap" rel="stylesheet">
95
- <style>
96
- :root {
97
- --font-head: 'Bricolage Grotesque', sans-serif;
98
- --font-sans: 'Space Grotesk', sans-serif;
99
- --font-mono: 'Space Mono', monospace;
100
- }
101
- </style>
102
- ```
103
-
104
- If fonts aren't loaded, the library falls back to `Space Grotesk -> system-ui -> sans-serif`.
105
-
106
- ## Theming
107
-
108
- ### Light / Dark Mode
109
-
110
- Use the built-in `ThemeProvider` to manage theme switching:
64
+ ### Dark Mode
111
65
 
112
66
  ```tsx
113
- import { ThemeProvider } from "@mikenotthepope/substrateui";
67
+ import { ThemeProvider } from "next-themes"
114
68
 
115
- function App({ children }) {
116
- return (
117
- <ThemeProvider defaultTheme="system">
118
- {children}
119
- </ThemeProvider>
120
- );
121
- }
69
+ // Wrap your app:
70
+ <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
71
+ {children}
72
+ </ThemeProvider>
122
73
  ```
123
74
 
124
- Access and toggle the theme anywhere:
75
+ ### Use Components
125
76
 
126
77
  ```tsx
127
- import { useTheme } from "@mikenotthepope/substrateui";
128
-
129
- function ThemeToggle() {
130
- const { theme, setTheme } = useTheme();
131
- return (
132
- <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
133
- Toggle theme
134
- </button>
135
- );
136
- }
78
+ import { Button, Stack, Card, CardHeader, CardTitle, CardContent } from "substrateui"
79
+ import { AppShell, AppShellSidebar, AppShellMain } from "substrateui/organisms"
80
+ import { cn } from "substrateui/utils"
137
81
  ```
138
82
 
139
- Accepts `"light"`, `"dark"`, or `"system"` (default). Persists to `localStorage` and respects `prefers-color-scheme`.
83
+ ## Exports
140
84
 
141
- ### Rounded Corners
142
-
143
- Components have sharp corners by default. Add `with-radius` to opt in to rounded corners:
144
-
145
- ```html
146
- <html class="with-radius">
147
- ```
85
+ | Import path | Contents |
86
+ |---|---|
87
+ | `substrateui` | All 75 UI primitives (Button, Card, Input, Table, etc.) |
88
+ | `substrateui/organisms` | App-level patterns (AppShell, PageHeader, PageBody, PageTabs, StatCard) |
89
+ | `substrateui/utils` | `cn()` utility (clsx + tailwind-merge) |
90
+ | `substrateui/styles.css` | OKLCH token system + Tailwind theme + base styles |
148
91
 
149
- ### Custom Tokens
150
-
151
- Override any CSS custom property to customize the theme:
152
-
153
- ```css
154
- :root {
155
- --primary: #6366f1;
156
- --primary-foreground: #fff;
157
- --primary-hover: #4f46e5;
158
- }
159
- ```
92
+ ## Requirements
160
93
 
161
- See the full token reference in `base/substrate.css`.
94
+ - React 18+
95
+ - Tailwind CSS 4+
96
+ - `tw-animate-css` (for animations)
97
+ - `next-themes` (optional, for dark mode toggle)
98
+ - `next` 15+ (optional, only for `substrateui/organisms` which use `next/link`)
162
99
 
163
- ## Components
100
+ ## Token Architecture
164
101
 
165
- ### Primitives
102
+ SubstrateUI uses a 3-layer OKLCH color system:
166
103
 
167
- Accordion, Alert, AlertDialog, Avatar, Badge, Breadcrumb, Button, Calendar, Card, Carousel, Chart, Checkbox, Collapsible, Combobox, Command, Container, ContextMenu, DataTable, Dialog, Divider, Drawer, DropdownMenu, Flex, Form, FormLayout, Grid, HoverCard, IconButton, ImageCard, Input, InputOTP, Label, Link, Loader, Marquee, Menu, Menubar, NavigationMenu, Pagination, Popover, Progress, RadioGroup, Resizable, ScrollArea, Select, Sheet, Sidebar, Skeleton, Slider, Sonner, Stack, Switch, Table, Tabs, Text, Textarea, Tooltip
104
+ 1. **Raw palette** OKLCH values (`--raw-plum-600`, `--raw-amber-500`, etc.)
105
+ 2. **Semantic tokens** — Purpose-based mappings (`--primary`, `--surface-raised`, `--status-error`, etc.) with automatic dark mode via `.dark` class
106
+ 3. **Tailwind utilities** — `@theme inline` maps tokens to `bg-primary`, `text-foreground`, `border-border`, etc.
168
107
 
169
- ### Landing
108
+ ## Component Categories
170
109
 
171
- AnnouncementBanner, CTABanner, FAQ, FeatureSection, Footer, Hero, LogoCloud, NewsletterSignup, PricingTable, Section, StatsBar, Testimonial
110
+ - **General** Button, ButtonGroup, Badge, Kbd, Spinner, Empty
111
+ - **Typography** — H1-H4, P, Lead, Large, Small, Muted, Code, Mono
112
+ - **Layout** — Stack, Cluster, Grid, Center, Divider, Spacer, Separator, AspectRatio, ResizablePanels
113
+ - **Forms** — Input, Textarea, Select, NativeSelect, Checkbox, RadioGroup, Switch, Slider, DatePicker, Combobox, InputGroup, InputOTP, SearchField, Field, Fieldset, FormSection, FormActions
114
+ - **Data Display** — Card, Table, DataTable, Avatar, Calendar, Carousel, Chart, HoverCard, Item
115
+ - **Feedback** — Alert, AlertDialog, Dialog, Progress, Skeleton, Sonner (toast)
116
+ - **Overlays** — Sheet, Drawer, Popover, Tooltip, ContextMenu, DropdownMenu, Command
117
+ - **Navigation** — Tabs, Breadcrumb, NavigationMenu, Menubar, Pagination, ScrollArea, Sidebar, Collapsible, Accordion
118
+ - **Patterns** — AppShell, PageHeader, PageBody, PageTabs, StatCard
172
119
 
173
- ### Composite
120
+ ## Customization
174
121
 
175
- CardGrid, NavBar, SectionNav, SimplePage, TwoColumnLayout
122
+ Override tokens after importing the stylesheet:
176
123
 
177
- ## Framework Compatibility
124
+ ```css
125
+ /* After importing substrateui/styles.css */
126
+ :root {
127
+ --primary: oklch(0.55 0.15 250); /* Change primary to blue */
128
+ }
129
+ ```
178
130
 
179
- Works in any React 19 environment — Next.js, Vite, Remix, etc.
131
+ ## Accessibility
180
132
 
181
- The `NavBar` component accepts an optional `linkComponent` prop for framework-specific routing:
133
+ SubstrateUI meets WCAG AA contrast requirements (verified by automated audit) and is built on Radix UI primitives for robust keyboard and screen reader support.
182
134
 
183
- ```tsx
184
- import Link from "next/link";
185
- import { NavBar } from "@mikenotthepope/substrateui";
135
+ - [Accessibility documentation](https://substrateui.dev/docs/accessibility)
136
+ - [Contrast audit report](./audit-contrast-report.md)
186
137
 
187
- <NavBar linkComponent={Link} brand={{ name: "MyApp" }} auth={{ state: "signed-out", href: "/login" }} />
188
- ```
138
+ Every component ships with accessible defaults. For guidance on specific components, see the "Accessibility" section on each component's documentation page.
189
139
 
190
- When omitted, it defaults to a plain `<a>` tag.
140
+ ## Storybook
191
141
 
192
- ## Development
142
+ Contributors can browse components in isolation, flip between light/dark themes, swap `ltr`/`rtl` direction, and switch the semantic palette (Plum / Forest) from the toolbar.
193
143
 
194
144
  ```bash
195
- bun install # Install dependencies
196
- bun dev # Start the demo app (Next.js)
197
- bun storybook # Start Storybook
198
- bun test # Run tests
199
- bun run build # Build the library (tsup)
200
- ```
201
-
202
- ### Project Structure
203
-
204
- ```
205
- substrateui/
206
- ├── src/index.ts # Barrel export for the published package
207
- ├── components/ui/ # 57 primitive components
208
- ├── components/landing/ # 12 landing page components
209
- ├── components/ # Composite components + ThemeProvider
210
- ├── base/substrate.css # Design tokens & base styles
211
- ├── app/ # Next.js demo/docs site
212
- ├── AGENTS.md # Shared AI agent instructions
213
- ├── CLAUDE.md # Claude Code config (imports AGENTS.md)
214
- └── tsup.config.ts # Library build config
145
+ bun run storybook # dev server on http://localhost:6006
146
+ bun run build-storybook # static bundle in ./storybook-static
215
147
  ```
216
148
 
217
- ## Acknowledgements
149
+ Hosted build: https://substrateui.dev/storybook/
218
150
 
219
- Substrate UI draws inspiration from these projects:
151
+ ## Links
220
152
 
221
- - [neobrutalism-components](https://github.com/ekmas/neobrutalism-components) by ekmas
222
- - [RetroUI](https://github.com/logging-studio/retroui) by Logging Studio
153
+ - [GitHub](https://github.com/substrateui/substrateui)
154
+ - [npm](https://www.npmjs.com/package/substrateui)
155
+ - [Storybook](https://substrateui.dev/storybook/)
223
156
 
224
157
  ## License
225
158
 
226
- [MIT](LICENSE)
159
+ MIT
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __defProps = Object.defineProperties;
7
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __spreadValues = (a, b) => {
13
+ for (var prop in b || (b = {}))
14
+ if (__hasOwnProp.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ if (__getOwnPropSymbols)
17
+ for (var prop of __getOwnPropSymbols(b)) {
18
+ if (__propIsEnum.call(b, prop))
19
+ __defNormalProp(a, prop, b[prop]);
20
+ }
21
+ return a;
22
+ };
23
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
+ var __objRest = (source, exclude) => {
25
+ var target = {};
26
+ for (var prop in source)
27
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
28
+ target[prop] = source[prop];
29
+ if (source != null && __getOwnPropSymbols)
30
+ for (var prop of __getOwnPropSymbols(source)) {
31
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
32
+ target[prop] = source[prop];
33
+ }
34
+ return target;
35
+ };
36
+ function cn(...inputs) {
37
+ return twMerge(clsx(inputs));
38
+ }
39
+
40
+ export { __objRest, __spreadProps, __spreadValues, cn };
41
+ //# sourceMappingURL=chunk-IQWAGBDM.js.map
42
+ //# sourceMappingURL=chunk-IQWAGBDM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B","file":"chunk-IQWAGBDM.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"]}
@@ -0,0 +1,258 @@
1
+ "use client";
2
+ import { __objRest, __spreadValues, cn } from './chunk-IQWAGBDM.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
6
+
7
+ function Card(_a) {
8
+ var _b = _a, {
9
+ className,
10
+ interactive = false,
11
+ ref
12
+ } = _b, props = __objRest(_b, [
13
+ "className",
14
+ "interactive",
15
+ "ref"
16
+ ]);
17
+ return /* @__PURE__ */ jsx(
18
+ "div",
19
+ __spreadValues({
20
+ ref,
21
+ "data-slot": "card",
22
+ className: cn(
23
+ "rounded-lg border-2 bg-card text-card-foreground shadow-sm",
24
+ interactive && "cursor-pointer hover:border-ring hover:shadow-md transition-all active:translate-y-[1.5px]",
25
+ className
26
+ )
27
+ }, props)
28
+ );
29
+ }
30
+ function CardHeader(_a) {
31
+ var _b = _a, {
32
+ className,
33
+ ref
34
+ } = _b, props = __objRest(_b, [
35
+ "className",
36
+ "ref"
37
+ ]);
38
+ return /* @__PURE__ */ jsx(
39
+ "div",
40
+ __spreadValues({
41
+ ref,
42
+ "data-slot": "card-header",
43
+ className: cn("flex flex-col space-y-1.5 p-6", className)
44
+ }, props)
45
+ );
46
+ }
47
+ function CardTitle(_a) {
48
+ var _b = _a, {
49
+ className,
50
+ ref
51
+ } = _b, props = __objRest(_b, [
52
+ "className",
53
+ "ref"
54
+ ]);
55
+ return /* @__PURE__ */ jsx(
56
+ "div",
57
+ __spreadValues({
58
+ ref,
59
+ "data-slot": "card-title",
60
+ className: cn(
61
+ "text-2xl font-semibold leading-none tracking-tight",
62
+ className
63
+ )
64
+ }, props)
65
+ );
66
+ }
67
+ function CardDescription(_a) {
68
+ var _b = _a, {
69
+ className,
70
+ ref
71
+ } = _b, props = __objRest(_b, [
72
+ "className",
73
+ "ref"
74
+ ]);
75
+ return /* @__PURE__ */ jsx(
76
+ "div",
77
+ __spreadValues({
78
+ ref,
79
+ "data-slot": "card-description",
80
+ className: cn("text-sm text-muted-foreground", className)
81
+ }, props)
82
+ );
83
+ }
84
+ function CardContent(_a) {
85
+ var _b = _a, {
86
+ className,
87
+ ref
88
+ } = _b, props = __objRest(_b, [
89
+ "className",
90
+ "ref"
91
+ ]);
92
+ return /* @__PURE__ */ jsx(
93
+ "div",
94
+ __spreadValues({
95
+ ref,
96
+ "data-slot": "card-content",
97
+ className: cn("p-6 pt-0", className)
98
+ }, props)
99
+ );
100
+ }
101
+ function CardFooter(_a) {
102
+ var _b = _a, {
103
+ className,
104
+ ref
105
+ } = _b, props = __objRest(_b, [
106
+ "className",
107
+ "ref"
108
+ ]);
109
+ return /* @__PURE__ */ jsx(
110
+ "div",
111
+ __spreadValues({
112
+ ref,
113
+ "data-slot": "card-footer",
114
+ className: cn("flex items-center p-6 pt-0", className)
115
+ }, props)
116
+ );
117
+ }
118
+ var maxMap = {
119
+ sm: "max-w-screen-sm",
120
+ md: "max-w-screen-md",
121
+ lg: "max-w-screen-lg",
122
+ xl: "max-w-screen-xl",
123
+ "2xl": "max-w-screen-2xl",
124
+ full: "max-w-full"
125
+ };
126
+ function Center(_a) {
127
+ var _b = _a, {
128
+ max = "2xl",
129
+ padding = true,
130
+ asChild = false,
131
+ className,
132
+ ref
133
+ } = _b, props = __objRest(_b, [
134
+ "max",
135
+ "padding",
136
+ "asChild",
137
+ "className",
138
+ "ref"
139
+ ]);
140
+ const Comp = asChild ? Slot : "div";
141
+ return /* @__PURE__ */ jsx(
142
+ Comp,
143
+ __spreadValues({
144
+ "data-slot": "center",
145
+ className: cn(
146
+ "mx-auto w-full",
147
+ maxMap[max],
148
+ padding && "px-4 sm:px-6 lg:px-8",
149
+ className
150
+ ),
151
+ ref
152
+ }, props)
153
+ );
154
+ }
155
+ var gapMap = {
156
+ none: "gap-0",
157
+ xs: "gap-1",
158
+ sm: "gap-2",
159
+ md: "gap-4",
160
+ lg: "gap-6",
161
+ xl: "gap-8",
162
+ "2xl": "gap-12"
163
+ };
164
+ var alignMap = {
165
+ start: "items-start",
166
+ center: "items-center",
167
+ end: "items-end",
168
+ stretch: "items-stretch"
169
+ };
170
+ function Stack(_a) {
171
+ var _b = _a, {
172
+ gap = "md",
173
+ align = "stretch",
174
+ asChild = false,
175
+ className,
176
+ ref
177
+ } = _b, props = __objRest(_b, [
178
+ "gap",
179
+ "align",
180
+ "asChild",
181
+ "className",
182
+ "ref"
183
+ ]);
184
+ const Comp = asChild ? Slot : "div";
185
+ return /* @__PURE__ */ jsx(
186
+ Comp,
187
+ __spreadValues({
188
+ "data-slot": "stack",
189
+ className: cn("flex flex-col", gapMap[gap], alignMap[align], className),
190
+ ref
191
+ }, props)
192
+ );
193
+ }
194
+ var Tabs = TabsPrimitive.Root;
195
+ function TabsList(_a) {
196
+ var _b = _a, {
197
+ className,
198
+ ref
199
+ } = _b, props = __objRest(_b, [
200
+ "className",
201
+ "ref"
202
+ ]);
203
+ return /* @__PURE__ */ jsx(
204
+ TabsPrimitive.List,
205
+ __spreadValues({
206
+ ref,
207
+ "data-slot": "tabs-list",
208
+ className: cn(
209
+ "inline-flex h-10 items-center justify-center rounded-lg bg-surface-sunken border-2 p-1 text-muted-foreground",
210
+ className
211
+ )
212
+ }, props)
213
+ );
214
+ }
215
+ function TabsTrigger(_a) {
216
+ var _b = _a, {
217
+ className,
218
+ ref
219
+ } = _b, props = __objRest(_b, [
220
+ "className",
221
+ "ref"
222
+ ]);
223
+ return /* @__PURE__ */ jsx(
224
+ TabsPrimitive.Trigger,
225
+ __spreadValues({
226
+ ref,
227
+ "data-slot": "tabs-trigger",
228
+ className: cn(
229
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all active:translate-y-[1.5px] transition-transform focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
230
+ className
231
+ )
232
+ }, props)
233
+ );
234
+ }
235
+ function TabsContent(_a) {
236
+ var _b = _a, {
237
+ className,
238
+ ref
239
+ } = _b, props = __objRest(_b, [
240
+ "className",
241
+ "ref"
242
+ ]);
243
+ return /* @__PURE__ */ jsx(
244
+ TabsPrimitive.Content,
245
+ __spreadValues({
246
+ ref,
247
+ "data-slot": "tabs-content",
248
+ className: cn(
249
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
250
+ className
251
+ )
252
+ }, props)
253
+ );
254
+ }
255
+
256
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Center, Stack, Tabs, TabsContent, TabsList, TabsTrigger };
257
+ //# sourceMappingURL=chunk-IRBORST3.js.map
258
+ //# sourceMappingURL=chunk-IRBORST3.js.map