@juspay/svelte-ui-components 2.118.1 → 2.120.0
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/dist/Card/Card.svelte
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
classes,
|
|
9
9
|
testId,
|
|
10
10
|
onclick,
|
|
11
|
+
href,
|
|
12
|
+
target,
|
|
13
|
+
rel,
|
|
11
14
|
headerRight,
|
|
12
15
|
footer,
|
|
13
16
|
stretch = false,
|
|
@@ -15,7 +18,14 @@
|
|
|
15
18
|
cssVars
|
|
16
19
|
}: CardProperties = $props();
|
|
17
20
|
|
|
18
|
-
const
|
|
21
|
+
const isAnchor = $derived(typeof href === 'string' && href.length > 0);
|
|
22
|
+
const isInteractive = $derived(isAnchor || typeof onclick === 'function');
|
|
23
|
+
// HTML target values are ASCII case-insensitive (e.g. "_BLANK" opens a new
|
|
24
|
+
// context identically to "_blank"), so the comparison must normalize case
|
|
25
|
+
// to keep the noopener/noreferrer default from being silently skipped.
|
|
26
|
+
const resolvedRel = $derived(
|
|
27
|
+
rel ?? (target?.toLowerCase() === '_blank' ? 'noopener noreferrer' : null)
|
|
28
|
+
);
|
|
19
29
|
|
|
20
30
|
const styleAttr = $derived(
|
|
21
31
|
cssVars
|
|
@@ -37,8 +47,8 @@
|
|
|
37
47
|
};
|
|
38
48
|
</script>
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
<svelte:element
|
|
51
|
+
this={isAnchor ? 'a' : 'div'}
|
|
42
52
|
class="card {classes ?? ''}"
|
|
43
53
|
class:card-interactive={isInteractive}
|
|
44
54
|
class:card-stretch={stretch}
|
|
@@ -46,10 +56,13 @@
|
|
|
46
56
|
style={styleAttr}
|
|
47
57
|
data-pw={typeof testId === 'string' ? testId : null}
|
|
48
58
|
testID={typeof testId === 'string' ? testId : null}
|
|
49
|
-
role={isInteractive ? 'button' : null}
|
|
50
|
-
tabindex={isInteractive ? 0 : null}
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
role={!isAnchor && isInteractive ? 'button' : null}
|
|
60
|
+
tabindex={!isAnchor && isInteractive ? 0 : null}
|
|
61
|
+
href={isAnchor ? href : null}
|
|
62
|
+
target={isAnchor ? target : null}
|
|
63
|
+
rel={isAnchor ? resolvedRel : null}
|
|
64
|
+
onclick={onclick ?? null}
|
|
65
|
+
onkeydown={!isAnchor && isInteractive ? handleKeydown : null}
|
|
53
66
|
>
|
|
54
67
|
{#if (typeof title === 'string' && title.length > 0) || typeof headerRight === 'function'}
|
|
55
68
|
<div class="card-header" class:card-header-split={typeof headerRight === 'function'}>
|
|
@@ -85,10 +98,16 @@
|
|
|
85
98
|
{@render footer()}
|
|
86
99
|
</footer>
|
|
87
100
|
{/if}
|
|
88
|
-
</
|
|
101
|
+
</svelte:element>
|
|
89
102
|
|
|
90
103
|
<style>
|
|
91
104
|
.card {
|
|
105
|
+
/* Explicit so the root's layout doesn't depend on the browser default for
|
|
106
|
+
whichever tag svelte:element renders -- a <div> defaults to block and an
|
|
107
|
+
<a> defaults to inline, and an inline box ignores width/height entirely.
|
|
108
|
+
Pinning both here keeps anchor-mode cards byte-identical to div cards. */
|
|
109
|
+
display: block;
|
|
110
|
+
text-decoration: none;
|
|
92
111
|
background: var(--card-background, inherit);
|
|
93
112
|
border: var(--card-border, 1px solid currentColor);
|
|
94
113
|
border-radius: var(--card-border-radius, var(--radius, 4px));
|
|
@@ -12,12 +12,28 @@ export type OptionalCardProperties = {
|
|
|
12
12
|
/** Renders as `data-pw` on the root element for Playwright test selection. */
|
|
13
13
|
testId?: string;
|
|
14
14
|
/**
|
|
15
|
-
* When provided the root element becomes interactive
|
|
15
|
+
* When provided (and `href` is not) the root element becomes an interactive `<div>`:
|
|
16
16
|
* `role="button"`, `tabindex=0`, and keydown (Enter/Space) triggers the handler.
|
|
17
|
-
* When
|
|
18
|
-
*
|
|
17
|
+
* When `href` is also provided, the root renders as a native `<a>` instead (see
|
|
18
|
+
* `href`) and this synthetic role/tabindex/keydown shim is skipped, since anchor
|
|
19
|
+
* semantics already cover focus and Enter-activation; `onclick` still fires either
|
|
20
|
+
* way. When neither `onclick` nor `href` is provided the root is a plain `<div>`
|
|
21
|
+
* with no interactive attributes, so existing consumers see zero behaviour change.
|
|
19
22
|
*/
|
|
20
23
|
onclick?: (event: MouseEvent) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Render the card root as an `<a>` styled identically, instead of a `<div>`. Use
|
|
26
|
+
* for card-styled links/navigation. When set, the root is natively focusable and
|
|
27
|
+
* Enter-activates, so the `role="button"`/`tabindex`/keydown shim used for a
|
|
28
|
+
* clickable `<div>` (see `onclick`) is not applied. `onclick` (if also provided)
|
|
29
|
+
* still fires alongside navigation. Omitted by default, so existing consumers are
|
|
30
|
+
* unaffected.
|
|
31
|
+
*/
|
|
32
|
+
href?: string;
|
|
33
|
+
/** Anchor target (only applied when `href` is set), e.g. `_blank`. */
|
|
34
|
+
target?: string;
|
|
35
|
+
/** Anchor rel (only applied when `href` is set). Defaults to `noopener noreferrer` when `target="_blank"`. */
|
|
36
|
+
rel?: string;
|
|
21
37
|
/**
|
|
22
38
|
* Snippet rendered at the top-right of the header row, alongside title/description.
|
|
23
39
|
* When omitted the header row is unchanged (title block takes full width).
|