@crediball/elements 0.4.0 → 0.4.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.
@@ -1,30 +1,9 @@
1
1
  // src/base.ts
2
2
  import {
3
- getCrediballClient
3
+ getCrediballClient,
4
+ loadRemoteFont,
5
+ themeToCssVars
4
6
  } from "@crediball/core";
5
- var THEME_VARS = [
6
- ["accent", "--crediball-accent", String],
7
- ["onAccent", "--crediball-on-accent", String],
8
- ["ink", "--crediball-ink", String],
9
- ["canvas", "--crediball-canvas", String],
10
- ["hairline", "--crediball-hairline", String],
11
- ["radius", "--crediball-radius", (v) => `${v}px`],
12
- ["radiusCard", "--crediball-radius-card", (v) => `${v}px`],
13
- ["fontStack", "--crediball-font", String]
14
- ];
15
- function loadRemoteFont(url) {
16
- if (typeof document === "undefined") return;
17
- const existing = document.querySelector("link[data-crediball-font]");
18
- if (existing?.href === url) return;
19
- if (existing) existing.href = url;
20
- else {
21
- const link = document.createElement("link");
22
- link.rel = "stylesheet";
23
- link.href = url;
24
- link.setAttribute("data-crediball-font", "");
25
- document.head.appendChild(link);
26
- }
27
- }
28
7
  var _CrediballElement = class _CrediballElement extends HTMLElement {
29
8
  constructor() {
30
9
  super(...arguments);
@@ -85,9 +64,8 @@ var _CrediballElement = class _CrediballElement extends HTMLElement {
85
64
  if (this.getAttribute("apply-remote-theme") === "false") return;
86
65
  const theme = this.getSnapshot()?.packages?.ui?.theme;
87
66
  if (!theme) return;
88
- for (const [key, cssVar, fmt] of THEME_VARS) {
89
- const value = theme[key];
90
- if (value != null && value !== "") this.style.setProperty(cssVar, fmt(value));
67
+ for (const [cssVar, value] of Object.entries(themeToCssVars(theme))) {
68
+ this.style.setProperty(cssVar, value);
91
69
  }
92
70
  if (theme.fontUrl) loadRemoteFont(theme.fontUrl);
93
71
  }
@@ -110,9 +88,7 @@ _CrediballElement.CLIENT_ATTRS = /* @__PURE__ */ new Set([
110
88
  var CrediballElement = _CrediballElement;
111
89
 
112
90
  // src/format.ts
113
- function formatCredits(credits) {
114
- return new Intl.NumberFormat(void 0).format(Math.round(credits));
115
- }
91
+ import { formatCredits } from "@crediball/core";
116
92
 
117
93
  // src/balance.ts
118
94
  var CrediballBalanceElement = class extends CrediballElement {
@@ -186,6 +162,7 @@ var CrediballTopUpButtonElement = class extends CrediballElement {
186
162
  };
187
163
 
188
164
  // src/low-credit-warning.ts
165
+ import { isBalanceLow } from "@crediball/core";
189
166
  var CrediballLowCreditWarningElement = class extends CrediballElement {
190
167
  static get observedAttributes() {
191
168
  return [...CrediballElement.observedAttributes, "threshold"];
@@ -200,7 +177,7 @@ var CrediballLowCreditWarningElement = class extends CrediballElement {
200
177
  const content = snapshot?.packages?.ui?.content;
201
178
  const thresholdAttr = this.getAttribute("threshold");
202
179
  const threshold = thresholdAttr != null ? Number(thresholdAttr) : content?.lowCreditThreshold;
203
- const isLow = threshold != null && snapshot?.balance != null ? snapshot.balance < threshold : !!snapshot?.isLow;
180
+ const isLow = isBalanceLow(snapshot?.balance ?? null, threshold, !!snapshot?.isLow);
204
181
  this.style.display = isLow ? "" : "none";
205
182
  const slot = this.shadowRoot?.querySelector("slot");
206
183
  if (slot) slot.textContent = content?.lowCreditMessage ?? "Low credit balance \u2014 top up to keep going.";
@@ -208,13 +185,7 @@ var CrediballLowCreditWarningElement = class extends CrediballElement {
208
185
  };
209
186
 
210
187
  // src/paywall.ts
211
- function formatMoney(amount, currency) {
212
- try {
213
- return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(amount);
214
- } catch {
215
- return `${amount.toFixed(2)} ${currency}`;
216
- }
217
- }
188
+ import { formatMoney } from "@crediball/core";
218
189
  var CURRENCY_SYMBOLS = { EUR: "\u20AC", USD: "$", GBP: "\xA3" };
219
190
  function currencySymbolFor(currency) {
220
191
  return CURRENCY_SYMBOLS[currency.toUpperCase()] ?? currency;
@@ -68,8 +68,21 @@ var Crediball = (() => {
68
68
  return () => window.removeEventListener(BALANCE_CHANGED_EVENT, listener);
69
69
  }
70
70
 
71
- // ../core/dist/client.js
71
+ // ../core/dist/http.js
72
72
  var DEFAULT_API_URL = "https://www.crediball.ai/api";
73
+ async function errorMessage(res, fallback) {
74
+ const body = await res.json().catch(() => null);
75
+ return body && typeof body === "object" && "error" in body && String(body.error) || fallback;
76
+ }
77
+ async function fetchJson(url, init, failureLabel = `Request to ${url}`) {
78
+ const res = await fetch(url, init);
79
+ if (!res.ok) {
80
+ throw new Error(await errorMessage(res, `${failureLabel} failed with ${res.status}`));
81
+ }
82
+ return res.json();
83
+ }
84
+
85
+ // ../core/dist/client.js
73
86
  var DEFAULT_POLL_MS = 3e4;
74
87
  var SSE_HEALTHY_POLL_MULTIPLIER = 2;
75
88
  var MAX_SSE_FAILURES = 2;
@@ -85,15 +98,6 @@ var Crediball = (() => {
85
98
  error: null
86
99
  };
87
100
  }
88
- async function fetchJson(url, headers) {
89
- const res = await fetch(url, { headers });
90
- if (!res.ok) {
91
- const body = await res.json().catch(() => null);
92
- const message = body && typeof body === "object" && "error" in body && String(body.error) || `Request to ${url} failed with ${res.status}`;
93
- throw new Error(message);
94
- }
95
- return res.json();
96
- }
97
101
  function computeIsLow(balance, costs, explicitThreshold) {
98
102
  if (balance == null)
99
103
  return false;
@@ -134,10 +138,10 @@ var Crediball = (() => {
134
138
  const qs = `userId=${encodeURIComponent(userId)}`;
135
139
  try {
136
140
  const [balanceRes, usageRes, costsRes, packagesRes] = await Promise.all([
137
- fetchJson(`${this.apiUrl}/public/balance?${qs}`, headers),
138
- fetchJson(`${this.apiUrl}/public/usage?${qs}`, headers),
139
- fetchJson(`${this.apiUrl}/public/costs`, headers),
140
- fetchJson(`${this.apiUrl}/public/packages?${qs}`, headers)
141
+ fetchJson(`${this.apiUrl}/public/balance?${qs}`, { headers }),
142
+ fetchJson(`${this.apiUrl}/public/usage?${qs}`, { headers }),
143
+ fetchJson(`${this.apiUrl}/public/costs`, { headers }),
144
+ fetchJson(`${this.apiUrl}/public/packages?${qs}`, { headers })
141
145
  ]);
142
146
  const costs = {};
143
147
  for (const e of costsRes.events)
@@ -188,22 +192,16 @@ var Crediball = (() => {
188
192
  this.apiUrl = (config.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
189
193
  this.pollIntervalMs = config.pollIntervalMs ?? DEFAULT_POLL_MS;
190
194
  }
191
- async postCheckout(path, input) {
195
+ postCheckout(path, input) {
192
196
  const { publishableKey, userId } = this.config;
193
- const res = await fetch(`${this.apiUrl}${path}`, {
197
+ return fetchJson(`${this.apiUrl}${path}`, {
194
198
  method: "POST",
195
199
  headers: {
196
200
  "Content-Type": "application/json",
197
201
  Authorization: `Bearer ${publishableKey}`
198
202
  },
199
203
  body: JSON.stringify({ userId, ...input })
200
- });
201
- if (!res.ok) {
202
- const body = await res.json().catch(() => null);
203
- const message = body && typeof body === "object" && "error" in body && String(body.error) || `Checkout request failed with ${res.status}`;
204
- throw new Error(message);
205
- }
206
- return res.json();
204
+ }, "Checkout request");
207
205
  }
208
206
  pause() {
209
207
  this.stopPolling();
@@ -303,8 +301,23 @@ var Crediball = (() => {
303
301
  return client;
304
302
  }
305
303
 
306
- // src/base.ts
307
- var THEME_VARS = [
304
+ // ../core/dist/format.js
305
+ function formatCredits(credits) {
306
+ return new Intl.NumberFormat(void 0).format(Math.round(credits));
307
+ }
308
+ function formatMoney(amount, currency) {
309
+ try {
310
+ return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(amount);
311
+ } catch {
312
+ return `${amount.toFixed(2)} ${currency}`;
313
+ }
314
+ }
315
+ function isBalanceLow(balance, threshold, fallback) {
316
+ return threshold != null && balance != null ? balance < threshold : fallback;
317
+ }
318
+
319
+ // ../core/dist/theme.js
320
+ var THEME_CSS_VAR_ENTRIES = [
308
321
  ["accent", "--crediball-accent", String],
309
322
  ["onAccent", "--crediball-on-accent", String],
310
323
  ["ink", "--crediball-ink", String],
@@ -314,11 +327,25 @@ var Crediball = (() => {
314
327
  ["radiusCard", "--crediball-radius-card", (v) => `${v}px`],
315
328
  ["fontStack", "--crediball-font", String]
316
329
  ];
330
+ function themeToCssVars(theme) {
331
+ const vars = {};
332
+ if (!theme)
333
+ return vars;
334
+ for (const [key, cssVar, fmt] of THEME_CSS_VAR_ENTRIES) {
335
+ const value = theme[key];
336
+ if (value != null && value !== "")
337
+ vars[cssVar] = fmt(value);
338
+ }
339
+ return vars;
340
+ }
317
341
  function loadRemoteFont(url) {
318
- if (typeof document === "undefined") return;
342
+ if (typeof document === "undefined")
343
+ return;
319
344
  const existing = document.querySelector("link[data-crediball-font]");
320
- if (existing?.href === url) return;
321
- if (existing) existing.href = url;
345
+ if (existing?.href === url)
346
+ return;
347
+ if (existing)
348
+ existing.href = url;
322
349
  else {
323
350
  const link = document.createElement("link");
324
351
  link.rel = "stylesheet";
@@ -327,6 +354,8 @@ var Crediball = (() => {
327
354
  document.head.appendChild(link);
328
355
  }
329
356
  }
357
+
358
+ // src/base.ts
330
359
  var _CrediballElement = class _CrediballElement extends HTMLElement {
331
360
  constructor() {
332
361
  super(...arguments);
@@ -387,9 +416,8 @@ var Crediball = (() => {
387
416
  if (this.getAttribute("apply-remote-theme") === "false") return;
388
417
  const theme = this.getSnapshot()?.packages?.ui?.theme;
389
418
  if (!theme) return;
390
- for (const [key, cssVar, fmt] of THEME_VARS) {
391
- const value = theme[key];
392
- if (value != null && value !== "") this.style.setProperty(cssVar, fmt(value));
419
+ for (const [cssVar, value] of Object.entries(themeToCssVars(theme))) {
420
+ this.style.setProperty(cssVar, value);
393
421
  }
394
422
  if (theme.fontUrl) loadRemoteFont(theme.fontUrl);
395
423
  }
@@ -411,11 +439,6 @@ var Crediball = (() => {
411
439
  ]);
412
440
  var CrediballElement = _CrediballElement;
413
441
 
414
- // src/format.ts
415
- function formatCredits(credits) {
416
- return new Intl.NumberFormat(void 0).format(Math.round(credits));
417
- }
418
-
419
442
  // src/balance.ts
420
443
  var CrediballBalanceElement = class extends CrediballElement {
421
444
  constructor() {
@@ -502,7 +525,7 @@ var Crediball = (() => {
502
525
  const content = snapshot?.packages?.ui?.content;
503
526
  const thresholdAttr = this.getAttribute("threshold");
504
527
  const threshold = thresholdAttr != null ? Number(thresholdAttr) : content?.lowCreditThreshold;
505
- const isLow = threshold != null && snapshot?.balance != null ? snapshot.balance < threshold : !!snapshot?.isLow;
528
+ const isLow = isBalanceLow(snapshot?.balance ?? null, threshold, !!snapshot?.isLow);
506
529
  this.style.display = isLow ? "" : "none";
507
530
  const slot = this.shadowRoot?.querySelector("slot");
508
531
  if (slot) slot.textContent = content?.lowCreditMessage ?? "Low credit balance \u2014 top up to keep going.";
@@ -510,13 +533,6 @@ var Crediball = (() => {
510
533
  };
511
534
 
512
535
  // src/paywall.ts
513
- function formatMoney(amount, currency) {
514
- try {
515
- return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(amount);
516
- } catch {
517
- return `${amount.toFixed(2)} ${currency}`;
518
- }
519
- }
520
536
  var CURRENCY_SYMBOLS = { EUR: "\u20AC", USD: "$", GBP: "\xA3" };
521
537
  function currencySymbolFor(currency) {
522
538
  return CURRENCY_SYMBOLS[currency.toUpperCase()] ?? currency;
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  CrediballPaywallElement,
6
6
  CrediballTopUpButtonElement,
7
7
  CrediballUsageElement
8
- } from "./chunk-KXVW7PIU.js";
8
+ } from "./chunk-WUPVPARI.js";
9
9
  export {
10
10
  CrediballBalanceElement,
11
11
  CrediballElement,
package/dist/register.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  CrediballPaywallElement,
5
5
  CrediballTopUpButtonElement,
6
6
  CrediballUsageElement
7
- } from "./chunk-KXVW7PIU.js";
7
+ } from "./chunk-WUPVPARI.js";
8
8
 
9
9
  // src/register.ts
10
10
  function define(name, ctor) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crediball/elements",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Framework-agnostic web components for showing Crediball credits inside your AI app.",
5
5
  "license": "MIT",
6
6
  "author": "Filippo Rezzadore <filipporezzadore@gmail.com>",
@@ -56,7 +56,7 @@
56
56
  "prepublishOnly": "npm run build"
57
57
  },
58
58
  "dependencies": {
59
- "@crediball/core": "^0.3.0"
59
+ "@crediball/core": "^0.4.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "tsup": "^8.3.5",