@ima-jin/ui 1.0.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 +36 -0
- package/dist/index.js +1937 -0
- package/dist/index.mjs +1891 -0
- package/package.json +26 -0
- package/src/BuildInfo.tsx +20 -0
- package/src/DidShareListEditor.tsx +433 -0
- package/src/MarkdownContent.tsx +70 -0
- package/src/MarkdownEditor.tsx +79 -0
- package/src/MoneyInput.tsx +103 -0
- package/src/PayoutSetupBanner.tsx +117 -0
- package/src/acting-as.ts +21 -0
- package/src/action-sheet.tsx +118 -0
- package/src/app-launcher.tsx +298 -0
- package/src/app-shell.tsx +154 -0
- package/src/balance-badge.tsx +106 -0
- package/src/brand.ts +26 -0
- package/src/button.tsx +14 -0
- package/src/connection-picker.tsx +106 -0
- package/src/footer.tsx +39 -0
- package/src/index.ts +44 -0
- package/src/nav-bar.tsx +611 -0
- package/src/notification-bell.tsx +144 -0
- package/src/notification-provider.tsx +134 -0
- package/src/theme-init.ts +10 -0
- package/src/toast.tsx +147 -0
- package/src/use-identities.ts +69 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AppShell — viewport-clamped layout primitive
|
|
5
|
+
*
|
|
6
|
+
* Clamp contract:
|
|
7
|
+
* - Header / Footer: shrink-0 (they stay pinned, never squish)
|
|
8
|
+
* - Body: flex-1 min-h-0 overflow-auto (fills remaining space, scrolls)
|
|
9
|
+
*
|
|
10
|
+
* This prevents headers (e.g. nav + search bar) from pushing content off-screen
|
|
11
|
+
* on small viewports. Each pane in a Split should repeat the same Header/Body/Footer
|
|
12
|
+
* pattern for per-pane clamping.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/* ------------------------------------------------------------------ */
|
|
16
|
+
/* AppShell root */
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
|
|
19
|
+
export interface AppShellProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const AppShell = React.forwardRef<HTMLDivElement, AppShellProps>(
|
|
24
|
+
function AppShell({ className = '', children, ...props }, ref) {
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={`h-dvh flex flex-col overflow-hidden ${className}`}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/* ------------------------------------------------------------------ */
|
|
38
|
+
/* Header */
|
|
39
|
+
/* ------------------------------------------------------------------ */
|
|
40
|
+
|
|
41
|
+
export interface AppShellHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
42
|
+
children?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const AppShellHeader = React.forwardRef<HTMLDivElement, AppShellHeaderProps>(
|
|
46
|
+
function AppShellHeader({ className = '', children, ...props }, ref) {
|
|
47
|
+
return (
|
|
48
|
+
<div ref={ref} className={`shrink-0 ${className}`} {...props}>
|
|
49
|
+
{children}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
/* ------------------------------------------------------------------ */
|
|
56
|
+
/* Body (scrollable content area) */
|
|
57
|
+
/* ------------------------------------------------------------------ */
|
|
58
|
+
|
|
59
|
+
export interface AppShellBodyProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
60
|
+
children?: React.ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const AppShellBody = React.forwardRef<HTMLDivElement, AppShellBodyProps>(
|
|
64
|
+
function AppShellBody({ className = '', children, ...props }, ref) {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={`flex-1 min-h-0 overflow-auto ${className}`}
|
|
69
|
+
{...props}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
/* ------------------------------------------------------------------ */
|
|
78
|
+
/* Footer */
|
|
79
|
+
/* ------------------------------------------------------------------ */
|
|
80
|
+
|
|
81
|
+
export interface AppShellFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
82
|
+
children?: React.ReactNode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const AppShellFooter = React.forwardRef<HTMLDivElement, AppShellFooterProps>(
|
|
86
|
+
function AppShellFooter({ className = '', children, ...props }, ref) {
|
|
87
|
+
return (
|
|
88
|
+
<div ref={ref} className={`shrink-0 ${className}`} {...props}>
|
|
89
|
+
{children}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/* ------------------------------------------------------------------ */
|
|
96
|
+
/* Split (horizontal panes) */
|
|
97
|
+
/* ------------------------------------------------------------------ */
|
|
98
|
+
|
|
99
|
+
export interface AppShellSplitProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
100
|
+
children?: React.ReactNode;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const AppShellSplit = React.forwardRef<HTMLDivElement, AppShellSplitProps>(
|
|
104
|
+
function AppShellSplit({ className = '', children, ...props }, ref) {
|
|
105
|
+
return (
|
|
106
|
+
<div
|
|
107
|
+
ref={ref}
|
|
108
|
+
className={`flex-1 min-h-0 flex flex-row overflow-hidden ${className}`}
|
|
109
|
+
{...props}
|
|
110
|
+
>
|
|
111
|
+
{children}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
/* ------------------------------------------------------------------ */
|
|
118
|
+
/* Split.Pane */
|
|
119
|
+
/* ------------------------------------------------------------------ */
|
|
120
|
+
|
|
121
|
+
export interface AppShellPaneProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
122
|
+
width?: string | number;
|
|
123
|
+
children?: React.ReactNode;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const AppShellPane = React.forwardRef<HTMLDivElement, AppShellPaneProps>(
|
|
127
|
+
function AppShellPane({ width, className = '', style, children, ...props }, ref) {
|
|
128
|
+
const widthStyle = width != null ? { width, ...style } : style;
|
|
129
|
+
return (
|
|
130
|
+
<div
|
|
131
|
+
ref={ref}
|
|
132
|
+
className={`flex flex-col min-h-0 overflow-hidden ${className}`}
|
|
133
|
+
style={widthStyle}
|
|
134
|
+
{...props}
|
|
135
|
+
>
|
|
136
|
+
{children}
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
AppShell.displayName = 'AppShell';
|
|
143
|
+
AppShellHeader.displayName = 'AppShell.Header';
|
|
144
|
+
AppShellBody.displayName = 'AppShell.Body';
|
|
145
|
+
AppShellFooter.displayName = 'AppShell.Footer';
|
|
146
|
+
AppShellSplit.displayName = 'AppShell.Split';
|
|
147
|
+
AppShellPane.displayName = 'AppShell.Split.Pane';
|
|
148
|
+
|
|
149
|
+
/* Attach subcomponents as static properties for compound API */
|
|
150
|
+
(AppShell as unknown as Record<string, unknown>).Header = AppShellHeader;
|
|
151
|
+
(AppShell as unknown as Record<string, unknown>).Body = AppShellBody;
|
|
152
|
+
(AppShell as unknown as Record<string, unknown>).Footer = AppShellFooter;
|
|
153
|
+
(AppShell as unknown as Record<string, unknown>).Split = AppShellSplit;
|
|
154
|
+
AppShellSplit.Pane = AppShellPane;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { useState, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
export interface BalanceBadgeProps {
|
|
6
|
+
/** DID of the user whose balance to show */
|
|
7
|
+
did?: string | null;
|
|
8
|
+
/** Pay service URL (e.g., https://pay.imajin.ai) */
|
|
9
|
+
payUrl: string;
|
|
10
|
+
/** Auth token for API requests */
|
|
11
|
+
authToken?: string | null;
|
|
12
|
+
/** Custom className for styling */
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface BalanceData {
|
|
17
|
+
did: string;
|
|
18
|
+
amount: number;
|
|
19
|
+
currency: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Balance Badge Component
|
|
25
|
+
*
|
|
26
|
+
* Displays user's balance from the pay service.
|
|
27
|
+
* - Only shows if user is logged in (has DID and token)
|
|
28
|
+
* - Only shows if balance > 0
|
|
29
|
+
* - Fetches balance from pay service
|
|
30
|
+
*/
|
|
31
|
+
export function BalanceBadge({ did, payUrl, authToken, className = '' }: BalanceBadgeProps) {
|
|
32
|
+
const [balance, setBalance] = useState<BalanceData | null>(null);
|
|
33
|
+
const [loading, setLoading] = useState(false);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!did || !authToken) {
|
|
37
|
+
setBalance(null);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let cancelled = false;
|
|
42
|
+
|
|
43
|
+
async function fetchBalance() {
|
|
44
|
+
setLoading(true);
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${payUrl}/api/balance/${did}`, {
|
|
47
|
+
headers: {
|
|
48
|
+
'Authorization': `Bearer ${authToken}`,
|
|
49
|
+
},
|
|
50
|
+
credentials: 'include',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (res.ok) {
|
|
54
|
+
const data = await res.json();
|
|
55
|
+
if (!cancelled) {
|
|
56
|
+
setBalance(data);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
if (!cancelled) {
|
|
60
|
+
setBalance(null);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('Failed to fetch balance:', error);
|
|
65
|
+
if (!cancelled) {
|
|
66
|
+
setBalance(null);
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
if (!cancelled) {
|
|
70
|
+
setLoading(false);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fetchBalance();
|
|
76
|
+
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
};
|
|
80
|
+
}, [did, authToken, payUrl]);
|
|
81
|
+
|
|
82
|
+
// Don't show if not logged in
|
|
83
|
+
if (!did || !authToken) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Don't show while loading
|
|
88
|
+
if (loading) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Don't show if balance is 0 or null
|
|
93
|
+
if (!balance || balance.amount <= 0) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div
|
|
99
|
+
className={`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-gradient-to-r from-orange-500/10 to-amber-500/10 border border-orange-500/20 ${className}`}
|
|
100
|
+
>
|
|
101
|
+
<span className="text-sm font-medium text-green-600 dark:text-green-400">
|
|
102
|
+
${balance.amount.toFixed(2)}
|
|
103
|
+
</span>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
package/src/brand.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imajin brand constants
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for taglines, copy, and brand text.
|
|
5
|
+
* Import from @imajin/ui in any app.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const BRAND = {
|
|
9
|
+
name: 'Imajin',
|
|
10
|
+
nameJp: '今人',
|
|
11
|
+
pronunciation: 'eema-gin',
|
|
12
|
+
|
|
13
|
+
/** Primary tagline — used on homepage hero */
|
|
14
|
+
tagline: 'The internet that pays you back',
|
|
15
|
+
|
|
16
|
+
/** Footer line — used across all services */
|
|
17
|
+
footer: 'Part of the Imajin sovereign network',
|
|
18
|
+
|
|
19
|
+
/** Short sovereign message — used in emails, receipts */
|
|
20
|
+
sovereign: 'No platform. No middleman. Yours.',
|
|
21
|
+
|
|
22
|
+
/** Links */
|
|
23
|
+
url: 'https://imajin.ai',
|
|
24
|
+
community: 'https://app.dfos.com/j/c3rff6e96e4ca9hncc43en',
|
|
25
|
+
github: 'https://github.com/ima-jin/imajin-ai',
|
|
26
|
+
} as const;
|
package/src/button.tsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
variant?: 'primary' | 'secondary';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function Button({ variant = 'primary', className = '', ...props }: ButtonProps) {
|
|
8
|
+
const base = 'px-4 py-2 rounded font-medium transition-colors';
|
|
9
|
+
const variants = {
|
|
10
|
+
primary: 'bg-orange-500 text-white hover:bg-orange-600',
|
|
11
|
+
secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
|
|
12
|
+
};
|
|
13
|
+
return <button className={`${base} ${variants[variant]} ${className}`} {...props} />;
|
|
14
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
interface Connection {
|
|
6
|
+
did: string;
|
|
7
|
+
name: string | null;
|
|
8
|
+
handle: string | null;
|
|
9
|
+
avatar: string | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ConnectionPickerProps {
|
|
13
|
+
connectionsUrl: string;
|
|
14
|
+
excludeDids?: string[];
|
|
15
|
+
onSelect: (connection: Connection) => void;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ConnectionPicker({
|
|
21
|
+
connectionsUrl,
|
|
22
|
+
excludeDids = [],
|
|
23
|
+
onSelect,
|
|
24
|
+
placeholder = 'Search connections...',
|
|
25
|
+
disabled = false,
|
|
26
|
+
}: ConnectionPickerProps) {
|
|
27
|
+
const [connections, setConnections] = useState<Connection[]>([]);
|
|
28
|
+
const [loading, setLoading] = useState(true);
|
|
29
|
+
const [error, setError] = useState<string | null>(null);
|
|
30
|
+
const [search, setSearch] = useState('');
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
fetch(connectionsUrl)
|
|
34
|
+
.then(r => r.json())
|
|
35
|
+
.then(data => {
|
|
36
|
+
setConnections(data.connections || []);
|
|
37
|
+
setLoading(false);
|
|
38
|
+
})
|
|
39
|
+
.catch(() => {
|
|
40
|
+
setError('Failed to load connections');
|
|
41
|
+
setLoading(false);
|
|
42
|
+
});
|
|
43
|
+
}, [connectionsUrl]);
|
|
44
|
+
|
|
45
|
+
const excludeSet = new Set(excludeDids);
|
|
46
|
+
const available = connections.filter(c => !excludeSet.has(c.did));
|
|
47
|
+
const filtered = search
|
|
48
|
+
? available.filter(c =>
|
|
49
|
+
(c.handle || '').toLowerCase().includes(search.toLowerCase()) ||
|
|
50
|
+
(c.name || '').toLowerCase().includes(search.toLowerCase())
|
|
51
|
+
)
|
|
52
|
+
: available;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div className="space-y-2">
|
|
56
|
+
<input
|
|
57
|
+
type="text"
|
|
58
|
+
value={search}
|
|
59
|
+
onChange={e => setSearch(e.target.value)}
|
|
60
|
+
placeholder={placeholder}
|
|
61
|
+
disabled={disabled || loading}
|
|
62
|
+
className="w-full px-3 py-2 text-sm border border-gray-600 rounded-lg bg-gray-900 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-orange-500 disabled:opacity-50"
|
|
63
|
+
/>
|
|
64
|
+
{loading ? (
|
|
65
|
+
<p className="text-sm text-gray-500 px-1">Loading connections...</p>
|
|
66
|
+
) : error ? (
|
|
67
|
+
<p className="text-sm text-red-400 px-1">{error}</p>
|
|
68
|
+
) : filtered.length === 0 ? (
|
|
69
|
+
<p className="text-sm text-gray-500 px-1">
|
|
70
|
+
{available.length === 0 ? 'No connections available.' : 'No matching connections.'}
|
|
71
|
+
</p>
|
|
72
|
+
) : (
|
|
73
|
+
<div className="space-y-0 max-h-48 overflow-y-auto rounded-lg border border-gray-700 bg-gray-900">
|
|
74
|
+
{filtered.map(conn => (
|
|
75
|
+
<button
|
|
76
|
+
key={conn.did}
|
|
77
|
+
onClick={() => { onSelect(conn); setSearch(''); }}
|
|
78
|
+
disabled={disabled}
|
|
79
|
+
className="w-full flex items-center gap-3 px-3 py-2 hover:bg-gray-800 transition text-left disabled:opacity-50"
|
|
80
|
+
>
|
|
81
|
+
{conn.avatar ? (
|
|
82
|
+
<img
|
|
83
|
+
src={conn.avatar}
|
|
84
|
+
alt={conn.name || conn.handle || conn.did}
|
|
85
|
+
className="w-8 h-8 rounded-full object-cover flex-shrink-0"
|
|
86
|
+
/>
|
|
87
|
+
) : (
|
|
88
|
+
<div className="w-8 h-8 rounded-full bg-gray-700 flex items-center justify-center text-gray-400 text-sm font-semibold flex-shrink-0">
|
|
89
|
+
{(conn.name || conn.handle || conn.did).charAt(0).toUpperCase()}
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
<div className="min-w-0">
|
|
93
|
+
<div className="text-sm font-medium text-white truncate">
|
|
94
|
+
{conn.name || (conn.handle ? `@${conn.handle}` : conn.did.slice(0, 20) + '...')}
|
|
95
|
+
</div>
|
|
96
|
+
{conn.handle && conn.name && (
|
|
97
|
+
<div className="text-xs text-gray-400 truncate">@{conn.handle}</div>
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
</button>
|
|
101
|
+
))}
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
package/src/footer.tsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { BuildInfo } from './BuildInfo';
|
|
5
|
+
|
|
6
|
+
function getServiceFromPathname(pathname: string): string {
|
|
7
|
+
const segment = pathname.split('/').filter(Boolean)[0];
|
|
8
|
+
if (!segment) return 'landing';
|
|
9
|
+
return segment;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ImajinFooter({ className }: { className?: string }) {
|
|
13
|
+
const [subscribeHref, setSubscribeHref] = useState('/subscribe');
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const service = getServiceFromPathname(window.location.pathname);
|
|
17
|
+
setSubscribeHref(`/subscribe?from=${service}`);
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className={`flex flex-col items-center gap-2 ${className || ""}`}>
|
|
22
|
+
<p className="text-center text-sm text-gray-500">
|
|
23
|
+
Part of the{" "}
|
|
24
|
+
<a href="https://imajin.ai" className="text-orange-500 hover:underline">Imajin</a>
|
|
25
|
+
{" "}sovereign network
|
|
26
|
+
</p>
|
|
27
|
+
<p className="text-center text-sm text-gray-500">
|
|
28
|
+
<a href="https://app.dfos.com/j/c3rff6e96e4ca9hncc43en" className="hover:underline">Community</a>
|
|
29
|
+
{" · "}
|
|
30
|
+
<a href="https://github.com/ima-jin/imajin-ai" className="hover:underline">GitHub</a>
|
|
31
|
+
{" · "}
|
|
32
|
+
<a href="/privacy" className="hover:underline">Privacy</a>
|
|
33
|
+
{" · "}
|
|
34
|
+
<a href={subscribeHref} className="hover:underline">Subscribe</a>
|
|
35
|
+
</p>
|
|
36
|
+
<BuildInfo />
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export { NavBar } from './nav-bar';
|
|
2
|
+
export type { NavBarProps, NavIdentity, ServiceUrls } from './nav-bar';
|
|
3
|
+
export { AppLauncher } from './app-launcher';
|
|
4
|
+
export type { AppLauncherProps, LauncherService } from './app-launcher';
|
|
5
|
+
export { Button } from './button';
|
|
6
|
+
export { BalanceBadge } from './balance-badge';
|
|
7
|
+
export type { BalanceBadgeProps } from './balance-badge';
|
|
8
|
+
export { ImajinFooter } from './footer';
|
|
9
|
+
export { BuildInfo } from './BuildInfo';
|
|
10
|
+
export { BRAND } from './brand';
|
|
11
|
+
export { MarkdownEditor } from './MarkdownEditor';
|
|
12
|
+
export type { MarkdownEditorProps } from './MarkdownEditor';
|
|
13
|
+
export { MarkdownContent } from './MarkdownContent';
|
|
14
|
+
export type { MarkdownContentProps } from './MarkdownContent';
|
|
15
|
+
export { ConnectionPicker } from './connection-picker';
|
|
16
|
+
export type { ConnectionPickerProps } from './connection-picker';
|
|
17
|
+
|
|
18
|
+
export { PayoutSetupBanner } from './PayoutSetupBanner';
|
|
19
|
+
|
|
20
|
+
export { ToastProvider, useToast } from './toast';
|
|
21
|
+
export type { ToastType } from './toast';
|
|
22
|
+
|
|
23
|
+
export { NotificationProvider, useNotifications } from './notification-provider';
|
|
24
|
+
export type { Notification, NotificationContextValue } from './notification-provider';
|
|
25
|
+
export { NotificationBell } from './notification-bell';
|
|
26
|
+
|
|
27
|
+
export { ActionSheet } from './action-sheet';
|
|
28
|
+
export { AppShell } from './app-shell';
|
|
29
|
+
export { DidShareListEditor } from './DidShareListEditor';
|
|
30
|
+
export { MoneyInput } from './MoneyInput';
|
|
31
|
+
export type {
|
|
32
|
+
AppShellProps,
|
|
33
|
+
AppShellHeaderProps,
|
|
34
|
+
AppShellBodyProps,
|
|
35
|
+
AppShellFooterProps,
|
|
36
|
+
AppShellSplitProps,
|
|
37
|
+
AppShellPaneProps,
|
|
38
|
+
} from './app-shell';
|
|
39
|
+
|
|
40
|
+
export { themeInitScript } from './theme-init';
|
|
41
|
+
|
|
42
|
+
export { getActingAs, setActingAs, getActingAsHeaders } from './acting-as';
|
|
43
|
+
export { useIdentities } from './use-identities';
|
|
44
|
+
export type { GroupIdentity } from './use-identities';
|