@pollinations/ui 0.0.2 → 0.1.0-alpha.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 +38 -71
- package/dist/{Chip-SM52sUbZ.d.cts → Chip-CQCq34kS.d.cts} +1 -1
- package/dist/{Chip-C5impfYd.d.ts → Chip-Cj4xG7Te.d.ts} +1 -1
- package/dist/app-user-menu/sdk.cjs +497 -0
- package/dist/app-user-menu/sdk.cjs.map +1 -0
- package/dist/app-user-menu/sdk.d.cts +18 -0
- package/dist/app-user-menu/sdk.d.ts +18 -0
- package/dist/app-user-menu/sdk.js +469 -0
- package/dist/app-user-menu/sdk.js.map +1 -0
- package/dist/app.css +94 -3
- package/dist/auth/index.cjs +77 -62
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.js +77 -62
- package/dist/auth/index.js.map +1 -1
- package/dist/gen/index.cjs +477 -0
- package/dist/gen/index.cjs.map +1 -0
- package/dist/gen/index.d.cts +35 -0
- package/dist/gen/index.d.ts +35 -0
- package/dist/gen/index.js +451 -0
- package/dist/gen/index.js.map +1 -0
- package/dist/index.cjs +1875 -761
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -109
- package/dist/index.d.ts +294 -109
- package/dist/index.js +1889 -798
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme-jRPPBmld.d.cts +20 -0
- package/dist/theme-jRPPBmld.d.ts +20 -0
- package/dist/wallet/index.cjs +17 -8
- package/dist/wallet/index.cjs.map +1 -1
- package/dist/wallet/index.d.cts +2 -2
- package/dist/wallet/index.d.ts +2 -2
- package/dist/wallet/index.js +17 -8
- package/dist/wallet/index.js.map +1 -1
- package/package.json +15 -18
- package/dist/Button-Bn8pGg6N.d.ts +0 -26
- package/dist/Button-CWUBCiIc.d.cts +0 -26
- package/dist/auth/sdk.cjs +0 -220
- package/dist/auth/sdk.cjs.map +0 -1
- package/dist/auth/sdk.d.cts +0 -53
- package/dist/auth/sdk.d.ts +0 -53
- package/dist/auth/sdk.js +0 -187
- package/dist/auth/sdk.js.map +0 -1
- package/dist/modality/index.cjs +0 -83
- package/dist/modality/index.cjs.map +0 -1
- package/dist/modality/index.d.cts +0 -25
- package/dist/modality/index.d.ts +0 -25
- package/dist/modality/index.js +0 -56
- package/dist/modality/index.js.map +0 -1
- package/dist/theme-VMRlhqST.d.cts +0 -9
- package/dist/theme-VMRlhqST.d.ts +0 -9
- package/dist/wallet/sdk.cjs +0 -206
- package/dist/wallet/sdk.cjs.map +0 -1
- package/dist/wallet/sdk.d.cts +0 -33
- package/dist/wallet/sdk.d.ts +0 -33
- package/dist/wallet/sdk.js +0 -175
- package/dist/wallet/sdk.js.map +0 -1
- package/dist/wallet.css +0 -73
package/README.md
CHANGED
|
@@ -1,65 +1,39 @@
|
|
|
1
1
|
# @pollinations/ui
|
|
2
2
|
|
|
3
|
-
Internal UI primitives for Pollinations apps.
|
|
4
|
-
state from
|
|
5
|
-
core
|
|
3
|
+
Internal UI primitives, compositions, and modules for Pollinations apps.
|
|
4
|
+
SDK-backed subpaths consume auth state from
|
|
5
|
+
[`@pollinations/sdk/react`](../sdk/README.md#react-auth-provider); core
|
|
6
|
+
primitives and display recipes stay SDK-free.
|
|
6
7
|
|
|
7
8
|
## Install
|
|
8
9
|
|
|
10
|
+
> [!WARNING]
|
|
11
|
+
> **The `alpha` line (`0.1.0-alpha.x`) is unstable and breakage-prone.** It ships the in-progress design-system rebuild (new `--polli-color-*` token system, new primitives, renamed size props `sm|md|lg`) and its API may change between alpha versions without notice. The stable `latest` line is `0.0.2`. Opt into the alpha deliberately, and pin an exact version.
|
|
12
|
+
|
|
9
13
|
```bash
|
|
14
|
+
# stable (recommended)
|
|
10
15
|
npm install @pollinations/ui
|
|
16
|
+
|
|
17
|
+
# alpha (in-progress rebuild — pin exactly)
|
|
18
|
+
npm install @pollinations/ui@alpha
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
Install `@pollinations/sdk` too when using
|
|
14
|
-
|
|
21
|
+
Install `@pollinations/sdk` too when using the
|
|
22
|
+
`@pollinations/ui/app-user-menu/sdk` subpath.
|
|
15
23
|
|
|
16
24
|
## Usage
|
|
17
25
|
|
|
18
26
|
```tsx
|
|
19
27
|
import "@pollinations/ui/styles.css";
|
|
20
|
-
import { PolliProvider
|
|
28
|
+
import { PolliProvider } from "@pollinations/sdk/react";
|
|
21
29
|
import { Surface } from "@pollinations/ui";
|
|
22
|
-
import {
|
|
23
|
-
LoginButton,
|
|
24
|
-
LogoutButton,
|
|
25
|
-
UserAvatar,
|
|
26
|
-
UserName,
|
|
27
|
-
WhenLoggedIn,
|
|
28
|
-
WhenLoggedOut,
|
|
29
|
-
} from "@pollinations/ui/auth/sdk";
|
|
30
|
-
import {
|
|
31
|
-
Balance,
|
|
32
|
-
KeyBudget,
|
|
33
|
-
KeyExpiry,
|
|
34
|
-
KeyModels,
|
|
35
|
-
KeyPrefix,
|
|
36
|
-
} from "@pollinations/ui/wallet/sdk";
|
|
37
|
-
|
|
38
|
-
function RecentRequests() {
|
|
39
|
-
const { data: usage } = useAccountKeyUsage({ days: 7, limit: 5 });
|
|
40
|
-
return <span>{usage?.usage.length ?? 0} recent requests</span>;
|
|
41
|
-
}
|
|
30
|
+
import { AppUserMenu } from "@pollinations/ui/app-user-menu/sdk";
|
|
42
31
|
|
|
43
32
|
export function App() {
|
|
44
33
|
return (
|
|
45
34
|
<PolliProvider appKey="pk_your_publishable_key" permissions={["profile"]}>
|
|
46
35
|
<Surface data-theme="amber">
|
|
47
|
-
<
|
|
48
|
-
<LoginButton theme="amber">
|
|
49
|
-
Log in with Pollinations
|
|
50
|
-
</LoginButton>
|
|
51
|
-
</WhenLoggedOut>
|
|
52
|
-
<WhenLoggedIn>
|
|
53
|
-
<UserAvatar size="md" />
|
|
54
|
-
<UserName />
|
|
55
|
-
<Balance />
|
|
56
|
-
<KeyPrefix />
|
|
57
|
-
<KeyBudget />
|
|
58
|
-
<KeyExpiry />
|
|
59
|
-
<KeyModels />
|
|
60
|
-
<RecentRequests />
|
|
61
|
-
<LogoutButton theme="amber">Log out</LogoutButton>
|
|
62
|
-
</WhenLoggedIn>
|
|
36
|
+
<AppUserMenu dashboardHref="https://enter.pollinations.ai" />
|
|
63
37
|
</Surface>
|
|
64
38
|
</PolliProvider>
|
|
65
39
|
);
|
|
@@ -87,11 +61,8 @@ The SVG sources use `currentColor`. Apps control the rendered color by inlining
|
|
|
87
61
|
them or using them as masks. Root-level favicon, PWA icon, and SEO files stay
|
|
88
62
|
app-owned.
|
|
89
63
|
|
|
90
|
-
Wallet
|
|
91
|
-
|
|
92
|
-
```css
|
|
93
|
-
@import "@pollinations/ui/wallet.css";
|
|
94
|
-
```
|
|
64
|
+
Wallet colors and utilities are bundled into the main stylesheet
|
|
65
|
+
(`@pollinations/ui/styles.css`) — no separate import needed.
|
|
95
66
|
|
|
96
67
|
## What's exported
|
|
97
68
|
|
|
@@ -100,30 +71,25 @@ Wallet-specific colors and utilities live in a separate stylesheet:
|
|
|
100
71
|
- `@pollinations/ui/auth` exports SDK-free auth modal pieces:
|
|
101
72
|
`AuthModal`, `AuthModalHeader`, `AuthModalLoading`, `AuthInfoCard`, and
|
|
102
73
|
`ErrorBanner`.
|
|
103
|
-
- `@pollinations/ui/auth/sdk` exports identity/session components that read
|
|
104
|
-
from the surrounding `<PolliProvider>`:
|
|
105
|
-
- **null when not logged in (or before data loads):** `LogoutButton`,
|
|
106
|
-
`UserAvatar`, `UserEmail`, `UserName`, `WhenLoggedIn`.
|
|
107
|
-
- **shown only when logged out:** `LoginButton`, `WhenLoggedOut`.
|
|
108
|
-
|
|
109
|
-
These are intentionally bare wrappers around `useAuth*` hooks. They render
|
|
110
|
-
the data and nothing else — no default copy, no default theme, no default
|
|
111
|
-
intent. The app composes layout, copy, and color.
|
|
112
74
|
- `@pollinations/ui/wallet` exports SDK-free wallet-specific display helpers
|
|
113
75
|
and recipes: `formatPollen`, `PaidChip`, `TierChip`, `WalletDot`,
|
|
114
76
|
`WalletBalanceCard`, `PAID_BALANCE_CHART_COLOR`, and
|
|
115
77
|
`TIER_BALANCE_CHART_COLOR`.
|
|
116
|
-
- `@pollinations/ui/
|
|
117
|
-
|
|
118
|
-
- `@pollinations/ui/
|
|
78
|
+
- `@pollinations/ui/app-user-menu/sdk` exports the SDK-backed app account
|
|
79
|
+
menu module.
|
|
80
|
+
- `@pollinations/ui/gen` exports the generation UI — `ModelSelector`,
|
|
81
|
+
category labels, and the model-modality theme mapping.
|
|
119
82
|
- `@pollinations/ui/assets/*` exports canonical Pollinations source SVGs:
|
|
120
83
|
`logo.svg` and `logo-wordmark.svg`.
|
|
121
|
-
- **Design primitives** — `
|
|
122
|
-
`
|
|
123
|
-
`IconButton`, `
|
|
124
|
-
`
|
|
125
|
-
`
|
|
126
|
-
|
|
84
|
+
- **Design primitives** — `Button`, `ButtonGroup`, `Chip`, `ChevronIcon`,
|
|
85
|
+
`Dialog`, `DialogTitle`, `Dropdown`, `DropdownItem`, `Field`, `Heading`,
|
|
86
|
+
`IconButton`, `InlineLink`, `Input`, `ScrollArea`, `Slider`, `Surface`,
|
|
87
|
+
`Switch`, `TabButton`, `Table`, `TableBody`, `TableCell`, `TableHead`,
|
|
88
|
+
`TableHeaderCell`, `TableRow`, `Text`, `Textarea`, `Tooltip`.
|
|
89
|
+
- **Design compositions** — `Alert`, `CodeBlock`, `Collapsible`,
|
|
90
|
+
`CopyButton`, `ExternalLinkButton`, `FileUpload`, `InfoTip`, `LinkCard`,
|
|
91
|
+
`Markdown`, `MediaPlaceholder`, `MultiSelect`, `NavItem`, `PeriodPicker`,
|
|
92
|
+
`Prose`, `Section`, `StatCard`.
|
|
127
93
|
- **Helpers** — `cn`, `useScrollLock`, `currentPeriod`,
|
|
128
94
|
`getPeriodBucketKeys`, `periodBucketKeyToDate`.
|
|
129
95
|
- **Theme** — `themes` (runtime array of theme names), `ThemeName` (type).
|
|
@@ -135,16 +101,17 @@ from `@pollinations/sdk/react` (`useAccountKeyUsage`, `useAccountKey`,
|
|
|
135
101
|
## Source Layout
|
|
136
102
|
|
|
137
103
|
- `src/primitives/*` contains generic, SDK-free building blocks.
|
|
104
|
+
- `src/compositions/*` contains SDK-free recipes that compose primitives.
|
|
138
105
|
- `src/modules/*` contains package-owned recipes with domain assumptions
|
|
139
|
-
such as auth, wallet, and
|
|
106
|
+
such as auth, wallet, app-user-menu, and gen.
|
|
140
107
|
- Public subpath exports (`@pollinations/ui/auth`,
|
|
141
|
-
`@pollinations/ui/
|
|
142
|
-
`@pollinations/ui/
|
|
143
|
-
|
|
108
|
+
`@pollinations/ui/wallet`, `@pollinations/ui/gen`,
|
|
109
|
+
`@pollinations/ui/app-user-menu/sdk`) are built directly from those source
|
|
110
|
+
layers.
|
|
144
111
|
|
|
145
112
|
## Theming
|
|
146
113
|
|
|
147
|
-
Set `data-theme="amber" | "blue" | "pink" | "teal" | "violet" | "
|
|
114
|
+
Set `data-theme="amber" | "blue" | "pink" | "coral" | "teal" | "violet" | "emerald"`
|
|
148
115
|
on any ancestor (or per-component via the `theme` prop on Button-family
|
|
149
116
|
components) to switch the cascade. Theme variables are defined in
|
|
150
117
|
`styles.css` — import it once at your app entry.
|
|
@@ -185,7 +152,7 @@ with host app tokens.
|
|
|
185
152
|
| `--polli-text-base` | Base text size. |
|
|
186
153
|
| `--polli-color-surface-white` | Translucent white surface. |
|
|
187
154
|
|
|
188
|
-
Wallet tokens are public
|
|
155
|
+
Wallet tokens are public (bundled into `@pollinations/ui/styles.css`):
|
|
189
156
|
|
|
190
157
|
| Token | Purpose |
|
|
191
158
|
| ----------------------------- | --------------------------------------------- |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC, ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import { T as ThemeName } from './theme-
|
|
2
|
+
import { T as ThemeName } from './theme-jRPPBmld.cjs';
|
|
3
3
|
|
|
4
4
|
/** Semantic chip labels for status and metadata badges. */
|
|
5
5
|
type ChipIntent = "news" | "alpha" | "neutral" | "success" | "warning" | "danger";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC, ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import { T as ThemeName } from './theme-
|
|
2
|
+
import { T as ThemeName } from './theme-jRPPBmld.js';
|
|
3
3
|
|
|
4
4
|
/** Semantic chip labels for status and metadata badges. */
|
|
5
5
|
type ChipIntent = "news" | "alpha" | "neutral" | "success" | "warning" | "danger";
|
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/modules/app-user-menu/sdk.ts
|
|
21
|
+
var sdk_exports = {};
|
|
22
|
+
__export(sdk_exports, {
|
|
23
|
+
AppUserMenu: () => AppUserMenu,
|
|
24
|
+
isEmbeddedContext: () => isEmbeddedContext
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(sdk_exports);
|
|
27
|
+
|
|
28
|
+
// src/modules/app-user-menu/AppUserMenu.tsx
|
|
29
|
+
var import_react10 = require("@pollinations/sdk/react");
|
|
30
|
+
|
|
31
|
+
// src/lib/cn.ts
|
|
32
|
+
var import_clsx = require("clsx");
|
|
33
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
34
|
+
var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({ prefix: "polli" });
|
|
35
|
+
function cn(...inputs) {
|
|
36
|
+
return twMerge((0, import_clsx.clsx)(...inputs));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/primitives/ChevronIcon.tsx
|
|
40
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
|
+
var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
42
|
+
"svg",
|
|
43
|
+
{
|
|
44
|
+
"aria-hidden": "true",
|
|
45
|
+
width: "12",
|
|
46
|
+
height: "12",
|
|
47
|
+
viewBox: "0 0 12 12",
|
|
48
|
+
className: cn(
|
|
49
|
+
"polli:shrink-0 polli:transition-transform polli:duration-200 polli:ease-out",
|
|
50
|
+
expanded && "polli:rotate-180",
|
|
51
|
+
className
|
|
52
|
+
),
|
|
53
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
54
|
+
"path",
|
|
55
|
+
{
|
|
56
|
+
d: "M3 4.5 6 7.5l3-3",
|
|
57
|
+
fill: "none",
|
|
58
|
+
stroke: "currentColor",
|
|
59
|
+
strokeLinecap: "round",
|
|
60
|
+
strokeLinejoin: "round",
|
|
61
|
+
strokeWidth: "1.5"
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// src/primitives/Dropdown.tsx
|
|
68
|
+
var import_popover = require("@ark-ui/react/popover");
|
|
69
|
+
var import_portal = require("@ark-ui/react/portal");
|
|
70
|
+
var import_react = require("react");
|
|
71
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
72
|
+
var DEFAULT_PANEL = "polli:rounded-lg polli:border polli:border-theme-border polli:bg-theme-bg-pale polli:shadow-lg";
|
|
73
|
+
var Dropdown = ({
|
|
74
|
+
theme,
|
|
75
|
+
trigger,
|
|
76
|
+
children,
|
|
77
|
+
align = "start",
|
|
78
|
+
open: openProp,
|
|
79
|
+
onOpenChange,
|
|
80
|
+
className
|
|
81
|
+
}) => {
|
|
82
|
+
const [internalOpen, setInternalOpen] = (0, import_react.useState)(false);
|
|
83
|
+
const isControlled = openProp !== void 0;
|
|
84
|
+
const open = isControlled ? openProp : internalOpen;
|
|
85
|
+
const setOpen = (next) => {
|
|
86
|
+
if (!isControlled) setInternalOpen(next);
|
|
87
|
+
onOpenChange?.(next);
|
|
88
|
+
};
|
|
89
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
90
|
+
import_popover.Popover.Root,
|
|
91
|
+
{
|
|
92
|
+
open,
|
|
93
|
+
onOpenChange: (details) => setOpen(details.open),
|
|
94
|
+
positioning: {
|
|
95
|
+
placement: align === "end" ? "bottom-end" : "bottom-start"
|
|
96
|
+
},
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_popover.Popover.Trigger, { asChild: true, children: trigger(open) }),
|
|
99
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_popover.Popover.Positioner, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
100
|
+
import_popover.Popover.Content,
|
|
101
|
+
{
|
|
102
|
+
"data-theme": theme,
|
|
103
|
+
className: cn(
|
|
104
|
+
"polli:z-50 polli:overflow-hidden polli:focus:outline-none",
|
|
105
|
+
DEFAULT_PANEL,
|
|
106
|
+
className
|
|
107
|
+
),
|
|
108
|
+
children: typeof children === "function" ? children(() => setOpen(false)) : children
|
|
109
|
+
}
|
|
110
|
+
) }) })
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// src/primitives/DropdownItem.tsx
|
|
117
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
118
|
+
function DropdownItem({
|
|
119
|
+
as,
|
|
120
|
+
className,
|
|
121
|
+
children,
|
|
122
|
+
...rest
|
|
123
|
+
}) {
|
|
124
|
+
const Component = as || "button";
|
|
125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
126
|
+
Component,
|
|
127
|
+
{
|
|
128
|
+
...Component === "button" ? { type: "button" } : void 0,
|
|
129
|
+
...rest,
|
|
130
|
+
className: cn(
|
|
131
|
+
"polli-control polli:flex polli:w-full polli:cursor-pointer polli:items-center polli:gap-2 polli:rounded-lg polli:bg-transparent polli:px-3 polli:py-2 polli:text-left polli:text-sm polli:font-medium polli:text-theme-text-base polli:no-underline polli:transition-colors polli:hover:bg-theme-bg-hover polli:focus-visible:bg-theme-bg-hover",
|
|
132
|
+
className
|
|
133
|
+
),
|
|
134
|
+
children
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/modules/auth/LoginButton.tsx
|
|
140
|
+
var import_react2 = require("@pollinations/sdk/react");
|
|
141
|
+
|
|
142
|
+
// src/primitives/Button.tsx
|
|
143
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
144
|
+
var sizes = {
|
|
145
|
+
sm: "polli:px-2 polli:pt-0.5 polli:pb-1",
|
|
146
|
+
md: "polli:px-4 polli:pt-1.5 polli:pb-2",
|
|
147
|
+
lg: "polli:px-6 polli:py-3"
|
|
148
|
+
};
|
|
149
|
+
var themeClasses = "polli:bg-theme-bg-active polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:transition-colors";
|
|
150
|
+
var intentClasses = {
|
|
151
|
+
danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text polli:hover:bg-intent-danger-bg-hover polli:transition-colors"
|
|
152
|
+
};
|
|
153
|
+
var buttonClasses = ({
|
|
154
|
+
theme: _theme,
|
|
155
|
+
intent,
|
|
156
|
+
size,
|
|
157
|
+
className,
|
|
158
|
+
disabled
|
|
159
|
+
}) => {
|
|
160
|
+
const colorClasses = intent ? intentClasses[intent] : themeClasses;
|
|
161
|
+
return cn(
|
|
162
|
+
"polli-control polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:self-center polli:font-medium polli:leading-normal polli:box-border",
|
|
163
|
+
disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
|
|
164
|
+
colorClasses,
|
|
165
|
+
sizes[size || "md"],
|
|
166
|
+
className
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
function Button({
|
|
170
|
+
as,
|
|
171
|
+
children,
|
|
172
|
+
theme,
|
|
173
|
+
intent,
|
|
174
|
+
size,
|
|
175
|
+
className,
|
|
176
|
+
disabled,
|
|
177
|
+
...buttonProps
|
|
178
|
+
}) {
|
|
179
|
+
const Component = as || "button";
|
|
180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
181
|
+
Component,
|
|
182
|
+
{
|
|
183
|
+
"data-theme": intent ? void 0 : theme,
|
|
184
|
+
"data-intent": intent,
|
|
185
|
+
className: buttonClasses({
|
|
186
|
+
theme,
|
|
187
|
+
intent,
|
|
188
|
+
size,
|
|
189
|
+
className,
|
|
190
|
+
disabled
|
|
191
|
+
}),
|
|
192
|
+
disabled,
|
|
193
|
+
...buttonProps,
|
|
194
|
+
children
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/modules/auth/LoginButton.tsx
|
|
200
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
201
|
+
function LoginButton({ children, ...buttonProps }) {
|
|
202
|
+
const { isLoggedIn } = (0, import_react2.useAuthState)();
|
|
203
|
+
const { login } = (0, import_react2.useAuthActions)();
|
|
204
|
+
if (isLoggedIn) return null;
|
|
205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { ...buttonProps, onClick: () => login(), children });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/modules/auth/UserAvatar.tsx
|
|
209
|
+
var import_react3 = require("@pollinations/sdk/react");
|
|
210
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
211
|
+
var sizeClass = {
|
|
212
|
+
sm: "polli:w-6 polli:h-6 polli:text-xs",
|
|
213
|
+
md: "polli:w-9 polli:h-9 polli:text-sm",
|
|
214
|
+
lg: "polli:w-12 polli:h-12 polli:text-base"
|
|
215
|
+
};
|
|
216
|
+
function initials(name) {
|
|
217
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
218
|
+
if (parts.length === 0) return null;
|
|
219
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase() || null;
|
|
220
|
+
const first = parts[0][0] ?? "";
|
|
221
|
+
const last = parts[parts.length - 1][0] ?? "";
|
|
222
|
+
return (first + last).toUpperCase() || null;
|
|
223
|
+
}
|
|
224
|
+
function UserAvatar({ size = "md", className }) {
|
|
225
|
+
const { isLoggedIn } = (0, import_react3.useAuthState)();
|
|
226
|
+
const { data: profile } = (0, import_react3.useAccountProfile)({ enabled: isLoggedIn });
|
|
227
|
+
if (!isLoggedIn) return null;
|
|
228
|
+
const base = cn(
|
|
229
|
+
"polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:overflow-hidden polli:bg-theme-bg-pale polli:text-theme-text-strong polli:font-semibold polli:select-none",
|
|
230
|
+
sizeClass[size],
|
|
231
|
+
className
|
|
232
|
+
);
|
|
233
|
+
if (profile?.image) {
|
|
234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
235
|
+
"img",
|
|
236
|
+
{
|
|
237
|
+
"data-polli": "user-avatar",
|
|
238
|
+
src: profile.image,
|
|
239
|
+
alt: profile.name ?? "",
|
|
240
|
+
className: base
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
const label = profile?.name ? initials(profile.name) : null;
|
|
245
|
+
if (!label) return null;
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
247
|
+
"div",
|
|
248
|
+
{
|
|
249
|
+
"data-polli": "user-avatar",
|
|
250
|
+
role: "img",
|
|
251
|
+
"aria-label": profile?.name ?? void 0,
|
|
252
|
+
className: base,
|
|
253
|
+
children: label
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/modules/auth/UserName.tsx
|
|
259
|
+
var import_react4 = require("@pollinations/sdk/react");
|
|
260
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
261
|
+
function UserName({ className }) {
|
|
262
|
+
const { isLoggedIn } = (0, import_react4.useAuthState)();
|
|
263
|
+
const { data: profile } = (0, import_react4.useAccountProfile)({ enabled: isLoggedIn });
|
|
264
|
+
if (!isLoggedIn || !profile) return null;
|
|
265
|
+
const display = profile.name || profile.githubUsername;
|
|
266
|
+
if (!display) return null;
|
|
267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "data-polli": "user-name", className, children: display });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/modules/auth/WhenLoggedIn.tsx
|
|
271
|
+
var import_react5 = require("@pollinations/sdk/react");
|
|
272
|
+
var import_react6 = require("react");
|
|
273
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
274
|
+
function WhenLoggedIn({ children }) {
|
|
275
|
+
const { isLoggedIn } = (0, import_react5.useAuthState)();
|
|
276
|
+
if (!isLoggedIn) return null;
|
|
277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react6.Fragment, { children });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/modules/auth/WhenLoggedOut.tsx
|
|
281
|
+
var import_react7 = require("@pollinations/sdk/react");
|
|
282
|
+
var import_react8 = require("react");
|
|
283
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
284
|
+
function WhenLoggedOut({ children }) {
|
|
285
|
+
const { isLoggedIn } = (0, import_react7.useAuthState)();
|
|
286
|
+
if (isLoggedIn) return null;
|
|
287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children });
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/modules/wallet/Balance.tsx
|
|
291
|
+
var import_react9 = require("@pollinations/sdk/react");
|
|
292
|
+
|
|
293
|
+
// src/primitives/Chip.tsx
|
|
294
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
295
|
+
var chipSizes = {
|
|
296
|
+
sm: "polli:px-2 polli:py-0.5 polli:text-xs",
|
|
297
|
+
md: "polli:px-2.5 polli:py-0.5 polli:text-sm",
|
|
298
|
+
lg: "polli:px-3 polli:py-1 polli:text-sm"
|
|
299
|
+
};
|
|
300
|
+
var intentClasses2 = {
|
|
301
|
+
news: "polli:bg-intent-news-bg-light polli:text-intent-news-text",
|
|
302
|
+
alpha: "polli:bg-intent-alpha-bg-light polli:text-intent-alpha-text",
|
|
303
|
+
neutral: "polli:bg-ink-100/80 polli:text-ink-900",
|
|
304
|
+
success: "polli:bg-intent-success-bg-light polli:text-intent-success-text",
|
|
305
|
+
warning: "polli:bg-intent-warning-bg-light polli:text-intent-warning-text",
|
|
306
|
+
danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text"
|
|
307
|
+
};
|
|
308
|
+
var Chip = ({
|
|
309
|
+
theme,
|
|
310
|
+
intent,
|
|
311
|
+
size = "md",
|
|
312
|
+
className,
|
|
313
|
+
children,
|
|
314
|
+
...rest
|
|
315
|
+
}) => {
|
|
316
|
+
const intentClass = intent ? intentClasses2[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
|
|
317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
318
|
+
"span",
|
|
319
|
+
{
|
|
320
|
+
...rest,
|
|
321
|
+
"data-theme": theme,
|
|
322
|
+
className: cn(
|
|
323
|
+
"polli:inline-flex polli:shrink-0 polli:items-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-normal",
|
|
324
|
+
chipSizes[size],
|
|
325
|
+
intentClass,
|
|
326
|
+
className
|
|
327
|
+
),
|
|
328
|
+
children
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// src/modules/wallet/format-pollen.ts
|
|
334
|
+
var BUDGET = 5;
|
|
335
|
+
var MAX_DECIMALS = 4;
|
|
336
|
+
var COMPACT_THRESHOLD = 1e5;
|
|
337
|
+
function floorTo(value, decimals) {
|
|
338
|
+
const factor = 10 ** decimals;
|
|
339
|
+
return Math.floor(value * factor) / factor;
|
|
340
|
+
}
|
|
341
|
+
function formatCompact(value) {
|
|
342
|
+
const abs = Math.abs(value);
|
|
343
|
+
const sign = value < 0 ? "-" : "";
|
|
344
|
+
const [unit, scale] = abs >= 1e9 ? ["B", 1e9] : abs >= 1e6 ? ["M", 1e6] : ["K", 1e3];
|
|
345
|
+
const ratio = abs / scale;
|
|
346
|
+
const intDigits = Math.max(1, Math.floor(Math.log10(ratio)) + 1);
|
|
347
|
+
const decimals = Math.max(0, 3 - intDigits);
|
|
348
|
+
const floored = floorTo(ratio, decimals);
|
|
349
|
+
return `${sign}${Number(floored.toFixed(decimals)).toString()}${unit}`;
|
|
350
|
+
}
|
|
351
|
+
function formatPollen(value) {
|
|
352
|
+
if (!Number.isFinite(value) || value === 0) return "0";
|
|
353
|
+
const abs = Math.abs(value);
|
|
354
|
+
if (abs >= COMPACT_THRESHOLD) return formatCompact(value);
|
|
355
|
+
const intDigits = abs >= 1 ? Math.floor(Math.log10(abs)) + 1 : 1;
|
|
356
|
+
const decimals = Math.min(MAX_DECIMALS, Math.max(0, BUDGET - intDigits));
|
|
357
|
+
const floored = floorTo(value, decimals);
|
|
358
|
+
if (floored === 0) return "0";
|
|
359
|
+
return Number(floored.toFixed(decimals)).toString();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/modules/wallet/Balance.tsx
|
|
363
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
364
|
+
function Balance({ className } = {}) {
|
|
365
|
+
const { isLoggedIn } = (0, import_react9.useAuthState)();
|
|
366
|
+
const { data: balance } = (0, import_react9.useAccountBalance)({ enabled: isLoggedIn });
|
|
367
|
+
if (!isLoggedIn || balance == null) return null;
|
|
368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
369
|
+
Chip,
|
|
370
|
+
{
|
|
371
|
+
"data-polli": "balance",
|
|
372
|
+
className: cn("polli:tabular-nums", className),
|
|
373
|
+
children: [
|
|
374
|
+
formatPollen(balance.balance),
|
|
375
|
+
" pollen"
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// src/modules/app-user-menu/AppUserMenu.tsx
|
|
382
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
383
|
+
var defaultLabels = {
|
|
384
|
+
authorize: "Authorize app",
|
|
385
|
+
appUserMenu: "App user menu",
|
|
386
|
+
topUpAccount: "Top up account",
|
|
387
|
+
logout: "Log out from this app"
|
|
388
|
+
};
|
|
389
|
+
function isEmbeddedContext(embedQueryParam = "embed") {
|
|
390
|
+
if (typeof window === "undefined") return false;
|
|
391
|
+
const search = new URLSearchParams(window.location.search);
|
|
392
|
+
if (search.get(embedQueryParam) === "1") return true;
|
|
393
|
+
try {
|
|
394
|
+
return window.self !== window.top;
|
|
395
|
+
} catch {
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function AppUserMenu({
|
|
400
|
+
dashboardHref,
|
|
401
|
+
labels: labelOverrides,
|
|
402
|
+
hiddenWhenEmbedded = false,
|
|
403
|
+
embedQueryParam = "embed"
|
|
404
|
+
}) {
|
|
405
|
+
if (hiddenWhenEmbedded && isEmbeddedContext(embedQueryParam)) return null;
|
|
406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
407
|
+
AppUserMenuContent,
|
|
408
|
+
{
|
|
409
|
+
dashboardHref,
|
|
410
|
+
labels: labelOverrides
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function AppUserMenuContent({
|
|
415
|
+
dashboardHref,
|
|
416
|
+
labels: labelOverrides
|
|
417
|
+
}) {
|
|
418
|
+
const labels = { ...defaultLabels, ...labelOverrides };
|
|
419
|
+
const { logout } = (0, import_react10.useAuthActions)();
|
|
420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-theme": "amber", className: "polli:flex polli:justify-end", children: [
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(WhenLoggedOut, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LoginButton, { theme: "amber", children: labels.authorize }) }),
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(WhenLoggedIn, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
423
|
+
Dropdown,
|
|
424
|
+
{
|
|
425
|
+
theme: "amber",
|
|
426
|
+
align: "end",
|
|
427
|
+
className: "polli:w-64 polli:p-1",
|
|
428
|
+
trigger: (open) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
429
|
+
"button",
|
|
430
|
+
{
|
|
431
|
+
type: "button",
|
|
432
|
+
"data-theme": "amber",
|
|
433
|
+
"aria-label": labels.appUserMenu,
|
|
434
|
+
className: "polli-control polli:flex polli:min-w-0 polli:items-center polli:gap-2 polli:rounded-full polli:bg-theme-bg-active polli:py-1 polli:pl-1 polli:pr-3 polli:text-theme-text-base polli:shadow-sm polli:transition-colors polli:hover:bg-theme-bg-hover",
|
|
435
|
+
children: [
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
437
|
+
UserAvatar,
|
|
438
|
+
{
|
|
439
|
+
size: "md",
|
|
440
|
+
className: "polli:h-8 polli:w-8"
|
|
441
|
+
}
|
|
442
|
+
),
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "polli:flex polli:min-w-0 polli:flex-col polli:items-start polli:leading-tight", children: [
|
|
444
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(UserName, { className: "polli:max-w-32 polli:truncate polli:text-sm polli:font-semibold" }),
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Balance, { className: "polli:bg-transparent polli:px-0 polli:py-0 polli:text-xs polli:text-theme-text-base" })
|
|
446
|
+
] }),
|
|
447
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
448
|
+
ChevronIcon,
|
|
449
|
+
{
|
|
450
|
+
expanded: open,
|
|
451
|
+
className: "polli:h-4 polli:w-4 polli:text-theme-text-base"
|
|
452
|
+
}
|
|
453
|
+
)
|
|
454
|
+
]
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
children: (close) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
458
|
+
"div",
|
|
459
|
+
{
|
|
460
|
+
"data-theme": "amber",
|
|
461
|
+
className: "polli:flex polli:flex-col",
|
|
462
|
+
children: [
|
|
463
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
464
|
+
DropdownItem,
|
|
465
|
+
{
|
|
466
|
+
as: "a",
|
|
467
|
+
href: dashboardHref,
|
|
468
|
+
target: "_blank",
|
|
469
|
+
rel: "noopener noreferrer",
|
|
470
|
+
onClick: close,
|
|
471
|
+
children: labels.topUpAccount
|
|
472
|
+
}
|
|
473
|
+
),
|
|
474
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
475
|
+
DropdownItem,
|
|
476
|
+
{
|
|
477
|
+
type: "button",
|
|
478
|
+
onClick: () => {
|
|
479
|
+
close();
|
|
480
|
+
logout();
|
|
481
|
+
},
|
|
482
|
+
children: labels.logout
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
]
|
|
486
|
+
}
|
|
487
|
+
)
|
|
488
|
+
}
|
|
489
|
+
) })
|
|
490
|
+
] });
|
|
491
|
+
}
|
|
492
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
493
|
+
0 && (module.exports = {
|
|
494
|
+
AppUserMenu,
|
|
495
|
+
isEmbeddedContext
|
|
496
|
+
});
|
|
497
|
+
//# sourceMappingURL=sdk.cjs.map
|