@le-space/ui 0.6.45 → 0.6.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/ui",
3
- "version": "0.6.45",
3
+ "version": "0.6.46",
4
4
  "description": "Floating Aleph Relay Button UI components for Svelte and React.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,8 +44,8 @@
44
44
  "url": "https://github.com/NiKrause/relay-button/issues"
45
45
  },
46
46
  "dependencies": {
47
- "@le-space/browser": "0.6.45",
48
- "@le-space/core": "0.6.45",
47
+ "@le-space/browser": "0.6.46",
48
+ "@le-space/core": "0.6.46",
49
49
  "viem": "^2.53.1"
50
50
  },
51
51
  "peerDependencies": {
package/react/index.d.ts CHANGED
@@ -315,6 +315,12 @@ interface SponsorRelayState {
315
315
  balance: BalanceResponse | null;
316
316
  crns: Crn[];
317
317
  selectedCrn: Crn | null;
318
+ crnOptions: Array<{
319
+ hash: string;
320
+ name: string | null;
321
+ score: number | null;
322
+ }>;
323
+ crnPinnedByUser: boolean;
318
324
  instances: CompactInstanceRecord[];
319
325
  bootstrapRegistrations: CompactBootstrapRegistrationRecord[];
320
326
  orphanBootstrapRegistrations: CompactBootstrapRegistrationRecord[];
@@ -366,6 +372,8 @@ declare class SponsorRelayController {
366
372
  setUcanStoreBootstrapField(field: keyof SponsorRelayUcanStoreBootstrapInput, value: string): void;
367
373
  setTierId(tierId: string): void;
368
374
  private recomputePricingSummary;
375
+ /** Pin a specific CRN as the first deploy attempt (null = automatic). */
376
+ selectCrn(hash: string | null): void;
369
377
  private queueManifestRefresh;
370
378
  connectWallet(): Promise<void>;
371
379
  private refreshWalletDerivedState;
package/react/index.js CHANGED
@@ -43,7 +43,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
43
43
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
44
44
 
45
45
  // src/shared/package-version.ts
46
- var UI_PACKAGE_VERSION = "0.6.45";
46
+ var UI_PACKAGE_VERSION = "0.6.46";
47
47
 
48
48
  // src/shared/format.ts
49
49
  function shortHash(value, head = 8, tail = 6) {
@@ -3826,6 +3826,8 @@ function defaultState(props = {}) {
3826
3826
  balance: null,
3827
3827
  crns: [],
3828
3828
  selectedCrn: null,
3829
+ crnOptions: [],
3830
+ crnPinnedByUser: false,
3829
3831
  instances: [],
3830
3832
  bootstrapRegistrations: [],
3831
3833
  orphanBootstrapRegistrations: [],
@@ -5257,15 +5259,26 @@ var SponsorRelayController = class {
5257
5259
  const balance = this.state.balance;
5258
5260
  const quote = pricing && tier && balance ? buildPaymentQuote(tier, pricing, balance) : null;
5259
5261
  const spec = pricing && tier ? tierSpec(pricing, tier) : null;
5260
- const selectedCrn = compatibleCrnsForTier(this.state.crns, {
5262
+ const compatibleList = compatibleCrnsForTier(this.state.crns, {
5261
5263
  ...this.state,
5262
5264
  pricingSummary: {
5263
5265
  ...this.state.pricingSummary,
5264
5266
  pricing,
5265
5267
  tier
5266
5268
  }
5267
- })[0] ?? null;
5269
+ });
5270
+ const pinned = this.state.crnPinnedByUser ? compatibleList.find(
5271
+ (crn) => crn.hash === this.state.selectedCrn?.hash
5272
+ ) ?? null : null;
5273
+ const selectedCrn = pinned ?? compatibleList[0] ?? null;
5274
+ const crnOptions = compatibleList.slice(0, 15).map((crn) => ({
5275
+ hash: crn.hash,
5276
+ name: crn.name ?? null,
5277
+ score: typeof crn.score === "number" ? crn.score : null
5278
+ }));
5268
5279
  this.patch({
5280
+ crnOptions,
5281
+ crnPinnedByUser: this.state.crnPinnedByUser && pinned != null,
5269
5282
  pricingSummary: {
5270
5283
  pricing,
5271
5284
  tier,
@@ -5278,6 +5291,17 @@ var SponsorRelayController = class {
5278
5291
  selectedCrn
5279
5292
  });
5280
5293
  }
5294
+ /** Pin a specific CRN as the first deploy attempt (null = automatic). */
5295
+ selectCrn(hash) {
5296
+ if (!hash) {
5297
+ this.patch({ crnPinnedByUser: false });
5298
+ this.recomputePricingSummary();
5299
+ return;
5300
+ }
5301
+ const match = this.state.crns.find((crn) => crn.hash === hash) ?? null;
5302
+ if (!match) return;
5303
+ this.patch({ selectedCrn: match, crnPinnedByUser: true });
5304
+ }
5281
5305
  queueManifestRefresh() {
5282
5306
  if (!this.state.ready) {
5283
5307
  return;
@@ -7394,7 +7418,22 @@ function SponsorRelayFab(props) {
7394
7418
  " credits required"
7395
7419
  ] }),
7396
7420
  /* @__PURE__ */ jsx("div", { children: state.rootfsHealth.label }),
7397
- /* @__PURE__ */ jsx("div", { children: state.selectedCrn?.name ?? shortHash(state.selectedCrn?.hash) }),
7421
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
7422
+ "select",
7423
+ {
7424
+ "aria-label": "Select CRN",
7425
+ value: state.crnPinnedByUser ? state.selectedCrn?.hash ?? "" : "",
7426
+ onChange: (event) => controller.selectCrn(event.currentTarget.value || null),
7427
+ children: [
7428
+ /* @__PURE__ */ jsxs("option", { value: "", children: [
7429
+ "Auto (",
7430
+ state.crnOptions[0]?.name ?? "best score",
7431
+ ")"
7432
+ ] }),
7433
+ state.crnOptions.map((option) => /* @__PURE__ */ jsx("option", { value: option.hash, children: (option.name ?? option.hash.slice(0, 8)) + (option.score != null ? ` \xB7 ${option.score.toFixed(2)}` : "") }, option.hash))
7434
+ ]
7435
+ }
7436
+ ) }),
7398
7437
  /* @__PURE__ */ jsxs("div", { children: [
7399
7438
  "Ports",
7400
7439
  " ",
package/shared/index.d.ts CHANGED
@@ -313,6 +313,12 @@ interface SponsorRelayState {
313
313
  balance: BalanceResponse | null;
314
314
  crns: Crn[];
315
315
  selectedCrn: Crn | null;
316
+ crnOptions: Array<{
317
+ hash: string;
318
+ name: string | null;
319
+ score: number | null;
320
+ }>;
321
+ crnPinnedByUser: boolean;
316
322
  instances: CompactInstanceRecord[];
317
323
  bootstrapRegistrations: CompactBootstrapRegistrationRecord[];
318
324
  orphanBootstrapRegistrations: CompactBootstrapRegistrationRecord[];
@@ -341,7 +347,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
341
347
  declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
342
348
  declare const DEPLOYMENT_PENDING_WARNING_MS: number;
343
349
 
344
- declare const UI_PACKAGE_VERSION = "0.6.45";
350
+ declare const UI_PACKAGE_VERSION = "0.6.46";
345
351
 
346
352
  interface RootfsRequiredPortForward {
347
353
  port: number;
@@ -425,6 +431,8 @@ declare class SponsorRelayController {
425
431
  setUcanStoreBootstrapField(field: keyof SponsorRelayUcanStoreBootstrapInput, value: string): void;
426
432
  setTierId(tierId: string): void;
427
433
  private recomputePricingSummary;
434
+ /** Pin a specific CRN as the first deploy attempt (null = automatic). */
435
+ selectCrn(hash: string | null): void;
428
436
  private queueManifestRefresh;
429
437
  connectWallet(): Promise<void>;
430
438
  private refreshWalletDerivedState;
package/shared/index.js CHANGED
@@ -42,7 +42,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
42
42
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
43
43
 
44
44
  // src/shared/package-version.ts
45
- var UI_PACKAGE_VERSION = "0.6.45";
45
+ var UI_PACKAGE_VERSION = "0.6.46";
46
46
 
47
47
  // src/shared/format.ts
48
48
  function shortHash(value, head = 8, tail = 6) {
@@ -3825,6 +3825,8 @@ function defaultState(props = {}) {
3825
3825
  balance: null,
3826
3826
  crns: [],
3827
3827
  selectedCrn: null,
3828
+ crnOptions: [],
3829
+ crnPinnedByUser: false,
3828
3830
  instances: [],
3829
3831
  bootstrapRegistrations: [],
3830
3832
  orphanBootstrapRegistrations: [],
@@ -5256,15 +5258,26 @@ var SponsorRelayController = class {
5256
5258
  const balance = this.state.balance;
5257
5259
  const quote = pricing && tier && balance ? buildPaymentQuote(tier, pricing, balance) : null;
5258
5260
  const spec = pricing && tier ? tierSpec(pricing, tier) : null;
5259
- const selectedCrn = compatibleCrnsForTier(this.state.crns, {
5261
+ const compatibleList = compatibleCrnsForTier(this.state.crns, {
5260
5262
  ...this.state,
5261
5263
  pricingSummary: {
5262
5264
  ...this.state.pricingSummary,
5263
5265
  pricing,
5264
5266
  tier
5265
5267
  }
5266
- })[0] ?? null;
5268
+ });
5269
+ const pinned = this.state.crnPinnedByUser ? compatibleList.find(
5270
+ (crn) => crn.hash === this.state.selectedCrn?.hash
5271
+ ) ?? null : null;
5272
+ const selectedCrn = pinned ?? compatibleList[0] ?? null;
5273
+ const crnOptions = compatibleList.slice(0, 15).map((crn) => ({
5274
+ hash: crn.hash,
5275
+ name: crn.name ?? null,
5276
+ score: typeof crn.score === "number" ? crn.score : null
5277
+ }));
5267
5278
  this.patch({
5279
+ crnOptions,
5280
+ crnPinnedByUser: this.state.crnPinnedByUser && pinned != null,
5268
5281
  pricingSummary: {
5269
5282
  pricing,
5270
5283
  tier,
@@ -5277,6 +5290,17 @@ var SponsorRelayController = class {
5277
5290
  selectedCrn
5278
5291
  });
5279
5292
  }
5293
+ /** Pin a specific CRN as the first deploy attempt (null = automatic). */
5294
+ selectCrn(hash) {
5295
+ if (!hash) {
5296
+ this.patch({ crnPinnedByUser: false });
5297
+ this.recomputePricingSummary();
5298
+ return;
5299
+ }
5300
+ const match = this.state.crns.find((crn) => crn.hash === hash) ?? null;
5301
+ if (!match) return;
5302
+ this.patch({ selectedCrn: match, crnPinnedByUser: true });
5303
+ }
5280
5304
  queueManifestRefresh() {
5281
5305
  if (!this.state.ready) {
5282
5306
  return;
@@ -260,7 +260,19 @@ export let apiHosts = undefined
260
260
  </div>
261
261
  <div class="metric-card">
262
262
  <span>CRN</span>
263
- <strong>{state.selectedCrn?.name ?? shortHash(state.selectedCrn?.hash)}</strong>
263
+ <select
264
+ class="crn-select"
265
+ aria-label="Select CRN"
266
+ value={state.crnPinnedByUser ? (state.selectedCrn?.hash ?? '') : ''}
267
+ on:change={(event) => controller.selectCrn(event.currentTarget.value || null)}
268
+ >
269
+ <option value="">Auto ({state.crnOptions[0]?.name ?? 'best score'})</option>
270
+ {#each state.crnOptions as option (option.hash)}
271
+ <option value={option.hash}>
272
+ {option.name ?? option.hash.slice(0, 8)}{option.score != null ? ` · ${option.score.toFixed(2)}` : ''}
273
+ </option>
274
+ {/each}
275
+ </select>
264
276
  <small>{state.selectedCrn?.address ?? 'Auto-picked best compatible CRN'}</small>
265
277
  </div>
266
278
  <div class="metric-card">