@locusgraph/blocks 0.2.0 → 0.3.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.
Files changed (48) hide show
  1. package/README.md +11 -11
  2. package/dist/billing/plan-price.d.ts +4 -0
  3. package/dist/billing/plan-price.js +70 -0
  4. package/dist/billing/{plan-options.d.ts → plans.d.ts} +2 -2
  5. package/dist/billing/plans.js +74 -0
  6. package/dist/billing/top-up.d.ts +11 -0
  7. package/dist/billing/top-up.js +108 -0
  8. package/dist/billing/wallet.d.ts +8 -0
  9. package/dist/billing/wallet.js +217 -0
  10. package/dist/dates/local-date.js +51 -7
  11. package/dist/index.d.ts +13 -8
  12. package/dist/index.js +13 -8
  13. package/dist/keys/{no-keys.d.ts → keys-empty.d.ts} +2 -2
  14. package/dist/keys/keys-empty.js +73 -0
  15. package/dist/keys/{keys-table.d.ts → keys.d.ts} +2 -2
  16. package/dist/keys/keys.js +151 -0
  17. package/dist/skeletons/keys-skeleton.d.ts +6 -0
  18. package/dist/skeletons/keys-skeleton.js +170 -0
  19. package/dist/skeletons/plans-skeleton.d.ts +7 -0
  20. package/dist/skeletons/plans-skeleton.js +94 -0
  21. package/dist/skeletons/top-up-skeleton.d.ts +5 -0
  22. package/dist/skeletons/top-up-skeleton.js +73 -0
  23. package/dist/skeletons/usage-skeleton.d.ts +6 -0
  24. package/dist/skeletons/usage-skeleton.js +88 -0
  25. package/dist/skeletons/wallet-skeleton.d.ts +5 -0
  26. package/dist/skeletons/wallet-skeleton.js +84 -0
  27. package/dist/types.d.ts +5 -1
  28. package/dist/types.js +1 -1
  29. package/dist/usage/quota.d.ts +4 -0
  30. package/dist/usage/quota.js +203 -0
  31. package/dist/usage/usage-alert.d.ts +11 -0
  32. package/dist/usage/usage-alert.js +222 -0
  33. package/dist/usage/usage.d.ts +8 -0
  34. package/dist/usage/usage.js +57 -0
  35. package/package.json +6 -6
  36. package/dist/billing/credit-packs.d.ts +0 -9
  37. package/dist/billing/credit-packs.js +0 -6
  38. package/dist/billing/plan-options.js +0 -8
  39. package/dist/billing/wallet-panel.d.ts +0 -8
  40. package/dist/billing/wallet-panel.js +0 -16
  41. package/dist/keys/keys-table.js +0 -9
  42. package/dist/keys/no-keys.js +0 -8
  43. package/dist/usage/quota-meter.d.ts +0 -4
  44. package/dist/usage/quota-meter.js +0 -13
  45. package/dist/usage/usage-attention.d.ts +0 -11
  46. package/dist/usage/usage-attention.js +0 -20
  47. package/dist/usage/usage-summary.d.ts +0 -8
  48. package/dist/usage/usage-summary.js +0 -6
@@ -1,8 +0,0 @@
1
- import type { WalletGrant } from "../types.js";
2
- type WalletPanelProps = {
3
- balanceMicroUsd: number;
4
- debtMicroUsd?: number;
5
- grants: WalletGrant[];
6
- };
7
- export declare function WalletPanel({ balanceMicroUsd, debtMicroUsd, grants }: WalletPanelProps): import("react").JSX.Element;
8
- export {};
@@ -1,16 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Badge, RuleGridCell, RuleGridLabel } from "@locusgraph/components";
3
- import { balanceLevel, formatDate, formatMicroUsd } from "@locusgraph/utils";
4
- const levelHint = {
5
- low: { badge: "Low", text: "Add credits before usage stops.", tone: "text-warn" },
6
- empty: {
7
- badge: "Empty",
8
- text: "Paid usage is paused until you add credits.",
9
- tone: "text-destructive",
10
- },
11
- };
12
- export function WalletPanel({ balanceMicroUsd, debtMicroUsd = 0, grants }) {
13
- const level = balanceLevel(balanceMicroUsd);
14
- const hint = level === "fine" ? null : levelHint[level];
15
- return (_jsxs(RuleGridCell, { "data-level": level, className: "gap-4", children: [_jsxs("span", { className: "flex items-center justify-between", children: [_jsx(RuleGridLabel, { children: "Prepaid credits" }), hint && (_jsx(Badge, { variant: level === "empty" ? "destructive" : "secondary", className: level === "low" ? "text-warn" : undefined, children: hint.badge }))] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { className: "font-heading text-3xl font-semibold tracking-[-0.02em] tabular-nums", children: formatMicroUsd(balanceMicroUsd) }), hint && _jsx("p", { className: `text-sm ${hint.tone}`, children: hint.text })] }), _jsxs("div", { className: "flex flex-col gap-3 text-sm", children: [grants.length > 0 ? (_jsx("ul", { className: "flex flex-col divide-y divide-line", children: grants.map((grant) => (_jsxs("li", { className: "flex justify-between gap-4 py-2", children: [_jsx("span", { children: grant.label }), _jsxs("span", { className: "text-muted-foreground tabular-nums", children: [formatMicroUsd(grant.remainingMicroUsd), " \u00B7", " ", grant.expiresAt ? `expires ${formatDate(grant.expiresAt)}` : "never expires"] })] }, `${grant.label}:${grant.expiresAt}`))) })) : (_jsx("p", { className: "text-muted-foreground", children: "No credits yet. Buy a pack to keep using paid features." })), debtMicroUsd > 0 && (_jsxs("p", { className: "text-destructive", children: [formatMicroUsd(debtMicroUsd), " owed. It comes out of the next credits you add."] }))] })] }));
16
- }
@@ -1,9 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@locusgraph/components";
3
- import { LocalDate } from "../dates/local-date.js";
4
- function dateOr(value, empty) {
5
- return value ? _jsx(LocalDate, { value: value }) : empty;
6
- }
7
- export function KeysTable({ keys, actions, highlightedId }) {
8
- return (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Name" }), _jsx(TableHead, { className: "hidden md:table-cell", children: "Key" }), _jsx(TableHead, { children: "Product" }), _jsx(TableHead, { className: "hidden md:table-cell", children: "Created by" }), _jsx(TableHead, { className: "hidden sm:table-cell", children: "Created" }), _jsx(TableHead, { children: "Expires" }), actions && _jsx(TableHead, { className: "w-0" })] }) }), _jsx(TableBody, { children: keys.map((key) => (_jsxs(TableRow, { "data-new": key.id === highlightedId ? "" : undefined, className: "transition-colors duration-1000 data-new:bg-accent", children: [_jsx(TableCell, { className: "font-medium", children: key.name ?? "Untitled" }), _jsx(TableCell, { className: "hidden font-mono text-muted-foreground md:table-cell", children: key.maskedKey }), _jsx(TableCell, { children: key.productLabel }), _jsx(TableCell, { className: "hidden md:table-cell", children: key.createdBy }), _jsx(TableCell, { className: "hidden sm:table-cell", children: dateOr(key.createdAt, "") }), _jsx(TableCell, { children: dateOr(key.expiresAt, "Never") }), actions && _jsx(TableCell, { className: "text-right", children: actions(key) })] }, key.id))) })] }));
9
- }
@@ -1,8 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button, RuleGrid, RuleGridCell, RuleGridDescription, RuleGridLabel, } from "@locusgraph/components";
3
- import { KeyRoundIcon, PlusIcon } from "lucide-react";
4
- export function NoKeys({ newKeyHref, description = newKeyHref
5
- ? "Create a key to let a service call LocusGraph products for this organization."
6
- : "Ask an owner to create a key for this organization.", linkComponent: Link = "a", }) {
7
- return (_jsx(RuleGrid, { columns: 1, children: _jsxs(RuleGridCell, { className: "items-center gap-3 py-12 text-center", children: [_jsx(KeyRoundIcon, { className: "size-5 text-muted-foreground" }), _jsx(RuleGridLabel, { children: "No API keys yet" }), _jsx(RuleGridDescription, { className: "max-w-sm", children: description }), newKeyHref && (_jsx(Button, { asChild: true, size: "sm", children: _jsxs(Link, { href: newKeyHref, children: [_jsx(PlusIcon, {}), "New key"] }) }))] }) }));
8
- }
@@ -1,4 +0,0 @@
1
- import { type Quota } from "../types.js";
2
- export declare function QuotaMeter({ quota }: {
3
- quota: Quota;
4
- }): import("react").JSX.Element;
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Progress } from "@locusgraph/components";
3
- import { formatCount, quotaPercent, quotaStatus } from "@locusgraph/utils";
4
- import { periodLabel } from "../types.js";
5
- const statusIndicator = {
6
- ok: "",
7
- near: "[&_[data-slot=progress-indicator]]:bg-warn",
8
- over: "[&_[data-slot=progress-indicator]]:bg-destructive",
9
- };
10
- export function QuotaMeter({ quota }) {
11
- const percent = quotaPercent(quota);
12
- return (_jsxs("div", { "data-slot": "quota-meter", "data-status": quotaStatus(quota), className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-4 text-sm", children: [_jsx("span", { className: "font-mono", children: quota.key }), _jsxs("span", { className: "text-muted-foreground tabular-nums", children: [formatCount(quota.used), " of ", formatCount(quota.included), " ", periodLabel(quota.period)] })] }), _jsx(Progress, { value: percent, "aria-label": `${quota.key} ${percent}% of quota`, className: statusIndicator[quotaStatus(quota)] })] }));
13
- }
@@ -1,11 +0,0 @@
1
- import { type LinkComponent, type Quota } from "../types.js";
2
- type UsageAttentionProps = {
3
- balanceMicroUsd: number | null;
4
- quotas: Quota[];
5
- paidPlan: boolean;
6
- buyCreditsHref: string;
7
- upgradeHref: string;
8
- linkComponent?: LinkComponent | "a";
9
- };
10
- export declare function UsageAttention({ balanceMicroUsd, quotas, paidPlan, buyCreditsHref, upgradeHref, linkComponent: Link, }: UsageAttentionProps): import("react").JSX.Element | null;
11
- export {};
@@ -1,20 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Alert, AlertDescription, AlertTitle, Button } from "@locusgraph/components";
3
- import { balanceLevel, formatCount, formatMicroUsd, quotaStatus } from "@locusgraph/utils";
4
- import { CircleAlertIcon } from "lucide-react";
5
- import { periodLabel } from "../types.js";
6
- function attentionTitle(empty, overCount) {
7
- if (empty)
8
- return "Out of credits";
9
- return overCount > 0 ? "Usage is over your plan" : "Credits are running low";
10
- }
11
- export function UsageAttention({ balanceMicroUsd, quotas, paidPlan, buyCreditsHref, upgradeHref, linkComponent: Link = "a", }) {
12
- const level = balanceMicroUsd === null ? "fine" : balanceLevel(balanceMicroUsd);
13
- const over = quotas.filter((quota) => quotaStatus(quota) === "over");
14
- if (level === "fine" && over.length === 0)
15
- return null;
16
- const empty = level === "empty";
17
- return (_jsxs(Alert, { variant: empty ? "destructive" : "default", className: empty ? undefined : "text-warn *:data-[slot=alert-description]:text-warn/85", children: [_jsx(CircleAlertIcon, {}), _jsx(AlertTitle, { children: attentionTitle(empty, over.length) }), _jsxs(AlertDescription, { className: "flex flex-wrap items-end justify-between gap-4", children: [_jsxs("ul", { className: "flex flex-col gap-1", children: [over.map((quota) => (_jsxs("li", { children: [_jsx("span", { className: "font-mono", children: quota.key }), " is at ", formatCount(quota.used), " of", " ", formatCount(quota.included), " ", periodLabel(quota.period), "."] }, quota.key))), balanceMicroUsd !== null && level !== "fine" && (_jsx("li", { children: empty
18
- ? "Paid usage is paused until you add credits."
19
- : `${formatMicroUsd(balanceMicroUsd)} of credits left.` }))] }), _jsxs("div", { className: "flex items-center gap-4", children: [!paidPlan && (_jsx(Link, { href: upgradeHref, className: "text-sm text-foreground underline-offset-4 hover:underline", children: "Upgrade to Pro" })), _jsx(Button, { asChild: true, size: "sm", children: _jsx(Link, { href: buyCreditsHref, children: "Buy credits" }) })] })] })] }));
20
- }
@@ -1,8 +0,0 @@
1
- import type { Quota } from "../types.js";
2
- type UsageSummaryProps = {
3
- quotas: Quota[];
4
- label?: string;
5
- emptyText?: string;
6
- };
7
- export declare function UsageSummary({ quotas, label, emptyText, }: UsageSummaryProps): import("react").JSX.Element;
8
- export {};
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { RuleGrid, RuleGridCell, RuleGridLabel } from "@locusgraph/components";
3
- import { QuotaMeter } from "./quota-meter.js";
4
- export function UsageSummary({ quotas, label = "Usage", emptyText = "No plan includes metered usage yet.", }) {
5
- return (_jsx(RuleGrid, { columns: 1, children: _jsxs(RuleGridCell, { className: "gap-5", children: [_jsx(RuleGridLabel, { children: label }), quotas.length > 0 ? (quotas.map((quota) => _jsx(QuotaMeter, { quota: quota }, quota.key))) : (_jsx("p", { className: "text-sm text-muted-foreground", children: emptyText }))] }) }));
6
- }