@juspay/svelte-ui-components 2.111.4 → 2.113.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/ChipInput/ChipInput.svelte +122 -0
- package/dist/ChipInput/ChipInput.svelte.d.ts +4 -0
- package/dist/ChipInput/properties.d.ts +22 -0
- package/dist/ChipInput/properties.js +1 -0
- package/dist/FileDropzoneTrigger/FileDropzoneTrigger.svelte +81 -0
- package/dist/FileDropzoneTrigger/FileDropzoneTrigger.svelte.d.ts +4 -0
- package/dist/FileDropzoneTrigger/properties.d.ts +24 -0
- package/dist/FileDropzoneTrigger/properties.js +1 -0
- package/dist/IframeViewer/IframeViewer.svelte +14 -1
- package/dist/IframeViewer/IframeViewer.svelte.d.ts +3 -1
- package/dist/IframeViewer/properties.d.ts +7 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Input from '../Input/Input.svelte';
|
|
3
|
+
import Pill from '../Pill/Pill.svelte';
|
|
4
|
+
import type { ChipInputProperties } from './properties';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
values = $bindable([]),
|
|
8
|
+
placeholder = 'Add value…',
|
|
9
|
+
disabled = false,
|
|
10
|
+
testId,
|
|
11
|
+
classes,
|
|
12
|
+
onadd,
|
|
13
|
+
ondismiss,
|
|
14
|
+
onchange
|
|
15
|
+
}: ChipInputProperties = $props();
|
|
16
|
+
|
|
17
|
+
let draft = $state('');
|
|
18
|
+
|
|
19
|
+
function addChip(): void {
|
|
20
|
+
const trimmed = draft.trim();
|
|
21
|
+
draft = '';
|
|
22
|
+
if (trimmed.length === 0 || values.includes(trimmed)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
values = [...values, trimmed];
|
|
26
|
+
onadd?.(trimmed);
|
|
27
|
+
onchange?.([...values]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function removeChip(chip: string): void {
|
|
31
|
+
// values is dedup-only by construction (addChip rejects a value already present), so this
|
|
32
|
+
// component's own commit path never produces duplicates. If a caller assigns `values`
|
|
33
|
+
// directly through the bindable prop with a duplicate, remove only the first matching
|
|
34
|
+
// occurrence rather than every occurrence with that text.
|
|
35
|
+
const chipIndex = values.indexOf(chip);
|
|
36
|
+
if (chipIndex === -1) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
values = [...values.slice(0, chipIndex), ...values.slice(chipIndex + 1)];
|
|
40
|
+
ondismiss?.(chip);
|
|
41
|
+
onchange?.([...values]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function handleKeyDown(event: KeyboardEvent): void {
|
|
45
|
+
if (event.key === 'Enter') {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
addChip();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<div class="chip-input {classes ?? ''}" data-pw={testId} testID={testId}>
|
|
53
|
+
{#each values as chip (chip)}
|
|
54
|
+
<Pill
|
|
55
|
+
text={chip}
|
|
56
|
+
classes="chip-input-pill"
|
|
57
|
+
dismissible={!disabled}
|
|
58
|
+
{disabled}
|
|
59
|
+
ondismiss={() => removeChip(chip)}
|
|
60
|
+
{...typeof testId === 'string' ? { testId: `${testId}-chip` } : {}}
|
|
61
|
+
/>
|
|
62
|
+
{/each}
|
|
63
|
+
<div class="chip-input-draft-wrap">
|
|
64
|
+
<Input
|
|
65
|
+
value={draft}
|
|
66
|
+
{placeholder}
|
|
67
|
+
dataType="text"
|
|
68
|
+
name=""
|
|
69
|
+
autoComplete="off"
|
|
70
|
+
actionInput={false}
|
|
71
|
+
disable={disabled}
|
|
72
|
+
classes="chip-input-draft"
|
|
73
|
+
onInput={(nextValue) => {
|
|
74
|
+
draft = nextValue;
|
|
75
|
+
}}
|
|
76
|
+
onKeyDown={handleKeyDown}
|
|
77
|
+
onBlur={addChip}
|
|
78
|
+
{...typeof testId === 'string' ? { testId: `${testId}-input` } : {}}
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<style>
|
|
84
|
+
.chip-input {
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-wrap: var(--chip-input-flex-wrap, wrap);
|
|
87
|
+
align-items: var(--chip-input-align-items, center);
|
|
88
|
+
justify-content: var(--chip-input-justify-content, flex-start);
|
|
89
|
+
gap: var(--chip-input-gap, 6px);
|
|
90
|
+
width: var(--chip-input-width, 100%);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.chip-input-draft-wrap {
|
|
94
|
+
flex: var(--chip-input-draft-flex, 0 1 auto);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.chip-input :global(.chip-input-pill) {
|
|
98
|
+
--pill-gap: var(--chip-input-pill-gap, 4px);
|
|
99
|
+
--pill-background: var(--chip-input-pill-background, #e0e0e0);
|
|
100
|
+
--pill-color: var(--chip-input-pill-color, #333333);
|
|
101
|
+
--pill-font-size: var(--chip-input-pill-font-size, 13px);
|
|
102
|
+
--pill-font-weight: var(--chip-input-pill-font-weight, 500);
|
|
103
|
+
--pill-padding: var(--chip-input-pill-padding, 6px 10px);
|
|
104
|
+
--pill-border-radius: var(--chip-input-pill-border-radius, 999px);
|
|
105
|
+
--pill-border: var(--chip-input-pill-border, none);
|
|
106
|
+
--pill-max-width: var(--chip-input-pill-max-width);
|
|
107
|
+
--pill-dismiss-size: var(--chip-input-pill-dismiss-size, 14px);
|
|
108
|
+
--pill-dismiss-color: var(--chip-input-pill-dismiss-color, currentColor);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.chip-input-draft-wrap :global(.chip-input-draft) {
|
|
112
|
+
--input-width: var(--chip-input-draft-width, 90px);
|
|
113
|
+
--input-height: var(--chip-input-draft-height, 28px);
|
|
114
|
+
--input-border: var(--chip-input-draft-border, 1px solid transparent);
|
|
115
|
+
--input-radius: var(--chip-input-draft-radius, 4px);
|
|
116
|
+
--input-focus-border: var(--chip-input-draft-focus-border, 1px solid transparent);
|
|
117
|
+
--input-padding: var(--chip-input-draft-padding, 0 2px);
|
|
118
|
+
--input-margin: 0;
|
|
119
|
+
--input-font-size: var(--chip-input-draft-font-size, 13px);
|
|
120
|
+
--input-box-shadow: none;
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ChipInputProperties = MandatoryChipInputProperties & OptionalChipInputProperties & ChipInputEventProperties;
|
|
2
|
+
export type MandatoryChipInputProperties = {
|
|
3
|
+
/**
|
|
4
|
+
* The committed chips, in insertion order. Bindable. Dedup-only contract: the component's own
|
|
5
|
+
* commit path (`addChip`) silently drops a value already present, so ChipInput never produces
|
|
6
|
+
* duplicates itself. If a caller assigns a duplicate directly through the binding, dismiss
|
|
7
|
+
* removes only the first matching occurrence rather than every occurrence with that text.
|
|
8
|
+
*/
|
|
9
|
+
values: string[];
|
|
10
|
+
};
|
|
11
|
+
export type OptionalChipInputProperties = {
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
testId?: string;
|
|
15
|
+
classes?: string;
|
|
16
|
+
};
|
|
17
|
+
export type ChipInputEventProperties = {
|
|
18
|
+
onadd?: (value: string) => void;
|
|
19
|
+
ondismiss?: (value: string) => void;
|
|
20
|
+
/** Fires alongside `onadd`/`ondismiss`, after either has already updated `values`. */
|
|
21
|
+
onchange?: (values: string[]) => void;
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from '../Button/Button.svelte';
|
|
3
|
+
import Img from '../Img/Img.svelte';
|
|
4
|
+
import type { FileDropzoneTriggerProperties } from './properties';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
icon,
|
|
8
|
+
heading,
|
|
9
|
+
caption,
|
|
10
|
+
compact = false,
|
|
11
|
+
onclick,
|
|
12
|
+
testId,
|
|
13
|
+
classes
|
|
14
|
+
}: FileDropzoneTriggerProperties = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if compact}
|
|
18
|
+
<div class="file-dropzone-trigger-compact {classes ?? ''}">
|
|
19
|
+
<div class="file-dropzone-trigger-icon-sm" aria-hidden="true">
|
|
20
|
+
<Img src={icon} alt="" fallback="" classes="file-dropzone-trigger-icon-sm-img" />
|
|
21
|
+
</div>
|
|
22
|
+
<span class="file-dropzone-trigger-heading" data-pw={testId} testID={testId}>{heading}</span>
|
|
23
|
+
</div>
|
|
24
|
+
{:else}
|
|
25
|
+
<Button
|
|
26
|
+
classes={`file-dropzone-trigger-button ${classes ?? ''}`}
|
|
27
|
+
{onclick}
|
|
28
|
+
{...typeof testId === 'string' ? { testId } : {}}
|
|
29
|
+
>
|
|
30
|
+
<div class="file-dropzone-trigger-icon" aria-hidden="true">
|
|
31
|
+
<Img src={icon} alt="" fallback="" classes="file-dropzone-trigger-icon-img" />
|
|
32
|
+
</div>
|
|
33
|
+
<p class="file-dropzone-trigger-heading-wrap">
|
|
34
|
+
<span class="file-dropzone-trigger-heading">{heading}</span>
|
|
35
|
+
</p>
|
|
36
|
+
{#if caption}
|
|
37
|
+
<p class="file-dropzone-trigger-caption">{caption}</p>
|
|
38
|
+
{/if}
|
|
39
|
+
</Button>
|
|
40
|
+
{/if}
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.file-dropzone-trigger-compact {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: var(--file-dropzone-trigger-compact-flex-direction, row);
|
|
46
|
+
align-items: var(--file-dropzone-trigger-compact-align-items, center);
|
|
47
|
+
gap: var(--file-dropzone-trigger-compact-gap, 8px);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.file-dropzone-trigger-icon-sm,
|
|
51
|
+
.file-dropzone-trigger-icon {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.file-dropzone-trigger-icon-sm :global(.file-dropzone-trigger-icon-sm-img) {
|
|
58
|
+
--image-width: var(--file-dropzone-trigger-icon-sm-size, 16px);
|
|
59
|
+
--image-height: var(--file-dropzone-trigger-icon-sm-size, 16px);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.file-dropzone-trigger-icon :global(.file-dropzone-trigger-icon-img) {
|
|
63
|
+
--image-width: var(--file-dropzone-trigger-icon-size, 24px);
|
|
64
|
+
--image-height: var(--file-dropzone-trigger-icon-size, 24px);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.file-dropzone-trigger-heading {
|
|
68
|
+
color: var(--file-dropzone-trigger-heading-color, inherit);
|
|
69
|
+
font-weight: var(--file-dropzone-trigger-heading-font-weight, 600);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.file-dropzone-trigger-heading-wrap {
|
|
73
|
+
margin: var(--file-dropzone-trigger-heading-margin, 0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.file-dropzone-trigger-caption {
|
|
77
|
+
margin: var(--file-dropzone-trigger-caption-margin, 0);
|
|
78
|
+
color: var(--file-dropzone-trigger-caption-color, #64748b);
|
|
79
|
+
font-size: var(--file-dropzone-trigger-caption-font-size, 0.85em);
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FileDropzoneTriggerProperties } from './properties';
|
|
2
|
+
declare const FileDropzoneTrigger: import("svelte").Component<FileDropzoneTriggerProperties, {}, "">;
|
|
3
|
+
type FileDropzoneTrigger = ReturnType<typeof FileDropzoneTrigger>;
|
|
4
|
+
export default FileDropzoneTrigger;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type FileDropzoneTriggerProperties = MandatoryFileDropzoneTriggerProperties & OptionalFileDropzoneTriggerProperties & FileDropzoneTriggerEventProperties;
|
|
2
|
+
export type MandatoryFileDropzoneTriggerProperties = {
|
|
3
|
+
/** Upload icon asset, rendered through the library `Img` component. */
|
|
4
|
+
icon: string;
|
|
5
|
+
/** Primary call-to-action text (static copy, or a dynamic file name once selected). */
|
|
6
|
+
heading: string;
|
|
7
|
+
};
|
|
8
|
+
export type OptionalFileDropzoneTriggerProperties = {
|
|
9
|
+
/** Secondary line below the heading (accepted file type / size limit). Non-compact only. */
|
|
10
|
+
caption?: string;
|
|
11
|
+
/** Bare icon + heading with no Button wrapper or caption, for inline/compact trigger placements. */
|
|
12
|
+
compact?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Non-compact: forwarded to the inner `Button`. Compact: applied to the heading `<span>`.
|
|
15
|
+
* Emits both `data-pw` and `testID` on that element.
|
|
16
|
+
*/
|
|
17
|
+
testId?: string;
|
|
18
|
+
/** CSS class applied to the root element — the inner `Button` in non-compact, the icon+heading wrapper in compact. */
|
|
19
|
+
classes?: string;
|
|
20
|
+
};
|
|
21
|
+
export type FileDropzoneTriggerEventProperties = {
|
|
22
|
+
/** Wire to `FileInput`'s `openFilePicker`. Non-compact only — compact relies on `FileInput`'s own whole-area click/drop handling. */
|
|
23
|
+
onclick?: () => void;
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
sandbox,
|
|
11
11
|
loading,
|
|
12
12
|
referrerpolicy,
|
|
13
|
+
credentialless,
|
|
13
14
|
testId,
|
|
14
15
|
classes,
|
|
15
16
|
onMessage = () => {}
|
|
@@ -17,6 +18,10 @@
|
|
|
17
18
|
|
|
18
19
|
let iframeEl: HTMLIFrameElement | null = $state(null);
|
|
19
20
|
|
|
21
|
+
export const postMessage = (message: unknown, targetOrigin: string): void => {
|
|
22
|
+
iframeEl?.contentWindow?.postMessage(message, targetOrigin);
|
|
23
|
+
};
|
|
24
|
+
|
|
20
25
|
const messageHandler = (event: MessageEvent): void => {
|
|
21
26
|
// Secure by default: forward a message only when its origin is allow-listed AND it
|
|
22
27
|
// originates from the embedded iframe's own window. An empty allowedOrigins list
|
|
@@ -44,7 +49,15 @@
|
|
|
44
49
|
|
|
45
50
|
<div class="iframe-viewer {classes ?? ''}" data-pw={testId} testID={testId}>
|
|
46
51
|
{#if src}
|
|
47
|
-
<iframe
|
|
52
|
+
<iframe
|
|
53
|
+
bind:this={iframeEl}
|
|
54
|
+
{src}
|
|
55
|
+
{title}
|
|
56
|
+
{allow}
|
|
57
|
+
{sandbox}
|
|
58
|
+
{loading}
|
|
59
|
+
{referrerpolicy}
|
|
60
|
+
{...credentialless ? { credentialless: '' } : {}}
|
|
48
61
|
></iframe>
|
|
49
62
|
{/if}
|
|
50
63
|
</div>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { IframeViewerProperties } from './properties';
|
|
2
|
-
declare const IframeViewer: import("svelte").Component<IframeViewerProperties, {
|
|
2
|
+
declare const IframeViewer: import("svelte").Component<IframeViewerProperties, {
|
|
3
|
+
postMessage: (message: unknown, targetOrigin: string) => void;
|
|
4
|
+
}, "">;
|
|
3
5
|
type IframeViewer = ReturnType<typeof IframeViewer>;
|
|
4
6
|
export default IframeViewer;
|
|
@@ -15,6 +15,13 @@ export type OptionalIframeViewerProperties = {
|
|
|
15
15
|
allow?: string;
|
|
16
16
|
/** Value for the iframe `sandbox` attribute. Omitted when not set. */
|
|
17
17
|
sandbox?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Sets the iframe's `credentialless` attribute, isolating it from the embedding
|
|
20
|
+
* document's credentials/storage. Applied in the same render statement as `src` (not
|
|
21
|
+
* via a post-mount effect), so it is guaranteed to be present before the iframe's
|
|
22
|
+
* first load — no timing dependency on effect scheduling.
|
|
23
|
+
*/
|
|
24
|
+
credentialless?: boolean;
|
|
18
25
|
/** Loading strategy for the iframe. Omitted when not set. */
|
|
19
26
|
loading?: 'eager' | 'lazy';
|
|
20
27
|
/** Referrer policy for the iframe. Omitted when not set. */
|
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,8 @@ export { default as DeltaIndicator } from './DeltaIndicator/DeltaIndicator.svelt
|
|
|
75
75
|
export { default as DualAxisBarChart } from './DualAxisBarChart/DualAxisBarChart.svelte';
|
|
76
76
|
export { default as FunnelChart } from './FunnelChart/FunnelChart.svelte';
|
|
77
77
|
export { default as ProportionBar } from './ProportionBar/ProportionBar.svelte';
|
|
78
|
+
export { default as ChipInput } from './ChipInput/ChipInput.svelte';
|
|
79
|
+
export { default as FileDropzoneTrigger } from './FileDropzoneTrigger/FileDropzoneTrigger.svelte';
|
|
78
80
|
export type * from './Button/properties';
|
|
79
81
|
export type * from './Modal/properties';
|
|
80
82
|
export type * from './Input/properties';
|
|
@@ -146,6 +148,8 @@ export type * from './DeltaIndicator/properties';
|
|
|
146
148
|
export type * from './DualAxisBarChart/properties';
|
|
147
149
|
export type * from './FunnelChart/properties';
|
|
148
150
|
export type * from './ProportionBar/properties';
|
|
151
|
+
export type * from './ChipInput/properties';
|
|
152
|
+
export type * from './FileDropzoneTrigger/properties';
|
|
149
153
|
export type * from './_chart/highlight';
|
|
150
154
|
export { validateInput } from './utils';
|
|
151
155
|
export { formatNumberIndian } from './_chart/format';
|
package/dist/index.js
CHANGED
|
@@ -75,5 +75,7 @@ export { default as DeltaIndicator } from './DeltaIndicator/DeltaIndicator.svelt
|
|
|
75
75
|
export { default as DualAxisBarChart } from './DualAxisBarChart/DualAxisBarChart.svelte';
|
|
76
76
|
export { default as FunnelChart } from './FunnelChart/FunnelChart.svelte';
|
|
77
77
|
export { default as ProportionBar } from './ProportionBar/ProportionBar.svelte';
|
|
78
|
+
export { default as ChipInput } from './ChipInput/ChipInput.svelte';
|
|
79
|
+
export { default as FileDropzoneTrigger } from './FileDropzoneTrigger/FileDropzoneTrigger.svelte';
|
|
78
80
|
export { validateInput } from './utils';
|
|
79
81
|
export { formatNumberIndian } from './_chart/format';
|