@juspay/svelte-ui-components 2.136.10 → 2.136.11

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.
@@ -57,7 +57,8 @@ export type OptionalFunnelChartProperties = {
57
57
  aspectRatio?: number;
58
58
  /**
59
59
  * Upper bound (px) on the rendered chart height, so the aspect-ratio-derived height
60
- * can't balloon on wide surfaces. Defaults to `Infinity` (uncapped).
60
+ * can't balloon on wide surfaces. Defaults to `DEFAULT_CHART_MAX_HEIGHT` (420), the
61
+ * same cap every other chart in this library applies.
61
62
  */
62
63
  maxHeight?: number;
63
64
  /** Lower bound (px) on the rendered chart height (defaults to `0`). */
@@ -37,6 +37,107 @@
37
37
  transform: ((svg: string) => string) | null;
38
38
  };
39
39
 
40
+ // Root attributes that may be copied from fetched SVG markup onto the live
41
+ // <svg> host. The fetched document is remote, untrusted content — copying
42
+ // every attribute (the previous behaviour) let it plant executable `on*`
43
+ // handlers on an element in the host page, clobber the data-pw/testID test
44
+ // hooks, or override the component's CSS sizing contract with an inline
45
+ // style. An allowlist rather than an `on*` denylist is deliberate: a
46
+ // denylist misses vectors like `xlink:href="javascript:…"` and whatever
47
+ // attribute ships in browsers next. The names kept are what inlining
48
+ // actually needs — geometry/scaling, the namespace declarations exporters
49
+ // emit, the inheritable paint attributes that keep the icon's authored
50
+ // defaults while page CSS/currentColor themes it, and the accessibility
51
+ // metadata real icon sets ship (role, focusable, aria-*). `class` stays
52
+ // caller-owned via the `classes` prop, as before. Compared lowercased, so
53
+ // entries are lowercase (viewBox → 'viewbox') while the authored casing is
54
+ // preserved when the attribute is written to the host.
55
+ const SAFE_INLINE_ROOT_ATTRIBUTES: ReadonlySet<string> = new Set([
56
+ 'xmlns',
57
+ 'xmlns:xlink',
58
+ 'viewbox',
59
+ 'width',
60
+ 'height',
61
+ 'x',
62
+ 'y',
63
+ 'preserveaspectratio',
64
+ 'fill',
65
+ 'fill-opacity',
66
+ 'fill-rule',
67
+ 'stroke',
68
+ 'stroke-width',
69
+ 'stroke-opacity',
70
+ 'stroke-linecap',
71
+ 'stroke-linejoin',
72
+ 'stroke-miterlimit',
73
+ 'stroke-dasharray',
74
+ 'stroke-dashoffset',
75
+ 'clip-rule',
76
+ 'color',
77
+ 'opacity',
78
+ 'overflow',
79
+ 'role',
80
+ 'focusable'
81
+ ]);
82
+
83
+ function isSafeInlineRootAttribute(lowerCaseName: string): boolean {
84
+ return SAFE_INLINE_ROOT_ATTRIBUTES.has(lowerCaseName) || lowerCaseName.startsWith('aria-');
85
+ }
86
+
87
+ /**
88
+ * Strips executable content from a fetched SVG's descendants.
89
+ *
90
+ * The root allowlist above only guards the root. Children are adopted into
91
+ * the live document wholesale, and an event-handler content attribute
92
+ * becomes a live handler the moment its element is adopted — so
93
+ * `<image onerror="…">` two levels down runs exactly like `onerror` on the
94
+ * root would. A root-only guard would look like a fix while leaving the same
95
+ * vector open one element deeper.
96
+ *
97
+ * A denylist rather than an allowlist here, deliberately: descendants
98
+ * legitimately carry the entire SVG geometry and paint vocabulary (`d`,
99
+ * `transform`, `gradientUnits`, …), so enumerating what is permitted would
100
+ * break real artwork. What is dangerous is narrow and well understood:
101
+ * scripting elements, `on*` handlers, and URL attributes pointing at
102
+ * `javascript:`.
103
+ */
104
+ function sanitizeInlinedSubtree(root: SVGSVGElement): void {
105
+ for (const element of Array.from(root.querySelectorAll('script, foreignObject'))) {
106
+ element.remove();
107
+ }
108
+ for (const element of Array.from(root.querySelectorAll('*'))) {
109
+ for (const attribute of Array.from(element.attributes)) {
110
+ const name = attribute.name.toLowerCase();
111
+ if (name.startsWith('on')) {
112
+ element.removeAttribute(attribute.name);
113
+ continue;
114
+ }
115
+ // `href`, `xlink:href` and `src` accept a javascript: URL, which runs
116
+ // on activation of an <a> wrapper or on load of a nested resource.
117
+ const isUrlAttribute = name === 'href' || name === 'xlink:href' || name === 'src';
118
+ if (isUrlAttribute && /^\s*javascript:/i.test(attribute.value)) {
119
+ element.removeAttribute(attribute.name);
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ // Root attribute names of the raw fetched markup, lowercased — or null when
126
+ // that markup does not parse as SVG on its own. Distinguishes what arrived
127
+ // over the network (untrusted, the allowlist applies) from what the caller's
128
+ // transformSvg hook added (caller intent, passes through).
129
+ function collectRootAttributeNames(markup: string): ReadonlySet<string> | null {
130
+ const parsed = new DOMParser().parseFromString(markup, 'image/svg+xml');
131
+ if (parsed.querySelector('parsererror') !== null) {
132
+ return null;
133
+ }
134
+ const root = parsed.querySelector('svg');
135
+ if (root === null) {
136
+ return null;
137
+ }
138
+ return new Set(Array.from(root.attributes, (attribute) => attribute.name.toLowerCase()));
139
+ }
140
+
40
141
  async function loadInlineSvg(
41
142
  host: SVGSVGElement,
42
143
  url: string,
@@ -50,7 +151,8 @@
50
151
  return;
51
152
  }
52
153
  const rawSvg = await response.text();
53
- const markup = typeof transform === 'function' ? transform(rawSvg) : rawSvg;
154
+ const hasTransform = typeof transform === 'function';
155
+ const markup = hasTransform ? transform(rawSvg) : rawSvg;
54
156
  const parsed = new DOMParser().parseFromString(markup, 'image/svg+xml');
55
157
  if (parsed.querySelector('parsererror') !== null) {
56
158
  failedInlineSrc = url;
@@ -70,12 +172,26 @@
70
172
  while (host.firstChild !== null) {
71
173
  host.removeChild(host.firstChild);
72
174
  }
175
+ // With no transform the parsed root IS the fetched root, so every name
176
+ // is network-supplied and only the allowlist applies. With a transform,
177
+ // names absent from the raw payload were added by the caller's own hook
178
+ // and pass through; if the raw payload only parses after the transform,
179
+ // nothing can be attributed to the caller and the allowlist applies to
180
+ // everything.
181
+ const fetchedRootNames = hasTransform ? collectRootAttributeNames(rawSvg) : null;
73
182
  for (const attribute of Array.from(sourceSvg.attributes)) {
74
- if (attribute.name === 'class') {
183
+ const name = attribute.name.toLowerCase();
184
+ if (name === 'class') {
75
185
  continue;
76
186
  }
77
- host.setAttribute(attribute.name, attribute.value);
187
+ const addedByTransform = fetchedRootNames !== null && !fetchedRootNames.has(name);
188
+ if (isSafeInlineRootAttribute(name) || addedByTransform) {
189
+ host.setAttribute(attribute.name, attribute.value);
190
+ }
78
191
  }
192
+ // Before adoption, not after: an event-handler attribute becomes a live
193
+ // handler as soon as its element enters the document.
194
+ sanitizeInlinedSubtree(sourceSvg);
79
195
  while (sourceSvg.firstChild !== null) {
80
196
  host.appendChild(sourceSvg.firstChild);
81
197
  }
package/dist-wc/index.js CHANGED
@@ -3477,7 +3477,7 @@ function create_custom_element(e, t, n, i, a, o) {
3477
3477
  }
3478
3478
  //#endregion
3479
3479
  //#region src/lib/Img/Img.svelte
3480
- var root$88 = /* @__PURE__ */ from_svg("<svg></svg>"), root_1$75 = /* @__PURE__ */ from_html("<img/>"), $$css$85 = {
3480
+ var root_1$75 = /* @__PURE__ */ from_svg("<svg></svg>"), root_2$57 = /* @__PURE__ */ from_html("<img/>"), $$css$85 = {
3481
3481
  hash: "svelte-13ogpty",
3482
3482
  code: "img.svelte-13ogpty,\n svg.svelte-13ogpty {object-fit:var(--image-object-fit);height:var(--image-height, 24px);width:var(--image-width, 24px);padding:var(--image-padding, 0px);border-radius:var(--image-border-radius, 0px);margin:var(--image-margin, 0px);filter:var(--image-filter, none);background:var(--image-background);border:var(--image-border);transition:var(--image-transition);}img.svelte-13ogpty:hover,\n svg.svelte-13ogpty:hover {background:var(--image-hover-background, var(--image-background));border:var(--image-hover-border, var(--image-border));}"
3483
3483
  };
@@ -3491,35 +3491,88 @@ function Img(e, t) {
3491
3491
  function C() {
3492
3492
  typeof a() == "string" && a().length > 0 && get(f) !== a() ? set(f, a()) : o()?.();
3493
3493
  }
3494
- async function k(e, t, n, i) {
3494
+ let k = new Set([
3495
+ "xmlns",
3496
+ "xmlns:xlink",
3497
+ "viewbox",
3498
+ "width",
3499
+ "height",
3500
+ "x",
3501
+ "y",
3502
+ "preserveaspectratio",
3503
+ "fill",
3504
+ "fill-opacity",
3505
+ "fill-rule",
3506
+ "stroke",
3507
+ "stroke-width",
3508
+ "stroke-opacity",
3509
+ "stroke-linecap",
3510
+ "stroke-linejoin",
3511
+ "stroke-miterlimit",
3512
+ "stroke-dasharray",
3513
+ "stroke-dashoffset",
3514
+ "clip-rule",
3515
+ "color",
3516
+ "opacity",
3517
+ "overflow",
3518
+ "role",
3519
+ "focusable"
3520
+ ]);
3521
+ function R(e) {
3522
+ return k.has(e) || e.startsWith("aria-");
3523
+ }
3524
+ function G(e) {
3525
+ for (let t of Array.from(e.querySelectorAll("script, foreignObject"))) t.remove();
3526
+ for (let t of Array.from(e.querySelectorAll("*"))) for (let e of Array.from(t.attributes)) {
3527
+ let n = e.name.toLowerCase();
3528
+ if (n.startsWith("on")) {
3529
+ t.removeAttribute(e.name);
3530
+ continue;
3531
+ }
3532
+ (n === "href" || n === "xlink:href" || n === "src") && /^\s*javascript:/i.test(e.value) && t.removeAttribute(e.name);
3533
+ }
3534
+ }
3535
+ function te(e) {
3536
+ let t = new DOMParser().parseFromString(e, "image/svg+xml");
3537
+ if (t.querySelector("parsererror") !== null) return null;
3538
+ let n = t.querySelector("svg");
3539
+ return n === null ? null : new Set(Array.from(n.attributes, (e) => e.name.toLowerCase()));
3540
+ }
3541
+ async function ne(e, t, n, i) {
3495
3542
  try {
3496
3543
  let a = await fetch(t, { signal: i });
3497
3544
  if (!a.ok) {
3498
3545
  set(p, t, !0);
3499
3546
  return;
3500
3547
  }
3501
- let o = await a.text(), s = typeof n == "function" ? n(o) : o, c = new DOMParser().parseFromString(s, "image/svg+xml");
3502
- if (c.querySelector("parsererror") !== null) {
3548
+ let o = await a.text(), s = typeof n == "function", c = s ? n(o) : o, l = new DOMParser().parseFromString(c, "image/svg+xml");
3549
+ if (l.querySelector("parsererror") !== null) {
3503
3550
  set(p, t, !0);
3504
3551
  return;
3505
3552
  }
3506
- let l = c.querySelector("svg");
3507
- if (l === null) {
3553
+ let u = l.querySelector("svg");
3554
+ if (u === null) {
3508
3555
  set(p, t, !0);
3509
3556
  return;
3510
3557
  }
3511
3558
  if (i.aborted) return;
3512
3559
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
3513
- for (let t of Array.from(l.attributes)) t.name !== "class" && e.setAttribute(t.name, t.value);
3514
- for (; l.firstChild !== null;) e.appendChild(l.firstChild);
3560
+ let f = s ? te(o) : null;
3561
+ for (let t of Array.from(u.attributes)) {
3562
+ let n = t.name.toLowerCase();
3563
+ if (n === "class") continue;
3564
+ let i = f !== null && !f.has(n);
3565
+ (R(n) || i) && e.setAttribute(t.name, t.value);
3566
+ }
3567
+ for (G(u); u.firstChild !== null;) e.appendChild(u.firstChild);
3515
3568
  } catch {
3516
3569
  i.aborted || set(p, t, !0);
3517
3570
  }
3518
3571
  }
3519
- function R(e, t) {
3572
+ function re(e, t) {
3520
3573
  let n = new AbortController();
3521
3574
  function i(t) {
3522
- n.abort(), n = new AbortController(), k(e, t.url, t.transform, n.signal);
3575
+ n.abort(), n = new AbortController(), ne(e, t.url, t.transform, n.signal);
3523
3576
  }
3524
3577
  return i(t), {
3525
3578
  update(e) {
@@ -3530,7 +3583,7 @@ function Img(e, t) {
3530
3583
  }
3531
3584
  };
3532
3585
  }
3533
- var G = {
3586
+ var be = {
3534
3587
  get src() {
3535
3588
  return n();
3536
3589
  },
@@ -3579,23 +3632,23 @@ function Img(e, t) {
3579
3632
  set testId(e) {
3580
3633
  u(e), flushSync();
3581
3634
  }
3582
- }, te = comment(), ne = first_child(te), re = (e) => {
3583
- var t = root$88();
3584
- action(t, (e, t) => R?.(e, t), () => ({
3635
+ }, Me = comment(), Re = first_child(Me), Ue = (e) => {
3636
+ var t = root_1$75();
3637
+ action(t, (e, t) => re?.(e, t), () => ({
3585
3638
  url: get(f),
3586
3639
  transform: l() ?? null
3587
3640
  })), template_effect(() => {
3588
3641
  set_class(t, 0, clsx(s() ?? ""), "svelte-13ogpty"), set_attribute(t, "role", i().length > 0 ? "img" : null), set_attribute(t, "aria-label", i().length > 0 ? i() : null), set_attribute(t, "aria-hidden", i().length === 0 ? "true" : null), set_attribute(t, "data-pw", u()), set_attribute(t, "testID", u());
3589
3642
  }), append(e, t);
3590
- }, be = (e) => {
3591
- var t = root_1$75();
3643
+ }, it = (e) => {
3644
+ var t = root_2$57();
3592
3645
  template_effect(() => {
3593
3646
  set_class(t, 1, clsx(s() ?? ""), "svelte-13ogpty"), set_attribute(t, "src", get(f)), set_attribute(t, "alt", i()), set_attribute(t, "data-pw", u()), set_attribute(t, "testid", u());
3594
3647
  }), event("error", t, C), replay_events(t), append(e, t);
3595
3648
  };
3596
- return if_block(ne, (e) => {
3597
- get(S) ? e(re) : e(be, -1);
3598
- }), append(e, te), pop(G);
3649
+ return if_block(Re, (e) => {
3650
+ get(S) ? e(Ue) : e(it, -1);
3651
+ }), append(e, Me), pop(be);
3599
3652
  }
3600
3653
  create_custom_element(Img, {
3601
3654
  src: {},
@@ -12723,6 +12776,11 @@ customElements.define("sui-choicebox", create_custom_element(Choicebox_wc, {
12723
12776
  reflect: !0,
12724
12777
  type: "Boolean"
12725
12778
  },
12779
+ showIndicator: {
12780
+ attribute: "show-indicator",
12781
+ reflect: !0,
12782
+ type: "Boolean"
12783
+ },
12726
12784
  testId: {
12727
12785
  attribute: "test-id",
12728
12786
  type: "String"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.136.10",
3
+ "version": "2.136.11",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",