@marianmeres/stuic 2.9.0 → 2.10.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.
@@ -24,13 +24,13 @@
24
24
 
25
25
  let container: HTMLDivElement = $state()!;
26
26
 
27
+ // Note: completeness and rotate are NOT included here - they're updated via setters
28
+ // to avoid recreating the SVG on every change
27
29
  let circle = $derived(
28
30
  svgCircle({
29
31
  strokeWidth,
30
- completeness,
31
32
  bgStrokeColor,
32
33
  roundedEdges,
33
- rotate,
34
34
  strokeWidthRatio,
35
35
  class: circleClass,
36
36
  circleStyle:
@@ -43,6 +43,9 @@
43
43
 
44
44
  $effect(() => {
45
45
  container.appendChild(circle.svg);
46
+ return () => {
47
+ circle.svg.remove();
48
+ };
46
49
  });
47
50
 
48
51
  $effect(() => {
@@ -174,6 +174,7 @@
174
174
  ) => Promise<FieldAssetWithBlobUrl[]>;
175
175
  withOnProgress?: boolean;
176
176
  classControls?: string;
177
+ isLoading?: boolean;
177
178
  }
178
179
  </script>
179
180
 
@@ -231,6 +232,7 @@
231
232
  processAssets,
232
233
  withOnProgress,
233
234
  classControls = "",
235
+ isLoading = false,
234
236
  parseValue = (strigifiedModels: string) => {
235
237
  const val = strigifiedModels ?? "[]";
236
238
  try {
@@ -261,7 +263,7 @@
261
263
  // otherwise normal spinner will be shown
262
264
  let progress = $state<Record<string, number>>({});
263
265
  const onProgress = (id: string, value: number) => (progress[id] = Math.round(value));
264
- $inspect("progress", progress);
266
+ // $inspect("progress", progress);
265
267
 
266
268
  $effect(() => {
267
269
  if (!assets?.length) modal?.close?.();
@@ -280,7 +282,8 @@
280
282
  // return value and uses it directly as the error message.
281
283
 
282
284
  if (required && !assets.length) return t("field_req_att");
283
- if (assets.length > cardinality) return t("cardinality_reached", { max: cardinality });
285
+ if (assets.length > cardinality)
286
+ return t("cardinality_reached", { max: cardinality });
284
287
 
285
288
  // normally, with other fieldtypes, we would continue with provided validator:
286
289
  // return (validate as any)?.customValidator?.(value, context, el) || "";
@@ -369,72 +372,78 @@
369
372
  />
370
373
 
371
374
  {#snippet default_render()}
372
- <div class={["p-2 flex items-center gap-0.5 flex-wrap"]}>
373
- {#each assets as asset, idx}
374
- {@const { thumb, full, original } = asset_urls(asset)}
375
- {@const _is_img = isImage(asset.type ?? thumb)}
376
- <div class="relative group">
377
- <button
378
- class={[objectSize, "bg-black/10 grid place-content-center", classControls]}
379
- onclick={(e) => {
380
- e.stopPropagation();
381
- e.preventDefault();
382
- previewIdx = idx;
383
- modal.open();
384
- }}
385
- type="button"
386
- >
387
- {#if _is_img}
388
- <img
389
- src={thumb}
390
- alt={asset.name}
391
- class={[objectSize, objectFitStyle, "hover:saturate-150"]}
392
- />
393
- {:else}
394
- {@html getAssetIcon((asset.name ?? "").split(".").at(-1))({
395
- size: 32,
396
- class: "mx-auto",
397
- })}
398
- {/if}
399
- <span
400
- class="absolute bottom-1 left-1 right-1 grid bg-white/50 rounded"
401
- use:tooltip={() => ({ content: asset.name })}
375
+ {#if isLoading}
376
+ <div class="p-2 pl-8 flex items-center justify-center min-h-24">
377
+ <SpinnerCircle />
378
+ </div>
379
+ {:else}
380
+ <div class={["p-2 flex items-center gap-0.5 flex-wrap"]}>
381
+ {#each assets as asset, idx}
382
+ {@const { thumb, full, original } = asset_urls(asset)}
383
+ {@const _is_img = isImage(asset.type ?? thumb)}
384
+ <div class="relative group">
385
+ <button
386
+ class={[objectSize, "bg-black/10 grid place-content-center", classControls]}
387
+ onclick={(e) => {
388
+ e.stopPropagation();
389
+ e.preventDefault();
390
+ previewIdx = idx;
391
+ modal.open();
392
+ }}
393
+ type="button"
402
394
  >
403
- <span class="truncate px-2 text-xs">{asset.name}</span>
404
- </span>
405
-
406
- {#if asset.meta?.isUploading}
395
+ {#if _is_img}
396
+ <img
397
+ src={thumb}
398
+ alt={asset.name}
399
+ class={[objectSize, objectFitStyle, "hover:saturate-150"]}
400
+ />
401
+ {:else}
402
+ {@html getAssetIcon((asset.name ?? "").split(".").at(-1))({
403
+ size: 32,
404
+ class: "mx-auto",
405
+ })}
406
+ {/if}
407
407
  <span
408
- class="absolute inset-0 grid place-content-center pointer-events-none text-white"
408
+ class="absolute bottom-1 left-1 right-1 grid bg-white/50 rounded"
409
+ use:tooltip={() => ({ content: asset.name })}
409
410
  >
410
- {#if withOnProgress}
411
- <Circle
412
- class="text-white"
413
- animateCompletenessMs={300}
414
- bgStrokeColor="rgba(0 0 0 / 0.2)"
415
- completeness={progress[asset.id] / 100}
416
- rotate={-90}
417
- />
418
- {:else}
419
- <SpinnerCircle bgStrokeColor="gray" />
420
- {/if}
411
+ <span class="truncate px-2 text-xs">{asset.name}</span>
421
412
  </span>
422
- {/if}
423
- </button>
424
- </div>
425
- {/each}
426
- <button
427
- type="button"
428
- onclick={(e) => {
429
- e.preventDefault();
430
- e.stopPropagation();
431
- inputEl.click();
432
- }}
433
- class={[objectSize, " grid place-content-center group", classControls]}
434
- >
435
- {@html iconAdd({ size: 32, class: "opacity-75 group-hover:opacity-100" })}
436
- </button>
437
- </div>
413
+
414
+ {#if asset.meta?.isUploading}
415
+ <span
416
+ class="absolute inset-0 grid place-content-center pointer-events-none text-white"
417
+ >
418
+ {#if withOnProgress}
419
+ <Circle
420
+ class="text-white"
421
+ animateCompletenessMs={300}
422
+ bgStrokeColor="rgba(0 0 0 / 0.2)"
423
+ completeness={progress[asset.id] / 100}
424
+ rotate={-90}
425
+ />
426
+ {:else}
427
+ <SpinnerCircle bgStrokeColor="gray" />
428
+ {/if}
429
+ </span>
430
+ {/if}
431
+ </button>
432
+ </div>
433
+ {/each}
434
+ <button
435
+ type="button"
436
+ onclick={(e) => {
437
+ e.preventDefault();
438
+ e.stopPropagation();
439
+ inputEl.click();
440
+ }}
441
+ class={[objectSize, " grid place-content-center group", classControls]}
442
+ >
443
+ {@html iconAdd({ size: 32, class: "opacity-75 group-hover:opacity-100" })}
444
+ </button>
445
+ </div>
446
+ {/if}
438
447
  {/snippet}
439
448
 
440
449
  <div
@@ -64,6 +64,7 @@ export interface Props extends Record<string, any> {
64
64
  processAssets?: (assets: FieldAsset[], onProgress?: (blobUrl: string, progress: number) => any) => Promise<FieldAssetWithBlobUrl[]>;
65
65
  withOnProgress?: boolean;
66
66
  classControls?: string;
67
+ isLoading?: boolean;
67
68
  }
68
69
  declare const FieldAssets: import("svelte").Component<Props, {}, "value">;
69
70
  type FieldAssets = ReturnType<typeof FieldAssets>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "2.9.0",
3
+ "version": "2.10.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",