@saasflare/ui 1.0.0 → 1.0.1
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 +258 -0
- package/dist/button-B2DR7obe.d.mts +316 -0
- package/dist/button-B2DR7obe.d.ts +316 -0
- package/dist/chunk-7UB3R5JU.js +590 -0
- package/dist/chunk-JOVJRQO3.js +13 -0
- package/dist/chunk-P2JF7JDY.mjs +550 -0
- package/dist/chunk-S26666D6.mjs +11 -0
- package/dist/entries/carousel.d.mts +24 -0
- package/dist/entries/carousel.d.ts +24 -0
- package/dist/entries/carousel.js +223 -0
- package/dist/entries/carousel.mjs +194 -0
- package/dist/entries/chart.d.mts +69 -0
- package/dist/entries/chart.d.ts +69 -0
- package/dist/entries/chart.js +265 -0
- package/dist/entries/chart.mjs +237 -0
- package/dist/index.d.mts +173 -545
- package/dist/index.d.ts +173 -545
- package/dist/index.js +1094 -2018
- package/dist/index.mjs +650 -1638
- package/package.json +82 -18
package/README.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# @saasflare/ui
|
|
2
|
+
|
|
3
|
+
The Saasflare design system — an opinionated, themeable React component library
|
|
4
|
+
for **Next.js 16 + Tailwind CSS v4**, animated by default. Every component is
|
|
5
|
+
motion-aware, powered by Framer Motion and `LazyMotion` for a tight ~25 KB
|
|
6
|
+
runtime overhead.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @saasflare/ui
|
|
10
|
+
# or
|
|
11
|
+
pnpm add @saasflare/ui
|
|
12
|
+
# or
|
|
13
|
+
yarn add @saasflare/ui
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- **Repo:** https://github.com/saasflare/saasflare-ui
|
|
17
|
+
- **Catalog:** https://ui.saasflare.io
|
|
18
|
+
- **Demo:** https://demo.saasflare.io
|
|
19
|
+
- **License:** MIT
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Highlights
|
|
24
|
+
|
|
25
|
+
- **80+ components** — primitives (Button, Dialog, Form, Select, …) and composed
|
|
26
|
+
widgets (PricingCard, FeatureCard, MetricCard, BentoGrid, …).
|
|
27
|
+
- **Animated by default** — every interactive primitive ships with motion via
|
|
28
|
+
Framer Motion + `LazyMotion features={domAnimation}` (~25 KB gzip total).
|
|
29
|
+
- **Tailwind v4 native** — tokens declared via `@theme`, no `tailwind.config.ts`
|
|
30
|
+
extension required.
|
|
31
|
+
- **Theming via CSS variables** — switch palettes by setting `data-palette="…"`
|
|
32
|
+
on `<html>`. 17 presets shipped, custom palettes are one CSS block.
|
|
33
|
+
- **Light / dark out of the box** — driven by `next-themes`.
|
|
34
|
+
- **TypeScript strict** — full types, no `any`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Peer dependencies
|
|
39
|
+
|
|
40
|
+
`@saasflare/ui` is a Next.js-first library. The required peers reflect actual
|
|
41
|
+
runtime coupling — there is no graceful degradation if they are missing.
|
|
42
|
+
|
|
43
|
+
### Required
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm add react react-dom next next-themes framer-motion
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
| Peer | Range | Notes |
|
|
50
|
+
| --------------- | --------------------------- | ---------------------------------------- |
|
|
51
|
+
| `react` | `^18.2.0 \|\| ^19.0.0` | |
|
|
52
|
+
| `react-dom` | `^18.2.0 \|\| ^19.0.0` | |
|
|
53
|
+
| `next` | `^16.0.0` | Next 16 only — buyers on 15 upgrade first |
|
|
54
|
+
| `next-themes` | `^0.4.0` | Light/dark mode driver |
|
|
55
|
+
| `framer-motion` | `^12.0.0` | Used eagerly by core primitives |
|
|
56
|
+
|
|
57
|
+
`tailwindcss` is **not** a peer dependency — it's a build-time tool. Install it
|
|
58
|
+
in your app and add a `@source` directive (see Setup below).
|
|
59
|
+
|
|
60
|
+
### Optional (per-component)
|
|
61
|
+
|
|
62
|
+
These peers are only needed if you import the matching components.
|
|
63
|
+
`peerDependenciesMeta.optional` is set, so package managers won't warn if you
|
|
64
|
+
skip them.
|
|
65
|
+
|
|
66
|
+
| Component(s) | Install |
|
|
67
|
+
| ------------------------- | -------------------------------------------------------- |
|
|
68
|
+
| `Form` + resolvers | `react-hook-form@^7`, `@hookform/resolvers@^5`, `zod@^4` |
|
|
69
|
+
| `Toast` (`Toaster`) | `sonner@^2` |
|
|
70
|
+
| `Drawer` | `vaul@^1` |
|
|
71
|
+
| `Calendar` | `react-day-picker@^9`, `date-fns@^4` |
|
|
72
|
+
| `Resizable` | `react-resizable-panels@^4` |
|
|
73
|
+
|
|
74
|
+
### Subpath imports (heavy peers — install only when used)
|
|
75
|
+
|
|
76
|
+
| Subpath | Install |
|
|
77
|
+
| ------------------------ | -------------------------------- |
|
|
78
|
+
| `@saasflare/ui/chart` | `recharts@^3` (~95 KB gzip) |
|
|
79
|
+
| `@saasflare/ui/carousel` | `embla-carousel-react@^8` (~25 KB) |
|
|
80
|
+
|
|
81
|
+
These two components are deliberately **not** in the main barrel — importing
|
|
82
|
+
them through their subpath keeps the heavy peer out of consumers who don't use
|
|
83
|
+
them.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Setup
|
|
88
|
+
|
|
89
|
+
### 1. Import the styles bundle and configure Tailwind
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
/* app/globals.css */
|
|
93
|
+
@import "@saasflare/ui/styles";
|
|
94
|
+
@source "../node_modules/@saasflare/ui/dist/**/*.{js,mjs}";
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `@source` directive tells Tailwind v4's JIT engine to scan the package's
|
|
98
|
+
compiled output for utility classes (otherwise they get purged). The `@import
|
|
99
|
+
"@saasflare/ui/styles"` line pulls in the `@theme` token block, palette presets,
|
|
100
|
+
light/dark surface variables, and motion tokens.
|
|
101
|
+
|
|
102
|
+
> **Tailwind v3 users:** add the dist path to `content` in `tailwind.config.{js,ts}`:
|
|
103
|
+
> ```ts
|
|
104
|
+
> content: ["./node_modules/@saasflare/ui/dist/**/*.{js,mjs}", /* ... */]
|
|
105
|
+
> ```
|
|
106
|
+
|
|
107
|
+
### 2. Wrap your app in `SaasflareShell` *(mandatory)*
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
// app/layout.tsx
|
|
111
|
+
import { SaasflareShell } from "@saasflare/ui";
|
|
112
|
+
import { fontVariables } from "@saasflare/ui/fonts/default";
|
|
113
|
+
import "./globals.css";
|
|
114
|
+
|
|
115
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
116
|
+
return (
|
|
117
|
+
<html lang="en" className={fontVariables} data-palette="saasflare" suppressHydrationWarning>
|
|
118
|
+
<body>
|
|
119
|
+
<SaasflareShell>{children}</SaasflareShell>
|
|
120
|
+
</body>
|
|
121
|
+
</html>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
> **⚠️ The wrapper is required, not optional.** `@saasflare/ui` uses
|
|
127
|
+
> `LazyMotion features={domAnimation} strict` to keep the framer-motion bundle
|
|
128
|
+
> tight. Animated components use the `m.*` API (e.g. `m.button`) which throws
|
|
129
|
+
> at runtime if the `LazyMotion` provider is missing. `SaasflareShell` (or
|
|
130
|
+
> `SaasflareProvider` directly) provides it. Without one, every `Button`,
|
|
131
|
+
> `Card`, `Dialog`, etc. will error on mount.
|
|
132
|
+
|
|
133
|
+
`SaasflareShell` also owns the theme class, smooth-scroll context, and the
|
|
134
|
+
animation kill-switch context.
|
|
135
|
+
|
|
136
|
+
### 3. Use components
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { Button, Card, CardHeader, CardTitle, CardContent } from "@saasflare/ui";
|
|
140
|
+
|
|
141
|
+
export function Example() {
|
|
142
|
+
return (
|
|
143
|
+
<Card>
|
|
144
|
+
<CardHeader>
|
|
145
|
+
<CardTitle>Hello Saasflare</CardTitle>
|
|
146
|
+
</CardHeader>
|
|
147
|
+
<CardContent>
|
|
148
|
+
<Button>Get started</Button>
|
|
149
|
+
</CardContent>
|
|
150
|
+
</Card>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
For chart/carousel:
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import { ChartContainer, ChartTooltip } from "@saasflare/ui/chart";
|
|
159
|
+
import { Carousel, CarouselContent, CarouselItem } from "@saasflare/ui/carousel";
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Theming
|
|
165
|
+
|
|
166
|
+
### Switch palette at runtime
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<html data-palette="ocean">
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Built-in presets: `saasflare` (default), `ocean`, `ink`, `aurora`, `indigo`,
|
|
173
|
+
`emerald`, `violet`, `coral`, `stone`, `jade`, `cobalt`, `amber`, `fuchsia`,
|
|
174
|
+
`honey`, `teal`, `iris`, `ruby`.
|
|
175
|
+
|
|
176
|
+
### Define a custom palette
|
|
177
|
+
|
|
178
|
+
Add a block to your global CSS:
|
|
179
|
+
|
|
180
|
+
```css
|
|
181
|
+
:root[data-palette="brand"] {
|
|
182
|
+
--primary-h: 220;
|
|
183
|
+
--primary-c: 0.18;
|
|
184
|
+
--primary-l: 55%;
|
|
185
|
+
/* see packages/ui/styles/palettes.css for the full token list */
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Light / dark
|
|
190
|
+
|
|
191
|
+
`SaasflareShell` integrates with `next-themes`. Drop in the `ThemeModeToggle`
|
|
192
|
+
component or call `useSaasflareTheme()` for a programmatic API.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Fonts
|
|
197
|
+
|
|
198
|
+
Six curated presets ship with the package. Pick one or roll your own:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { fontVariables } from "@saasflare/ui/fonts/default";
|
|
202
|
+
// or: "@saasflare/ui/fonts/editorial"
|
|
203
|
+
// "@saasflare/ui/fonts/geometric"
|
|
204
|
+
// "@saasflare/ui/fonts/rounded"
|
|
205
|
+
// "@saasflare/ui/fonts/distinctive"
|
|
206
|
+
// "@saasflare/ui/fonts/neutral"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Apply `fontVariables` to `<html>` or `<body>` — the CSS variables defined by
|
|
210
|
+
the design system pick them up automatically.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Subpath exports
|
|
215
|
+
|
|
216
|
+
| Path | What it is |
|
|
217
|
+
| --------------------------------- | ------------------------------------------------------------------- |
|
|
218
|
+
| `@saasflare/ui` | Core: components, hooks, providers, utilities |
|
|
219
|
+
| `@saasflare/ui/chart` | Chart primitives (requires `recharts`) |
|
|
220
|
+
| `@saasflare/ui/carousel` | Carousel primitives (requires `embla-carousel-react`) |
|
|
221
|
+
| `@saasflare/ui/styles` | Full CSS bundle (alias for `globals.css`) |
|
|
222
|
+
| `@saasflare/ui/globals.css` | Same as above, explicit |
|
|
223
|
+
| `@saasflare/ui/theme.css` | Token root only (advanced use) |
|
|
224
|
+
| `@saasflare/ui/fonts` | Font preset registry |
|
|
225
|
+
| `@saasflare/ui/fonts/{preset}` | `default`, `editorial`, `geometric`, `rounded`, `distinctive`, `neutral` |
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## What's exported from the main entry
|
|
230
|
+
|
|
231
|
+
- **Utilities:** `cn`
|
|
232
|
+
- **Hooks:** `useIsMobile`, `useReducedMotion`, `useDisclosure`, `useMeasure`,
|
|
233
|
+
`usePagination`
|
|
234
|
+
- **Providers:** `SaasflareShell`, `SaasflareProvider`, `SaasflareScript`,
|
|
235
|
+
`SmoothScrollProvider`, `useSaasflareTheme`, `useSaasflareProps`,
|
|
236
|
+
`useAnimation`
|
|
237
|
+
- **Type tokens:** `PALETTES`, `STYLES`, `RADII`, plus matching TS types
|
|
238
|
+
(`PaletteId`, `StyleVariant`, `Palette`, `Surface`, `Radius`, `Size`,
|
|
239
|
+
`Density`, …)
|
|
240
|
+
- **Composed widgets:** `ScrollToTopButton`, `ThemeModeToggle`,
|
|
241
|
+
`TopLoadingBar`, `UserAvatar`
|
|
242
|
+
- **All core UI primitives** from `components/ui` (Chart and Carousel are
|
|
243
|
+
*not* here — see Subpath imports above) — full list and live examples in
|
|
244
|
+
the [catalog](https://ui.saasflare.io).
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Versioning
|
|
249
|
+
|
|
250
|
+
Semantic versioning. Breaking changes to component props, theme tokens, or
|
|
251
|
+
palette names ship as major bumps. Release notes live on
|
|
252
|
+
[GitHub Releases](https://github.com/saasflare/saasflare-ui/releases).
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
MIT © Saasflare
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Theme-related types and constants consumed by SaasflareProvider,
|
|
8
|
+
* SaasflareShell, and CustomPaletteInjector.
|
|
9
|
+
* @module packages/ui/types/theme-props
|
|
10
|
+
* @package ui
|
|
11
|
+
*
|
|
12
|
+
* Palette colors live in `styles/palettes.css` (OKLCH) — the single source of
|
|
13
|
+
* truth. To render a swatch in a picker, wrap an element in `data-palette={id}`
|
|
14
|
+
* and paint it with `oklch(var(--primary-l) var(--primary-c) var(--primary-h))`.
|
|
15
|
+
* Do NOT add a hex `color` field here; it will drift from palettes.css.
|
|
16
|
+
*/
|
|
17
|
+
/** All 16 available color palette ids and display names. */
|
|
18
|
+
declare const PALETTES: readonly [{
|
|
19
|
+
readonly id: "ocean";
|
|
20
|
+
readonly name: "Ocean";
|
|
21
|
+
}, {
|
|
22
|
+
readonly id: "achromatic";
|
|
23
|
+
readonly name: "Achromatic";
|
|
24
|
+
}, {
|
|
25
|
+
readonly id: "black";
|
|
26
|
+
readonly name: "Black";
|
|
27
|
+
}, {
|
|
28
|
+
readonly id: "ink";
|
|
29
|
+
readonly name: "Ink";
|
|
30
|
+
}, {
|
|
31
|
+
readonly id: "aurora";
|
|
32
|
+
readonly name: "Aurora";
|
|
33
|
+
}, {
|
|
34
|
+
readonly id: "indigo";
|
|
35
|
+
readonly name: "Indigo";
|
|
36
|
+
}, {
|
|
37
|
+
readonly id: "emerald";
|
|
38
|
+
readonly name: "Emerald";
|
|
39
|
+
}, {
|
|
40
|
+
readonly id: "violet";
|
|
41
|
+
readonly name: "Violet";
|
|
42
|
+
}, {
|
|
43
|
+
readonly id: "coral";
|
|
44
|
+
readonly name: "Coral";
|
|
45
|
+
}, {
|
|
46
|
+
readonly id: "stone";
|
|
47
|
+
readonly name: "Stone";
|
|
48
|
+
}, {
|
|
49
|
+
readonly id: "jade";
|
|
50
|
+
readonly name: "Jade";
|
|
51
|
+
}, {
|
|
52
|
+
readonly id: "cobalt";
|
|
53
|
+
readonly name: "Cobalt";
|
|
54
|
+
}, {
|
|
55
|
+
readonly id: "amber";
|
|
56
|
+
readonly name: "Amber";
|
|
57
|
+
}, {
|
|
58
|
+
readonly id: "fuchsia";
|
|
59
|
+
readonly name: "Fuchsia";
|
|
60
|
+
}, {
|
|
61
|
+
readonly id: "honey";
|
|
62
|
+
readonly name: "Honey";
|
|
63
|
+
}, {
|
|
64
|
+
readonly id: "teal";
|
|
65
|
+
readonly name: "Teal";
|
|
66
|
+
}, {
|
|
67
|
+
readonly id: "iris";
|
|
68
|
+
readonly name: "Iris";
|
|
69
|
+
}, {
|
|
70
|
+
readonly id: "ruby";
|
|
71
|
+
readonly name: "Ruby";
|
|
72
|
+
}];
|
|
73
|
+
/** Union of all preset color palette IDs. */
|
|
74
|
+
type PaletteId = (typeof PALETTES)[number]["id"];
|
|
75
|
+
/**
|
|
76
|
+
* Visual surface style variant.
|
|
77
|
+
*
|
|
78
|
+
* The union uses `(string & {})` so app-level custom surfaces (e.g.
|
|
79
|
+
* "neumorphic") registered via a [data-style="…"] selector in the
|
|
80
|
+
* app's globals.css are accepted without a type patch, while preset
|
|
81
|
+
* ids keep their autocomplete.
|
|
82
|
+
*/
|
|
83
|
+
type StyleVariant = "flat" | "glass" | (string & {});
|
|
84
|
+
/** All available built-in surface style variants. */
|
|
85
|
+
declare const STYLES: readonly [{
|
|
86
|
+
readonly id: "flat";
|
|
87
|
+
readonly name: "Flat";
|
|
88
|
+
}, {
|
|
89
|
+
readonly id: "glass";
|
|
90
|
+
readonly name: "Glass";
|
|
91
|
+
}];
|
|
92
|
+
/**
|
|
93
|
+
* Radius preset — orthogonal to {@link Surface} (geometry vs. material).
|
|
94
|
+
*
|
|
95
|
+
* Maps to `[data-radius]` selectors in theme.css; each preset sets `--radius`
|
|
96
|
+
* (and at "pill" also overrides the entire `--radius-sm/md/lg/xl` scale so
|
|
97
|
+
* derived values don't drift to ~9995px).
|
|
98
|
+
*
|
|
99
|
+
* Per-component override: pass `radius` on any Saasflare component.
|
|
100
|
+
* Per-theme override: `CustomPalette.radius` wins via inline style.
|
|
101
|
+
*/
|
|
102
|
+
type Radius = "sharp" | "soft" | "rounded" | "pill";
|
|
103
|
+
/** All available built-in radius presets. */
|
|
104
|
+
declare const RADII: readonly [{
|
|
105
|
+
readonly id: "sharp";
|
|
106
|
+
readonly name: "Sharp";
|
|
107
|
+
}, {
|
|
108
|
+
readonly id: "soft";
|
|
109
|
+
readonly name: "Soft";
|
|
110
|
+
}, {
|
|
111
|
+
readonly id: "rounded";
|
|
112
|
+
readonly name: "Rounded";
|
|
113
|
+
}, {
|
|
114
|
+
readonly id: "pill";
|
|
115
|
+
readonly name: "Pill";
|
|
116
|
+
}];
|
|
117
|
+
/**
|
|
118
|
+
* Custom color theme — high-level, developer-friendly.
|
|
119
|
+
*
|
|
120
|
+
* Pass any CSS color as `primary` (hex, oklch, rgb, hsl, named color).
|
|
121
|
+
* Hex values are converted to OKLCH internally via {@link hexToOklch};
|
|
122
|
+
* other formats are passed through as the raw `--primary` value.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* <SaasflareProvider
|
|
126
|
+
* palette={{ name: "acme", primary: "#007AFF" }}
|
|
127
|
+
* />
|
|
128
|
+
*
|
|
129
|
+
* @example Escape hatch for full control
|
|
130
|
+
* <SaasflareProvider palette={{
|
|
131
|
+
* name: "acme",
|
|
132
|
+
* primary: "#007AFF",
|
|
133
|
+
* light: { "--background": "#fafafa" },
|
|
134
|
+
* dark: { "--background": "#0a0a0a" },
|
|
135
|
+
* }} />
|
|
136
|
+
*/
|
|
137
|
+
interface CustomPalette {
|
|
138
|
+
/** Unique name — written to `data-palette` attribute. */
|
|
139
|
+
name: string;
|
|
140
|
+
/** Primary brand color in any CSS color format. Required. */
|
|
141
|
+
primary: string;
|
|
142
|
+
/**
|
|
143
|
+
* Optional neutral axis override — drives backgrounds, muted, borders,
|
|
144
|
+
* cards, popovers, sidebar (i.e. the entire grey foundation of the UI),
|
|
145
|
+
* not just one accent token. Accepts hex or an explicit hue angle (0-360).
|
|
146
|
+
* Default: tinted from `primary` with a tiny chroma for "brand warmth".
|
|
147
|
+
*/
|
|
148
|
+
neutral?: string;
|
|
149
|
+
/** Optional border radius override (any CSS length). */
|
|
150
|
+
radius?: string;
|
|
151
|
+
/** Escape hatch: raw CSS custom property overrides applied in light mode. */
|
|
152
|
+
light?: Record<string, string>;
|
|
153
|
+
/** Escape hatch: raw CSS custom property overrides applied in dark mode. */
|
|
154
|
+
dark?: Record<string, string>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Accepted values for the `palette` prop (brand colors — distinct from `theme`,
|
|
158
|
+
* which controls light/dark mode and is delegated to next-themes).
|
|
159
|
+
*
|
|
160
|
+
* - omit (undefined) → defers to persisted user preference, then global.css baseline
|
|
161
|
+
* - PaletteId → preset palette via [data-palette] selector
|
|
162
|
+
* - arbitrary string → app-registered [data-palette="…"] in the app's globals.css
|
|
163
|
+
* - CustomPalette → runtime palette via inline CSS custom properties
|
|
164
|
+
*
|
|
165
|
+
* The `(string & {})` branch preserves autocomplete for the 16 preset ids
|
|
166
|
+
* while still permitting arbitrary strings.
|
|
167
|
+
*/
|
|
168
|
+
type Palette = PaletteId | (string & {}) | CustomPalette;
|
|
169
|
+
/**
|
|
170
|
+
* Accepted values for the `surface` prop.
|
|
171
|
+
*
|
|
172
|
+
* - omit (undefined) → defers to persisted user preference, then "flat" baseline
|
|
173
|
+
* - StyleVariant → "flat" | "glass" | app-registered custom surface
|
|
174
|
+
*/
|
|
175
|
+
type Surface = StyleVariant;
|
|
176
|
+
/**
|
|
177
|
+
* Accepted values for the `radius` prop on SaasflareProvider / Shell.
|
|
178
|
+
*
|
|
179
|
+
* - omit (undefined) → defers to persisted user preference, then "rounded" baseline
|
|
180
|
+
* - Radius → forces [data-radius] on <html>
|
|
181
|
+
*/
|
|
182
|
+
type RadiusProp = Radius;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @fileoverview Base props and resolver hook for Saasflare components.
|
|
186
|
+
* @module packages/ui/providers/use-saasflare-props
|
|
187
|
+
* @package ui
|
|
188
|
+
*
|
|
189
|
+
* Every Saasflare component MUST:
|
|
190
|
+
* 1. Extend SaasflareComponentProps in its props interface
|
|
191
|
+
* 2. Call useSaasflareProps(props) to resolve effective values
|
|
192
|
+
*
|
|
193
|
+
* This ensures consistent precedence:
|
|
194
|
+
* component prop > provider context > hardcoded defaults
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* interface CardProps extends SaasflareComponentProps {
|
|
198
|
+
* title: string
|
|
199
|
+
* }
|
|
200
|
+
*
|
|
201
|
+
* function Card({ title, ...sfProps }: CardProps) {
|
|
202
|
+
* const { surface, radius, animated } = useSaasflareProps(sfProps)
|
|
203
|
+
* // surface/radius are guaranteed to be resolved, never undefined
|
|
204
|
+
* }
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
/** Props that every Saasflare component accepts for theme integration. */
|
|
208
|
+
interface SaasflareComponentProps {
|
|
209
|
+
/** Surface style override. Omit to inherit from provider. */
|
|
210
|
+
surface?: StyleVariant;
|
|
211
|
+
/** Radius preset override. Omit to inherit from provider. */
|
|
212
|
+
radius?: Radius;
|
|
213
|
+
/** Animation override. Omit to inherit from provider. */
|
|
214
|
+
animated?: boolean;
|
|
215
|
+
}
|
|
216
|
+
/** Fully resolved theme values — no optionals, no undefined. */
|
|
217
|
+
interface ResolvedSaasflareProps {
|
|
218
|
+
/** Active surface style. */
|
|
219
|
+
surface: StyleVariant;
|
|
220
|
+
/** Active radius preset. */
|
|
221
|
+
radius: Radius;
|
|
222
|
+
/** Whether animations are enabled. */
|
|
223
|
+
animated: boolean;
|
|
224
|
+
/** Active brand palette id (null = global.css baseline). */
|
|
225
|
+
palette: string | null;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Resolves component-level overrides against the provider context.
|
|
229
|
+
*
|
|
230
|
+
* Precedence: component prop > provider context > hardcoded default
|
|
231
|
+
*
|
|
232
|
+
* Safe without a provider — returns sensible defaults.
|
|
233
|
+
*/
|
|
234
|
+
declare function useSaasflareProps(props?: SaasflareComponentProps): ResolvedSaasflareProps;
|
|
235
|
+
|
|
236
|
+
declare const INTENTS: readonly ["primary", "neutral", "success", "warning", "danger", "info"];
|
|
237
|
+
type Intent = (typeof INTENTS)[number];
|
|
238
|
+
/**
|
|
239
|
+
* Button variant definitions using the 3-axis system.
|
|
240
|
+
*
|
|
241
|
+
* Axes:
|
|
242
|
+
* variant — visual treatment: solid, soft, outline, ghost, link, glass, shadow
|
|
243
|
+
* intent — color intent via data-intent attribute + CSS tokens
|
|
244
|
+
* size — dimensional: xs, sm, md, lg, xl, icon, icon-xs, icon-sm, icon-lg
|
|
245
|
+
*/
|
|
246
|
+
declare const buttonVariants: (props?: ({
|
|
247
|
+
variant?: "link" | "glass" | "soft" | "solid" | "outline" | "ghost" | "shadow" | null | undefined;
|
|
248
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
249
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
250
|
+
/** Framer-motion event overrides that conflict with React HTML events */
|
|
251
|
+
type MotionConflicts = "onDrag" | "onDragStart" | "onDragEnd" | "onAnimationStart" | "onAnimationEnd";
|
|
252
|
+
/**
|
|
253
|
+
* Props for the Saasflare Button component.
|
|
254
|
+
*
|
|
255
|
+
* Extends {@link SaasflareComponentProps} to accept `surface` and `animated`
|
|
256
|
+
* overrides that are resolved against the <SaasflareProvider> context.
|
|
257
|
+
*/
|
|
258
|
+
interface ButtonProps extends Omit<React.ComponentProps<"button">, MotionConflicts>, VariantProps<typeof buttonVariants>, SaasflareComponentProps {
|
|
259
|
+
/** Render as child element (Radix Slot pattern) */
|
|
260
|
+
asChild?: boolean;
|
|
261
|
+
/** Semantic color intent */
|
|
262
|
+
intent?: Intent;
|
|
263
|
+
/** Show loading spinner (replaces left icon, keeps text visible) */
|
|
264
|
+
loading?: boolean;
|
|
265
|
+
/** Stretch to full width of container */
|
|
266
|
+
fullWidth?: boolean;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Primary interactive button with motion, loading, and intent support.
|
|
270
|
+
*
|
|
271
|
+
* Resolves `surface` and `animated` via {@link useSaasflareProps} with the
|
|
272
|
+
* precedence: component prop > <SaasflareProvider> context > hardcoded default.
|
|
273
|
+
*
|
|
274
|
+
* When no explicit `variant` is set and the resolved surface is `"glass"`, the
|
|
275
|
+
* button promotes itself to `variant="glass"`. An explicit `variant` prop always
|
|
276
|
+
* wins over the surface-based promotion.
|
|
277
|
+
*
|
|
278
|
+
* @component
|
|
279
|
+
* @layer ui
|
|
280
|
+
*
|
|
281
|
+
* @param {string} variant - Visual treatment: "solid" | "soft" | "outline" | "ghost" | "link" | "glass" | "shadow"
|
|
282
|
+
* @param {string} intent - Color intent: "primary" | "neutral" | "success" | "warning" | "danger" | "info"
|
|
283
|
+
* @param {string} size - Button size: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
|
|
284
|
+
* @param {string} surface - Surface style override: "flat" | "glass" (inherits from provider when omitted)
|
|
285
|
+
* @param {boolean} animated - Gate motion effects (inherits from provider when omitted)
|
|
286
|
+
* @param {boolean} loading - Shows spinner, sets aria-busy, preserves width
|
|
287
|
+
* @param {boolean} fullWidth - Stretches to container width
|
|
288
|
+
* @param {boolean} asChild - Render as child element (Slot pattern)
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* // Solid primary (default)
|
|
292
|
+
* <Button>Save Changes</Button>
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* // Outline danger
|
|
296
|
+
* <Button variant="outline" intent="danger">Delete Account</Button>
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* // Inherits surface from provider — auto-promotes to glass variant
|
|
300
|
+
* <SaasflareProvider surface="glass"><Button>Frosted</Button></SaasflareProvider>
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* // Loading state
|
|
304
|
+
* <Button loading>Processing...</Button>
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* // Icon button
|
|
308
|
+
* <Button variant="ghost" size="icon"><SettingsIcon /></Button>
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* // Legacy API (deprecated but supported)
|
|
312
|
+
* <Button variant="destructive">Delete</Button>
|
|
313
|
+
*/
|
|
314
|
+
declare function Button({ className, variant: variantProp, size, intent: intentProp, asChild, loading, fullWidth, surface, animated, disabled, children, ...props }: ButtonProps): react_jsx_runtime.JSX.Element;
|
|
315
|
+
|
|
316
|
+
export { Button as B, type CustomPalette as C, type Intent as I, type Palette as P, type RadiusProp as R, type Surface as S, type StyleVariant as a, type Radius as b, type SaasflareComponentProps as c, type ButtonProps as d, PALETTES as e, type PaletteId as f, RADII as g, type ResolvedSaasflareProps as h, STYLES as i, buttonVariants as j, useSaasflareProps as u };
|