@fairmint/ui 0.1.0 → 0.1.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 +48 -61
- package/dist/components/AppHeader/AppHeader.d.ts +15 -0
- package/dist/components/AppHeader/AppHeader.d.ts.map +1 -0
- package/dist/components/ErrorFallback/ErrorFallback.d.ts +14 -0
- package/dist/components/ErrorFallback/ErrorFallback.d.ts.map +1 -0
- package/dist/components/FairmintLogo/FairmintLogo.d.ts +14 -0
- package/dist/components/FairmintLogo/FairmintLogo.d.ts.map +1 -0
- package/dist/components/FairmintProvider/FairmintProvider.d.ts +9 -0
- package/dist/components/FairmintProvider/FairmintProvider.d.ts.map +1 -0
- package/dist/components/LoadingSpinner/LoadingSpinner.d.ts +10 -0
- package/dist/components/LoadingSpinner/LoadingSpinner.d.ts.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +11 -0
- package/dist/components/PageHeader/PageHeader.d.ts.map +1 -0
- package/dist/components/SideNav/SideNav.d.ts +21 -0
- package/dist/components/SideNav/SideNav.d.ts.map +1 -0
- package/dist/components/UserMenu/UserMenu.d.ts +31 -0
- package/dist/components/UserMenu/UserMenu.d.ts.map +1 -0
- package/dist/{fairmint-ui.cjs.js → fairmint-ui.cjs} +76 -62
- package/dist/fairmint-ui.cjs.map +1 -0
- package/dist/{fairmint-ui.es.js → fairmint-ui.js} +77 -63
- package/dist/fairmint-ui.js.map +1 -0
- package/dist/index.d.ts +18 -301
- package/dist/index.d.ts.map +1 -0
- package/dist/styles.css +6 -2
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/theme/index.d.ts +170 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/vite.cjs +30 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.ts +18 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +30 -0
- package/dist/vite.js.map +1 -0
- package/package.json +29 -21
- package/dist/fairmint-ui.cjs.js.map +0 -1
- package/dist/fairmint-ui.es.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,101 +1,88 @@
|
|
|
1
1
|
# @fairmint/ui
|
|
2
2
|
|
|
3
|
-
Fairmint's shared design system and UI component library.
|
|
3
|
+
Fairmint's shared design system and UI component library.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
yarn add @fairmint/ui
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Peer dependencies (must be installed in your app):
|
|
7
|
+
### 1. Install
|
|
12
8
|
|
|
13
9
|
```bash
|
|
14
|
-
|
|
10
|
+
bun add @fairmint/ui
|
|
15
11
|
```
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
### CSS
|
|
13
|
+
Mantine is included as a dependency — no extra packages to install.
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
### 2. Import styles
|
|
22
16
|
|
|
23
17
|
```typescript
|
|
24
|
-
import '@
|
|
25
|
-
import '@fairmint/ui/styles.css'; // LoadingSpinner keyframe animation
|
|
18
|
+
import '@fairmint/ui/styles.css';
|
|
26
19
|
```
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
This single import includes both Mantine core styles and Fairmint component styles.
|
|
29
22
|
|
|
30
|
-
###
|
|
23
|
+
### 3. Wrap with provider
|
|
31
24
|
|
|
32
|
-
|
|
25
|
+
```tsx
|
|
26
|
+
import { FairmintProvider } from '@fairmint/ui';
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
|
|
28
|
+
function App() {
|
|
29
|
+
return (
|
|
30
|
+
<FairmintProvider>
|
|
31
|
+
{/* Your app */}
|
|
32
|
+
</FairmintProvider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
38
35
|
```
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
### 4. Use components
|
|
41
38
|
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
import '@fontsource/inter/400.css';
|
|
48
|
-
import '@fontsource/inter/500.css';
|
|
49
|
-
import '@fontsource/inter/600.css';
|
|
50
|
-
import '@fontsource/inter/700.css';
|
|
51
|
-
import '@fontsource/plus-jakarta-sans/600.css';
|
|
52
|
-
import '@fontsource/plus-jakarta-sans/700.css';
|
|
39
|
+
```tsx
|
|
40
|
+
import { PageHeader, FairmintLogo, LoadingSpinner } from '@fairmint/ui';
|
|
53
41
|
```
|
|
54
42
|
|
|
55
|
-
##
|
|
43
|
+
## Local Development (live editing)
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
When working on the UI library alongside a consumer app, add the Vite plugin for instant HMR without building:
|
|
58
46
|
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
import {
|
|
47
|
+
```typescript
|
|
48
|
+
// your-app/vite.config.ts
|
|
49
|
+
import { fairmintUiLocal } from '@fairmint/ui/vite';
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
plugins: [fairmintUiLocal(), react()],
|
|
53
|
+
});
|
|
66
54
|
```
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```tsx
|
|
71
|
-
import { mergeThemeOverrides } from '@mantine/core';
|
|
72
|
-
import { theme as fairmintTheme } from '@fairmint/ui';
|
|
56
|
+
This auto-detects the sibling `design/ui/` repo and resolves imports to local source. Opt out with `LOCAL_UI=0 bun run dev`. In CI the design repo isn't present, so it falls back to the npm package automatically.
|
|
73
57
|
|
|
74
|
-
|
|
75
|
-
```
|
|
58
|
+
## Fonts
|
|
76
59
|
|
|
77
|
-
|
|
60
|
+
Add to your `index.html`:
|
|
78
61
|
|
|
79
|
-
```
|
|
80
|
-
|
|
62
|
+
```html
|
|
63
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
64
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
65
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@600;700&display=swap" rel="stylesheet" />
|
|
81
66
|
```
|
|
82
67
|
|
|
83
|
-
|
|
68
|
+
## Exports
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
70
|
+
| Import | Contents |
|
|
71
|
+
|--------|----------|
|
|
72
|
+
| `@fairmint/ui` | FairmintProvider, theme, components, color constants |
|
|
73
|
+
| `@fairmint/ui/styles.css` | Mantine core CSS + library component CSS |
|
|
74
|
+
| `@fairmint/ui/vite` | `fairmintUiLocal()` Vite plugin for local dev |
|
|
89
75
|
|
|
90
76
|
## Development
|
|
91
77
|
|
|
92
78
|
```bash
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
79
|
+
cd design/ui
|
|
80
|
+
bun run dev # Storybook on port 6006
|
|
81
|
+
bun run build # Build library
|
|
82
|
+
bun run test # Run tests
|
|
83
|
+
bun run lint # Lint (Biome)
|
|
97
84
|
```
|
|
98
85
|
|
|
99
86
|
## Publishing
|
|
100
87
|
|
|
101
|
-
|
|
88
|
+
Automatic on push to `main` when `ui/` files change. Patch version auto-increments if the current version is already published.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface AppHeaderProps {
|
|
3
|
+
/** Logo element (typically FairmintLogo). */
|
|
4
|
+
logo: ReactNode;
|
|
5
|
+
/** Right-aligned content (user menu, actions). */
|
|
6
|
+
rightSection?: ReactNode;
|
|
7
|
+
/** Whether mobile nav is open. Controls burger state. */
|
|
8
|
+
mobileNavOpened?: boolean;
|
|
9
|
+
/** Toggle mobile nav callback. */
|
|
10
|
+
onMobileNavToggle?: () => void;
|
|
11
|
+
/** Header height in pixels. @default 60 */
|
|
12
|
+
height?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function AppHeader({ logo, rightSection, mobileNavOpened, onMobileNavToggle, height, }: AppHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=AppHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../../src/components/AppHeader/AppHeader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,IAAI,EAAE,SAAS,CAAC;IAChB,kDAAkD;IAClD,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,yDAAyD;IACzD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,YAAY,EACZ,eAAuB,EACvB,iBAAiB,EACjB,MAAW,GACZ,EAAE,cAAc,2CAkBhB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ErrorFallbackProps {
|
|
2
|
+
/** Title text. @default "Something went wrong" */
|
|
3
|
+
title?: string;
|
|
4
|
+
/** Description text. @default "We've been notified and are working on a fix." */
|
|
5
|
+
description?: string;
|
|
6
|
+
/** Callback when the user clicks the action button. Defaults to window.location.reload(). */
|
|
7
|
+
onAction?: () => void;
|
|
8
|
+
/** Action button label. @default "Reload Page" */
|
|
9
|
+
actionLabel?: string;
|
|
10
|
+
/** Optional error object for dev-mode display or logging. Compatible with Sentry ErrorBoundary render props. */
|
|
11
|
+
error?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare function ErrorFallback({ title, description, onAction, actionLabel, error, }: ErrorFallbackProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=ErrorFallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorFallback.d.ts","sourceRoot":"","sources":["../../../src/components/ErrorFallback/ErrorFallback.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gHAAgH;IAChH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAA8B,EAC9B,WAA6D,EAC7D,QAAQ,EACR,WAA2B,EAC3B,KAAK,GACN,EAAE,kBAAkB,2CAgBpB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface FairmintLogoProps {
|
|
2
|
+
/** Image source URL. Defaults to the CDN-hosted black wordmark. */
|
|
3
|
+
src?: string;
|
|
4
|
+
/** Width in pixels. @default 140 */
|
|
5
|
+
width?: number;
|
|
6
|
+
/** Height in pixels. @default 30 */
|
|
7
|
+
height?: number;
|
|
8
|
+
/** Additional CSS class. */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Alt text. @default "Fairmint" */
|
|
11
|
+
alt?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function FairmintLogo({ src, width, height, className, alt, }: FairmintLogoProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=FairmintLogo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FairmintLogo.d.ts","sourceRoot":"","sources":["../../../src/components/FairmintLogo/FairmintLogo.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,EAC3B,GAAoG,EACpG,KAAW,EACX,MAAW,EACX,SAAS,EACT,GAAgB,GACjB,EAAE,iBAAiB,2CAWnB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MantineColorScheme } from '@mantine/core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
export interface FairmintProviderProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
/** Color scheme. @default "light" */
|
|
6
|
+
colorScheme?: MantineColorScheme;
|
|
7
|
+
}
|
|
8
|
+
export declare function FairmintProvider({ children, colorScheme }: FairmintProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=FairmintProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FairmintProvider.d.ts","sourceRoot":"","sources":["../../../src/components/FairmintProvider/FairmintProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,SAAS,CAAC;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,WAAqB,EAAE,EAAE,qBAAqB,2CAU1F"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface LoadingSpinnerProps {
|
|
2
|
+
/** Icon size in pixels. @default 32 */
|
|
3
|
+
size?: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Animated certificate icon that fills from bottom to top.
|
|
7
|
+
* Requires the consumer to import `@fairmint/ui/styles.css` for the keyframe animation.
|
|
8
|
+
*/
|
|
9
|
+
export declare function LoadingSpinner({ size }: LoadingSpinnerProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=LoadingSpinner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoadingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/LoadingSpinner/LoadingSpinner.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAS,EAAE,EAAE,mBAAmB,2CA2ChE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface PageHeaderProps {
|
|
3
|
+
/** Page title text. */
|
|
4
|
+
title: string;
|
|
5
|
+
/** Optional subtitle text. */
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
/** Optional right-aligned action element (button, date picker, etc.). */
|
|
8
|
+
action?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare function PageHeader({ title, subtitle, action }: PageHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=PageHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/PageHeader/PageHeader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,eAAe,2CActE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface SideNavItem {
|
|
3
|
+
/** Unique identifier for this nav item (e.g., route path or slug). */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Display label. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Icon element. */
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
/** Whether this item is currently active. */
|
|
10
|
+
active?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SideNavProps {
|
|
13
|
+
/** Navigation items to render. */
|
|
14
|
+
items: SideNavItem[];
|
|
15
|
+
/** Callback when a nav item is clicked. Receives the item's `id`. */
|
|
16
|
+
onItemClick: (id: string) => void;
|
|
17
|
+
/** Active color. @default "indigo" */
|
|
18
|
+
color?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function SideNav({ items, onItemClick, color }: SideNavProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=SideNav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SideNav.d.ts","sourceRoot":"","sources":["../../../src/components/SideNav/SideNav.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,qEAAqE;IACrE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAgB,EAAE,EAAE,YAAY,2CA0B7E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface UserMenuItem {
|
|
3
|
+
/** Unique identifier for this menu item. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Display label. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Icon element. */
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
/** Item color (e.g., "red" for destructive actions). */
|
|
10
|
+
color?: string;
|
|
11
|
+
/** Optional section label above this item. Set on the first item in a group. */
|
|
12
|
+
sectionLabel?: string;
|
|
13
|
+
/** Show a divider before this item. */
|
|
14
|
+
dividerBefore?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface UserMenuProps {
|
|
17
|
+
/** User display name or email. */
|
|
18
|
+
displayName: string;
|
|
19
|
+
/** Single-character avatar initial. Derived from displayName[0] if not provided. */
|
|
20
|
+
avatarInitial?: string;
|
|
21
|
+
/** Avatar color. @default "indigo" */
|
|
22
|
+
avatarColor?: string;
|
|
23
|
+
/** Optional indicator element after the display name (e.g., chevron icon from your app's icon library). */
|
|
24
|
+
indicator?: ReactNode;
|
|
25
|
+
/** Menu items. */
|
|
26
|
+
items: UserMenuItem[];
|
|
27
|
+
/** Callback when a menu item is clicked. Receives the item's `id`. */
|
|
28
|
+
onItemClick: (id: string) => void;
|
|
29
|
+
}
|
|
30
|
+
export declare function UserMenu({ displayName, avatarInitial, avatarColor, indicator, items, onItemClick, }: UserMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
//# sourceMappingURL=UserMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserMenu.d.ts","sourceRoot":"","sources":["../../../src/components/UserMenu/UserMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kBAAkB;IAClB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,sEAAsE;IACtE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,QAAQ,CAAC,EACvB,WAAW,EACX,aAAa,EACb,WAAsB,EACtB,SAAS,EACT,KAAK,EACL,WAAW,GACZ,EAAE,aAAa,2CAsCf"}
|
|
@@ -1,7 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const core = require("@mantine/core");
|
|
4
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const core = require("@mantine/core");
|
|
5
|
+
function AppHeader({
|
|
6
|
+
logo,
|
|
7
|
+
rightSection,
|
|
8
|
+
mobileNavOpened = false,
|
|
9
|
+
onMobileNavToggle,
|
|
10
|
+
height = 60
|
|
11
|
+
}) {
|
|
12
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(core.Group, { h: height, px: "md", justify: "space-between", children: [
|
|
13
|
+
/* @__PURE__ */ jsxRuntime.jsxs(core.Group, { children: [
|
|
14
|
+
onMobileNavToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15
|
+
core.Burger,
|
|
16
|
+
{
|
|
17
|
+
opened: mobileNavOpened,
|
|
18
|
+
onClick: onMobileNavToggle,
|
|
19
|
+
hiddenFrom: "sm",
|
|
20
|
+
size: "sm",
|
|
21
|
+
"aria-label": "Toggle navigation"
|
|
22
|
+
}
|
|
23
|
+
),
|
|
24
|
+
logo
|
|
25
|
+
] }),
|
|
26
|
+
rightSection
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
function ErrorFallback({
|
|
30
|
+
title = "Something went wrong",
|
|
31
|
+
description = "We've been notified and are working on a fix.",
|
|
32
|
+
onAction,
|
|
33
|
+
actionLabel = "Reload Page",
|
|
34
|
+
error: error2
|
|
35
|
+
}) {
|
|
36
|
+
if (error2 !== void 0) {
|
|
37
|
+
console.error("[ErrorFallback]", error2);
|
|
38
|
+
}
|
|
39
|
+
const handleAction = onAction ?? (() => window.location.reload());
|
|
40
|
+
return /* @__PURE__ */ jsxRuntime.jsx(core.Container, { size: "sm", py: "xl", children: /* @__PURE__ */ jsxRuntime.jsxs(core.Stack, { align: "center", gap: "md", children: [
|
|
41
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Title, { order: 2, children: title }),
|
|
42
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { c: "dimmed", children: description }),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.Button, { onClick: handleAction, children: actionLabel })
|
|
44
|
+
] }) });
|
|
45
|
+
}
|
|
46
|
+
function FairmintLogo({
|
|
47
|
+
src = "https://imagedelivery.net/Lm6ChJXR4cIKKycsNMvGjA/0367be38-c9d8-4206-aaae-eba5ff830600/public",
|
|
48
|
+
width = 140,
|
|
49
|
+
height = 30,
|
|
50
|
+
className,
|
|
51
|
+
alt = "Fairmint"
|
|
52
|
+
}) {
|
|
53
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
54
|
+
"img",
|
|
55
|
+
{
|
|
56
|
+
src,
|
|
57
|
+
alt,
|
|
58
|
+
width,
|
|
59
|
+
height,
|
|
60
|
+
className,
|
|
61
|
+
style: { objectFit: "contain" }
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
5
65
|
const indigo = [
|
|
6
66
|
"#EEF2FF",
|
|
7
67
|
"#E0E7FF",
|
|
@@ -183,24 +243,8 @@ const semanticColors = {
|
|
|
183
243
|
error: "#F04438",
|
|
184
244
|
info: "#06AED4"
|
|
185
245
|
};
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
width = 140,
|
|
189
|
-
height = 30,
|
|
190
|
-
className,
|
|
191
|
-
alt = "Fairmint"
|
|
192
|
-
}) {
|
|
193
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
|
-
"img",
|
|
195
|
-
{
|
|
196
|
-
src,
|
|
197
|
-
alt,
|
|
198
|
-
width,
|
|
199
|
-
height,
|
|
200
|
-
className,
|
|
201
|
-
style: { objectFit: "contain" }
|
|
202
|
-
}
|
|
203
|
-
);
|
|
246
|
+
function FairmintProvider({ children, colorScheme = "light" }) {
|
|
247
|
+
return /* @__PURE__ */ jsxRuntime.jsx(core.MantineProvider, { theme, defaultColorScheme: colorScheme, children });
|
|
204
248
|
}
|
|
205
249
|
function LoadingSpinner({ size = 32 }) {
|
|
206
250
|
const iconProps = {
|
|
@@ -222,13 +266,23 @@ function LoadingSpinner({ size = 32 }) {
|
|
|
222
266
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 15h2" })
|
|
223
267
|
] });
|
|
224
268
|
return /* @__PURE__ */ jsxRuntime.jsxs(core.Box, { pos: "relative", style: { width: size, height: size }, role: "status", "aria-label": "Loading", children: [
|
|
225
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
270
|
+
"svg",
|
|
271
|
+
{
|
|
272
|
+
...iconProps,
|
|
273
|
+
stroke: "var(--mantine-color-gray-3)",
|
|
274
|
+
style: { position: "absolute", inset: 0 },
|
|
275
|
+
"aria-hidden": "true",
|
|
276
|
+
children: paths
|
|
277
|
+
}
|
|
278
|
+
),
|
|
226
279
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
227
280
|
"svg",
|
|
228
281
|
{
|
|
229
282
|
...iconProps,
|
|
230
283
|
stroke: "var(--mantine-color-indigo-5)",
|
|
231
284
|
style: { position: "absolute", inset: 0, animation: "fillUp 1.4s ease-in-out infinite" },
|
|
285
|
+
"aria-hidden": "true",
|
|
232
286
|
children: paths
|
|
233
287
|
}
|
|
234
288
|
)
|
|
@@ -243,47 +297,6 @@ function PageHeader({ title, subtitle, action }) {
|
|
|
243
297
|
action
|
|
244
298
|
] });
|
|
245
299
|
}
|
|
246
|
-
function ErrorFallback({
|
|
247
|
-
title = "Something went wrong",
|
|
248
|
-
description = "We've been notified and are working on a fix.",
|
|
249
|
-
onAction,
|
|
250
|
-
actionLabel = "Reload Page",
|
|
251
|
-
error: error2
|
|
252
|
-
}) {
|
|
253
|
-
if (error2 !== void 0) {
|
|
254
|
-
console.error("[ErrorFallback]", error2);
|
|
255
|
-
}
|
|
256
|
-
const handleAction = onAction ?? (() => window.location.reload());
|
|
257
|
-
return /* @__PURE__ */ jsxRuntime.jsx(core.Container, { size: "sm", py: "xl", children: /* @__PURE__ */ jsxRuntime.jsxs(core.Stack, { align: "center", gap: "md", children: [
|
|
258
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Title, { order: 2, children: title }),
|
|
259
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Text, { c: "dimmed", children: description }),
|
|
260
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.Button, { onClick: handleAction, children: actionLabel })
|
|
261
|
-
] }) });
|
|
262
|
-
}
|
|
263
|
-
function AppHeader({
|
|
264
|
-
logo,
|
|
265
|
-
rightSection,
|
|
266
|
-
mobileNavOpened = false,
|
|
267
|
-
onMobileNavToggle,
|
|
268
|
-
height = 60
|
|
269
|
-
}) {
|
|
270
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(core.Group, { h: height, px: "md", justify: "space-between", children: [
|
|
271
|
-
/* @__PURE__ */ jsxRuntime.jsxs(core.Group, { children: [
|
|
272
|
-
onMobileNavToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
273
|
-
core.Burger,
|
|
274
|
-
{
|
|
275
|
-
opened: mobileNavOpened,
|
|
276
|
-
onClick: onMobileNavToggle,
|
|
277
|
-
hiddenFrom: "sm",
|
|
278
|
-
size: "sm",
|
|
279
|
-
"aria-label": "Toggle navigation"
|
|
280
|
-
}
|
|
281
|
-
),
|
|
282
|
-
logo
|
|
283
|
-
] }),
|
|
284
|
-
rightSection
|
|
285
|
-
] });
|
|
286
|
-
}
|
|
287
300
|
function SideNav({ items, onItemClick, color = "indigo" }) {
|
|
288
301
|
return /* @__PURE__ */ jsxRuntime.jsx(core.Stack, { component: "nav", gap: 4, p: "md", "aria-label": "Main navigation", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
289
302
|
core.NavLink,
|
|
@@ -341,6 +354,7 @@ function UserMenu({
|
|
|
341
354
|
exports.AppHeader = AppHeader;
|
|
342
355
|
exports.ErrorFallback = ErrorFallback;
|
|
343
356
|
exports.FairmintLogo = FairmintLogo;
|
|
357
|
+
exports.FairmintProvider = FairmintProvider;
|
|
344
358
|
exports.LoadingSpinner = LoadingSpinner;
|
|
345
359
|
exports.PageHeader = PageHeader;
|
|
346
360
|
exports.SideNav = SideNav;
|
|
@@ -349,4 +363,4 @@ exports.brandColors = brandColors;
|
|
|
349
363
|
exports.neutralColors = neutralColors;
|
|
350
364
|
exports.semanticColors = semanticColors;
|
|
351
365
|
exports.theme = theme;
|
|
352
|
-
//# sourceMappingURL=fairmint-ui.cjs.
|
|
366
|
+
//# sourceMappingURL=fairmint-ui.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fairmint-ui.cjs","sources":["../src/components/AppHeader/AppHeader.tsx","../src/components/ErrorFallback/ErrorFallback.tsx","../src/components/FairmintLogo/FairmintLogo.tsx","../src/theme/index.ts","../src/components/FairmintProvider/FairmintProvider.tsx","../src/components/LoadingSpinner/LoadingSpinner.tsx","../src/components/PageHeader/PageHeader.tsx","../src/components/SideNav/SideNav.tsx","../src/components/UserMenu/UserMenu.tsx"],"sourcesContent":["import { Burger, Group } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\n\nexport interface AppHeaderProps {\n /** Logo element (typically FairmintLogo). */\n logo: ReactNode;\n /** Right-aligned content (user menu, actions). */\n rightSection?: ReactNode;\n /** Whether mobile nav is open. Controls burger state. */\n mobileNavOpened?: boolean;\n /** Toggle mobile nav callback. */\n onMobileNavToggle?: () => void;\n /** Header height in pixels. @default 60 */\n height?: number;\n}\n\nexport function AppHeader({\n logo,\n rightSection,\n mobileNavOpened = false,\n onMobileNavToggle,\n height = 60,\n}: AppHeaderProps) {\n return (\n <Group h={height} px=\"md\" justify=\"space-between\">\n <Group>\n {onMobileNavToggle && (\n <Burger\n opened={mobileNavOpened}\n onClick={onMobileNavToggle}\n hiddenFrom=\"sm\"\n size=\"sm\"\n aria-label=\"Toggle navigation\"\n />\n )}\n {logo}\n </Group>\n {rightSection}\n </Group>\n );\n}\n","import { Button, Container, Stack, Text, Title } from \"@mantine/core\";\n\nexport interface ErrorFallbackProps {\n /** Title text. @default \"Something went wrong\" */\n title?: string;\n /** Description text. @default \"We've been notified and are working on a fix.\" */\n description?: string;\n /** Callback when the user clicks the action button. Defaults to window.location.reload(). */\n onAction?: () => void;\n /** Action button label. @default \"Reload Page\" */\n actionLabel?: string;\n /** Optional error object for dev-mode display or logging. Compatible with Sentry ErrorBoundary render props. */\n error?: unknown;\n}\n\nexport function ErrorFallback({\n title = \"Something went wrong\",\n description = \"We've been notified and are working on a fix.\",\n onAction,\n actionLabel = \"Reload Page\",\n error,\n}: ErrorFallbackProps) {\n if (error !== undefined) {\n console.error(\"[ErrorFallback]\", error);\n }\n\n const handleAction = onAction ?? (() => window.location.reload());\n\n return (\n <Container size=\"sm\" py=\"xl\">\n <Stack align=\"center\" gap=\"md\">\n <Title order={2}>{title}</Title>\n <Text c=\"dimmed\">{description}</Text>\n <Button onClick={handleAction}>{actionLabel}</Button>\n </Stack>\n </Container>\n );\n}\n","export interface FairmintLogoProps {\n /** Image source URL. Defaults to the CDN-hosted black wordmark. */\n src?: string;\n /** Width in pixels. @default 140 */\n width?: number;\n /** Height in pixels. @default 30 */\n height?: number;\n /** Additional CSS class. */\n className?: string;\n /** Alt text. @default \"Fairmint\" */\n alt?: string;\n}\n\nexport function FairmintLogo({\n src = \"https://imagedelivery.net/Lm6ChJXR4cIKKycsNMvGjA/0367be38-c9d8-4206-aaae-eba5ff830600/public\",\n width = 140,\n height = 30,\n className,\n alt = \"Fairmint\",\n}: FairmintLogoProps) {\n return (\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n className={className}\n style={{ objectFit: \"contain\" }}\n />\n );\n}\n","import { createTheme, type MantineColorsTuple } from \"@mantine/core\";\n\n/**\n * Indigo palette — primary UI color.\n * Used for buttons, links, active navigation, focus rings.\n * Shade [5] (#6366F1) is the default primary.\n */\nconst indigo: MantineColorsTuple = [\n \"#EEF2FF\",\n \"#E0E7FF\",\n \"#C7D2FE\",\n \"#A5B4FC\",\n \"#818CF8\",\n \"#6366F1\",\n \"#4F46E5\",\n \"#4338CA\",\n \"#3730A3\",\n \"#312E81\",\n];\n\n/**\n * Neutral scale — replaces Mantine's default gray.\n * Used for text, borders, backgrounds, disabled states.\n */\nconst neutral: MantineColorsTuple = [\n \"#F8F9FA\",\n \"#F3F4F6\",\n \"#E5E7EB\",\n \"#D2D6DB\",\n \"#9DA4AE\",\n \"#6C737F\",\n \"#4D5761\",\n \"#2F3746\",\n \"#1C2536\",\n \"#111927\",\n];\n\n/**\n * Fairmint brand blue — accent color for gradients and brand elements.\n * Shade [5] (#0A4EFB) is the primary brand blue.\n *\n * NOTE: design/README.md lists #2D00F7 as Fairmint Blue.\n * This library uses #0A4EFB (production value from investorv2).\n */\nconst fairmintBlue: MantineColorsTuple = [\n \"#e6f0ff\",\n \"#cce0ff\",\n \"#99c2ff\",\n \"#66a3ff\",\n \"#3385ff\",\n \"#0A4EFB\",\n \"#083ec9\",\n \"#062e97\",\n \"#041f64\",\n \"#020f32\",\n];\n\n/**\n * Fairmint brand purple — accent color for gradients and brand elements.\n * Shade [5] (#9E03FF) is the primary brand purple.\n *\n * NOTE: design/README.md lists #6739FD as Fairmint Purple.\n * This library uses #9E03FF (production value from investorv2).\n */\nconst fairmintPurple: MantineColorsTuple = [\n \"#f5e6ff\",\n \"#e6ccff\",\n \"#cc99ff\",\n \"#b366ff\",\n \"#9933ff\",\n \"#9E03FF\",\n \"#7e02cc\",\n \"#5f0299\",\n \"#3f0166\",\n \"#200133\",\n];\n\nconst success: MantineColorsTuple = [\n \"#F0FDF9\",\n \"#D1FAE5\",\n \"#A7F3D0\",\n \"#6EE7B7\",\n \"#34D399\",\n \"#10B981\",\n \"#059669\",\n \"#047857\",\n \"#065F46\",\n \"#134E48\",\n];\n\nconst warning: MantineColorsTuple = [\n \"#FFFAEB\",\n \"#FEF0C7\",\n \"#FEDF89\",\n \"#FEC84B\",\n \"#FDB022\",\n \"#F79009\",\n \"#DC6803\",\n \"#B54708\",\n \"#93370D\",\n \"#7A2E0E\",\n];\n\nconst error: MantineColorsTuple = [\n \"#FEF3F2\",\n \"#FEE4E2\",\n \"#FECDCA\",\n \"#FDA29B\",\n \"#F97066\",\n \"#F04438\",\n \"#D92D20\",\n \"#B42318\",\n \"#912018\",\n \"#7A271A\",\n];\n\nconst info: MantineColorsTuple = [\n \"#ECFDFF\",\n \"#CFF9FE\",\n \"#A5F0FC\",\n \"#67E3F9\",\n \"#22CCEE\",\n \"#06AED4\",\n \"#088AB2\",\n \"#0E7090\",\n \"#155B75\",\n \"#164C63\",\n];\n\nexport const theme = createTheme({\n primaryColor: \"indigo\",\n colors: { indigo, gray: neutral, fairmintBlue, fairmintPurple, success, warning, error, info },\n\n fontFamily:\n '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n headings: {\n fontFamily: '\"Plus Jakarta Sans\", sans-serif',\n fontWeight: \"700\",\n },\n\n radius: {\n xs: \"0.25rem\",\n sm: \"0.375rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n },\n defaultRadius: \"md\",\n\n breakpoints: {\n xs: \"30em\",\n sm: \"48em\",\n md: \"64em\",\n lg: \"74em\",\n xl: \"90em\",\n },\n\n components: {\n Button: {\n defaultProps: { size: \"md\" },\n styles: {\n root: {\n fontWeight: 600,\n borderRadius: \"0.75rem\",\n textTransform: \"none\" as const,\n },\n },\n },\n TextInput: {\n defaultProps: { size: \"md\" },\n },\n Card: {\n defaultProps: {\n padding: \"lg\",\n radius: \"xl\",\n withBorder: true,\n },\n },\n Paper: {\n styles: {\n root: { backgroundImage: \"none\" },\n },\n },\n Table: {\n styles: {\n thead: {\n fontSize: \"0.75rem\",\n fontWeight: 600,\n letterSpacing: \"0.5px\",\n textTransform: \"uppercase\" as const,\n },\n },\n },\n },\n});\n\n/** Brand colors for gradients and custom styling. */\nexport const brandColors = {\n blue: \"#0A4EFB\",\n purple: \"#9E03FF\",\n indigo: \"#6366F1\",\n gradient: \"linear-gradient(90deg, #0A4EFB 0%, #9E03FF 100%)\",\n} as const;\n\n/** Neutral scale for direct access outside Mantine's theme system. Keys are numeric literals. */\nexport const neutralColors = {\n 50: \"#F8F9FA\",\n 100: \"#F3F4F6\",\n 200: \"#E5E7EB\",\n 300: \"#D2D6DB\",\n 400: \"#9DA4AE\",\n 500: \"#6C737F\",\n 600: \"#4D5761\",\n 700: \"#2F3746\",\n 800: \"#1C2536\",\n 900: \"#111927\",\n} as const;\n\n/** Semantic colors for status-based styling. */\nexport const semanticColors = {\n success: \"#10B981\",\n warning: \"#F79009\",\n error: \"#F04438\",\n info: \"#06AED4\",\n} as const;\n","import type { MantineColorScheme } from \"@mantine/core\";\nimport { MantineProvider } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\nimport { theme } from \"../../theme\";\n\nexport interface FairmintProviderProps {\n children: ReactNode;\n /** Color scheme. @default \"light\" */\n colorScheme?: MantineColorScheme;\n}\n\nexport function FairmintProvider({ children, colorScheme = \"light\" }: FairmintProviderProps) {\n if (import.meta.env?.DEV) {\n validateSetup();\n }\n\n return (\n <MantineProvider theme={theme} defaultColorScheme={colorScheme}>\n {children}\n </MantineProvider>\n );\n}\n\nfunction validateSetup() {\n if (typeof window === \"undefined\") return;\n\n requestIdleCallback(() => {\n const root = document.documentElement;\n const mantineCss = getComputedStyle(root).getPropertyValue(\"--mantine-color-scheme\");\n if (!mantineCss) {\n console.warn(\n '[@fairmint/ui] Mantine CSS not detected. Make sure you import \"@fairmint/ui/styles.css\" in your entry file.',\n );\n }\n });\n}\n","import { Box } from \"@mantine/core\";\n\nexport interface LoadingSpinnerProps {\n /** Icon size in pixels. @default 32 */\n size?: number;\n}\n\n/**\n * Animated certificate icon that fills from bottom to top.\n * Requires the consumer to import `@fairmint/ui/styles.css` for the keyframe animation.\n */\nexport function LoadingSpinner({ size = 32 }: LoadingSpinnerProps) {\n const iconProps = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: size,\n height: size,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n strokeWidth: 1.5,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n };\n\n const paths = (\n <>\n <path d=\"M15 15m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0\" />\n <path d=\"M13 17.5v4.5l2 -1.5l2 1.5v-4.5\" />\n <path d=\"M10 19h-5a2 2 0 0 1 -2 -2v-10c0 -1.1 .9 -2 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-1\" />\n <path d=\"M6 9h12\" />\n <path d=\"M6 12h3\" />\n <path d=\"M6 15h2\" />\n </>\n );\n\n return (\n <Box pos=\"relative\" style={{ width: size, height: size }} role=\"status\" aria-label=\"Loading\">\n <svg\n {...iconProps}\n stroke=\"var(--mantine-color-gray-3)\"\n style={{ position: \"absolute\", inset: 0 }}\n aria-hidden=\"true\"\n >\n {paths}\n </svg>\n <svg\n {...iconProps}\n stroke=\"var(--mantine-color-indigo-5)\"\n style={{ position: \"absolute\", inset: 0, animation: \"fillUp 1.4s ease-in-out infinite\" }}\n aria-hidden=\"true\"\n >\n {paths}\n </svg>\n </Box>\n );\n}\n","import { Group, Stack, Text, Title } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\n\nexport interface PageHeaderProps {\n /** Page title text. */\n title: string;\n /** Optional subtitle text. */\n subtitle?: string;\n /** Optional right-aligned action element (button, date picker, etc.). */\n action?: ReactNode;\n}\n\nexport function PageHeader({ title, subtitle, action }: PageHeaderProps) {\n return (\n <Group justify=\"space-between\" align=\"flex-start\" mb=\"lg\">\n <Stack gap={4}>\n <Title order={2}>{title}</Title>\n {subtitle && (\n <Text c=\"dimmed\" size=\"sm\">\n {subtitle}\n </Text>\n )}\n </Stack>\n {action}\n </Group>\n );\n}\n","import { NavLink, Stack } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\n\nexport interface SideNavItem {\n /** Unique identifier for this nav item (e.g., route path or slug). */\n id: string;\n /** Display label. */\n label: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Whether this item is currently active. */\n active?: boolean;\n}\n\nexport interface SideNavProps {\n /** Navigation items to render. */\n items: SideNavItem[];\n /** Callback when a nav item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n /** Active color. @default \"indigo\" */\n color?: string;\n}\n\nexport function SideNav({ items, onItemClick, color = \"indigo\" }: SideNavProps) {\n return (\n <Stack component=\"nav\" gap={4} p=\"md\" aria-label=\"Main navigation\">\n {items.map((item) => (\n <NavLink\n key={item.id}\n label={item.label}\n leftSection={item.icon}\n active={item.active}\n onClick={() => onItemClick(item.id)}\n color={color}\n variant=\"light\"\n style={{ borderRadius: \"var(--mantine-radius-md)\" }}\n styles={{\n root: {\n color: item.active ? undefined : \"var(--mantine-color-gray-5)\",\n fontWeight: item.active ? 500 : 400,\n },\n section: {\n color: item.active ? undefined : \"var(--mantine-color-gray-4)\",\n },\n }}\n />\n ))}\n </Stack>\n );\n}\n","import { Avatar, Box, Divider, Group, Menu, Text, UnstyledButton } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\n\nexport interface UserMenuItem {\n /** Unique identifier for this menu item. */\n id: string;\n /** Display label. */\n label: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Item color (e.g., \"red\" for destructive actions). */\n color?: string;\n /** Optional section label above this item. Set on the first item in a group. */\n sectionLabel?: string;\n /** Show a divider before this item. */\n dividerBefore?: boolean;\n}\n\nexport interface UserMenuProps {\n /** User display name or email. */\n displayName: string;\n /** Single-character avatar initial. Derived from displayName[0] if not provided. */\n avatarInitial?: string;\n /** Avatar color. @default \"indigo\" */\n avatarColor?: string;\n /** Optional indicator element after the display name (e.g., chevron icon from your app's icon library). */\n indicator?: ReactNode;\n /** Menu items. */\n items: UserMenuItem[];\n /** Callback when a menu item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n}\n\nexport function UserMenu({\n displayName,\n avatarInitial,\n avatarColor = \"indigo\",\n indicator,\n items,\n onItemClick,\n}: UserMenuProps) {\n const initial = avatarInitial ?? displayName.charAt(0).toUpperCase();\n\n return (\n <Menu shadow=\"md\" width={200} position=\"bottom-end\">\n <Menu.Target>\n <UnstyledButton aria-label=\"User menu\">\n <Group gap=\"xs\">\n <Avatar size=\"sm\" radius=\"xl\" color={avatarColor}>\n {initial}\n </Avatar>\n <Box visibleFrom=\"sm\">\n <Text size=\"sm\" fw={500} lineClamp={1} style={{ maxWidth: 150 }}>\n {displayName}\n </Text>\n </Box>\n {indicator}\n </Group>\n </UnstyledButton>\n </Menu.Target>\n\n <Menu.Dropdown>\n {items.map((item) => (\n <div key={item.id}>\n {item.dividerBefore && <Divider my=\"xs\" />}\n {item.sectionLabel && <Menu.Label>{item.sectionLabel}</Menu.Label>}\n <Menu.Item\n leftSection={item.icon}\n color={item.color}\n onClick={() => onItemClick(item.id)}\n >\n {item.label}\n </Menu.Item>\n </div>\n ))}\n </Menu.Dropdown>\n </Menu>\n );\n}\n"],"names":["Group","jsxs","jsx","Burger","error","Container","Stack","Title","Text","Button","createTheme","MantineProvider","Fragment","Box","NavLink","Menu","UnstyledButton","Avatar","Divider"],"mappings":"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"}
|