@juspay/svelte-ui-components 2.119.0 → 2.120.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.
@@ -128,6 +128,7 @@
128
128
  .container {
129
129
  display: flex;
130
130
  flex-direction: column;
131
+ width: var(--input-button-container-width, auto);
131
132
  margin: var(--input-button-container-margin);
132
133
  }
133
134
 
@@ -1,16 +1,54 @@
1
1
  <script lang="ts">
2
2
  import type { ProgressProperties } from './properties';
3
3
 
4
- let { value, max = 100, showLabel = false, testId, classes }: ProgressProperties = $props();
4
+ let {
5
+ value,
6
+ max = 100,
7
+ showLabel = false,
8
+ ariaLabel,
9
+ testId,
10
+ classes
11
+ }: ProgressProperties = $props();
5
12
 
6
- let percentage = $derived(Math.min(100, Math.max(0, (value / max) * 100)));
13
+ // `max` has to be a finite positive number for a percentage to mean
14
+ // anything. A zero, negative, or non-finite max (an as-yet-unloaded total,
15
+ // say) would make (value / max) NaN or Infinity and put "NaN" into
16
+ // aria-valuenow, which is not a valid ARIA value -- and a non-finite value
17
+ // has the same effect. Treat an unusable range as an empty (0%) bar
18
+ // instead. `value` is guarded here too, not just `max`: a NaN value isn't
19
+ // `< 0`, so it would otherwise slip past the isIndeterminate check below
20
+ // and hit the same NaN-percentage path. This check is deliberately kept
21
+ // independent of `isIndeterminate` below -- a negative `value` (e.g. -1)
22
+ // still signals indeterminate on its own, even paired with an invalid
23
+ // `max`, since indeterminate mode never reads `percentage` in the markup.
24
+ let hasValidRange = $derived(Number.isFinite(value) && Number.isFinite(max) && max > 0);
25
+ let percentage = $derived(hasValidRange ? Math.min(100, Math.max(0, (value / max) * 100)) : 0);
7
26
  let isIndeterminate = $derived(value < 0);
27
+ // Rounded to 2 decimal places rather than the nearest whole number, so
28
+ // aria-valuenow stays effectively in step with the bar's raw fractional
29
+ // width (matching Gauge's convention of tying aria-valuenow to the raw
30
+ // computed value, not the rounded display text). Full raw precision isn't
31
+ // used because (value / max) * 100 can land on binary floating-point noise
32
+ // like 55.00000000000001 -- rounding to 2 decimals clears that while still
33
+ // keeping the value far closer to the bar's true width than whole numbers.
34
+ let preciseValueNow = $derived(Math.round(percentage * 100) / 100);
35
+ // Shared by the visible label and the aria-label fallback, mirroring
36
+ // Gauge's labelText convention. "Loading" matches the aria-label
37
+ // LoadingDots already uses for its own indeterminate role="status" element.
38
+ let labelText = $derived(isIndeterminate ? 'Loading' : `${Math.round(percentage)}%`);
8
39
  </script>
9
40
 
10
41
  <div
11
42
  class="container {classes ?? ''}"
12
43
  data-pw={typeof testId === 'string' ? testId : null}
13
44
  testID={typeof testId === 'string' ? testId : null}
45
+ role="progressbar"
46
+ aria-valuenow={isIndeterminate ? null : preciseValueNow}
47
+ aria-valuemin={0}
48
+ aria-valuemax={100}
49
+ aria-valuetext={isIndeterminate ? 'indeterminate' : null}
50
+ aria-busy={isIndeterminate ? true : null}
51
+ aria-label={ariaLabel ?? labelText}
14
52
  >
15
53
  <div class="track">
16
54
  <div
@@ -20,7 +58,7 @@
20
58
  ></div>
21
59
  </div>
22
60
  {#if showLabel && !isIndeterminate}
23
- <div class="label">{Math.round(percentage)}%</div>
61
+ <div class="label">{labelText}</div>
24
62
  {/if}
25
63
  </div>
26
64
 
@@ -3,8 +3,23 @@ export type MandatoryProgressProperties = {
3
3
  value: number;
4
4
  };
5
5
  export type OptionalProgressProperties = {
6
+ /**
7
+ * The maximum value representing 100% completion. Must be a finite,
8
+ * positive number for the percentage to be meaningful. A zero, negative,
9
+ * or non-finite `max` (and likewise a non-finite `value`) is treated as an
10
+ * invalid range: the bar renders at 0% rather than propagating `NaN` into
11
+ * `aria-valuenow` and the percentage fallback text below.
12
+ */
6
13
  max?: number;
7
14
  showLabel?: boolean;
15
+ /**
16
+ * Accessible label for the progress element (`role="progressbar"`). Falls
17
+ * back to the computed percentage text (e.g. `"75%"`) when determinate, or
18
+ * `"Loading"` when indeterminate, so assistive technology always announces
19
+ * a name by default. For an invalid `value`/`max` range (see `max`), the
20
+ * fallback reads `"0%"`.
21
+ */
22
+ ariaLabel?: string;
8
23
  testId?: string;
9
24
  classes?: string;
10
25
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.119.0",
3
+ "version": "2.120.1",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",