@truenas/ui-components 0.7.13 → 0.7.14

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.
@@ -3746,8 +3746,22 @@ const defaultSpriteConfigPath = `${defaultSpriteBasePath}/sprite-config.json`;
3746
3746
  */
3747
3747
  class TnSpriteLoaderService {
3748
3748
  spriteConfig;
3749
- spriteLoaded = false;
3750
3749
  spriteLoadPromise;
3750
+ /**
3751
+ * A signal rather than a plain field, because the fetch below starts from the
3752
+ * constructor and lands whenever it lands: anything that resolves an icon
3753
+ * before it does gets a miss, and needs to be told when to ask again (#341).
3754
+ */
3755
+ spriteLoadedState = signal(false, ...(ngDevMode ? [{ debugName: "spriteLoadedState" }] : []));
3756
+ /**
3757
+ * Whether the sprite config has loaded, as a signal — read it inside a
3758
+ * `computed`/`effect` to re-resolve when the sprite arrives.
3759
+ *
3760
+ * `isSpriteLoaded()` reads the same state, so a caller that just wants the
3761
+ * current value needs nothing from here; this is for a caller that wants to
3762
+ * react to it changing.
3763
+ */
3764
+ spriteLoaded = this.spriteLoadedState.asReadonly();
3751
3765
  http = inject(HttpClient);
3752
3766
  sanitizer = inject(DomSanitizer);
3753
3767
  constructor() {
@@ -3764,8 +3778,10 @@ class TnSpriteLoaderService {
3764
3778
  this.spriteLoadPromise = (async () => {
3765
3779
  try {
3766
3780
  const config = await firstValueFrom(this.http.get(defaultSpriteConfigPath));
3781
+ // Config first, then the flag: a reader woken by the signal below goes
3782
+ // straight to `getIconUrl`, which needs the config already there.
3767
3783
  this.spriteConfig = config;
3768
- this.spriteLoaded = true;
3784
+ this.spriteLoadedState.set(true);
3769
3785
  }
3770
3786
  catch (error) {
3771
3787
  console.error('[TnSpriteLoader] Failed to load sprite config. Icons may not work:', error);
@@ -3778,7 +3794,7 @@ class TnSpriteLoaderService {
3778
3794
  */
3779
3795
  async ensureSpriteLoaded() {
3780
3796
  await this.loadSpriteConfig();
3781
- return this.spriteLoaded;
3797
+ return this.spriteLoadedState();
3782
3798
  }
3783
3799
  /**
3784
3800
  * Get the full URL for an icon in the sprite
@@ -3815,10 +3831,14 @@ class TnSpriteLoaderService {
3815
3831
  return this.sanitizer.bypassSecurityTrustResourceUrl(url);
3816
3832
  }
3817
3833
  /**
3818
- * Check if the sprite is loaded
3834
+ * Check if the sprite is loaded.
3835
+ *
3836
+ * Reads the `spriteLoaded` signal, so a call made from inside a `computed` or
3837
+ * an `effect` is tracked and that consumer re-runs when the sprite arrives —
3838
+ * which is how an icon resolved too early gets a second chance (#341).
3819
3839
  */
3820
3840
  isSpriteLoaded() {
3821
- return this.spriteLoaded;
3841
+ return this.spriteLoadedState();
3822
3842
  }
3823
3843
  /**
3824
3844
  * Get the sprite config if loaded