@juspay/svelte-ui-components 2.133.0 → 2.134.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/README.md +30 -0
- package/dist/Checkbox/Checkbox.svelte +3 -1
- package/dist/Checkbox/properties.d.ts +5 -0
- package/dist/Draggable/Draggable.svelte +175 -0
- package/dist/Draggable/Draggable.svelte.d.ts +4 -0
- package/dist/Draggable/properties.d.ts +26 -0
- package/dist/Draggable/properties.js +1 -0
- package/dist/Gallery/Gallery.svelte +593 -0
- package/dist/Gallery/Gallery.svelte.d.ts +4 -0
- package/dist/Gallery/properties.d.ts +39 -0
- package/dist/Gallery/properties.js +1 -0
- package/dist/Input/Input.svelte +17 -4
- package/dist/Input/properties.d.ts +6 -0
- package/dist/MediaPlayer/MediaPlayer.svelte +277 -0
- package/dist/MediaPlayer/MediaPlayer.svelte.d.ts +4 -0
- package/dist/MediaPlayer/properties.d.ts +34 -0
- package/dist/MediaPlayer/properties.js +1 -0
- package/dist/MediaUpload/MediaUpload.svelte +528 -0
- package/dist/MediaUpload/MediaUpload.svelte.d.ts +4 -0
- package/dist/MediaUpload/properties.d.ts +46 -0
- package/dist/MediaUpload/properties.js +1 -0
- package/dist/Menu/Menu.svelte +2 -0
- package/dist/Menu/properties.d.ts +5 -0
- package/dist/Modal/Modal.svelte +17 -3
- package/dist/Modal/properties.d.ts +4 -0
- package/dist/assets/add.svg +4 -0
- package/dist/assets/delete.svg +7 -0
- package/dist/assets/edit.svg +4 -0
- package/dist/assets/file.svg +4 -0
- package/dist/assets/mute.svg +5 -0
- package/dist/assets/pause.svg +4 -0
- package/dist/assets/play.svg +3 -0
- package/dist/assets/volume.svg +5 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4 -0
- package/dist-wc/index.d.ts +1 -0
- package/dist-wc/index.js +33018 -0
- package/package.json +16 -9
package/README.md
CHANGED
|
@@ -153,6 +153,36 @@ This library takes a different approach: **components are unstyled by default**
|
|
|
153
153
|
|
|
154
154
|
---
|
|
155
155
|
|
|
156
|
+
## Web Components
|
|
157
|
+
|
|
158
|
+
Every component also ships as a real Custom Element (Svelte 5's native `customElement`
|
|
159
|
+
compiler output, shadow DOM), tagged `sui-*` — usable from React, Vue, Angular, or plain
|
|
160
|
+
HTML, no separate Svelte installation required; the runtime is bundled with each
|
|
161
|
+
component.
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<!-- Always the latest release, via GitHub Pages -->
|
|
165
|
+
<script type="module" src="https://juspay.github.io/svelte-ui-components/wc/index.js"></script>
|
|
166
|
+
|
|
167
|
+
<!-- Pinned to an npm version, via jsDelivr or unpkg -->
|
|
168
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@juspay/svelte-ui-components@latest/dist-wc/index.js"></script>
|
|
169
|
+
<script type="module" src="https://unpkg.com/@juspay/svelte-ui-components@latest/dist-wc/index.js"></script>
|
|
170
|
+
|
|
171
|
+
<sui-button>Click me</sui-button>
|
|
172
|
+
<sui-input placeholder="Type here"></sui-input>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Or from npm directly, via the package's `./wc` export:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import '@juspay/svelte-ui-components/wc';
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Theming works identically to the Svelte components — the same `--{component}-{element}-{property}`
|
|
182
|
+
CSS custom properties apply across the shadow DOM boundary.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
156
186
|
## Theming
|
|
157
187
|
|
|
158
188
|
### How It Works
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
indeterminateIcon,
|
|
14
14
|
onclick,
|
|
15
15
|
classes,
|
|
16
|
-
ariaControls
|
|
16
|
+
ariaControls,
|
|
17
|
+
ariaLabel
|
|
17
18
|
}: CheckboxProperties = $props();
|
|
18
19
|
|
|
19
20
|
function handleClick(): void {
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
aria-checked={indeterminate ? 'mixed' : checked}
|
|
72
73
|
aria-disabled={disabled}
|
|
73
74
|
aria-controls={ariaControls ?? null}
|
|
75
|
+
aria-label={text.length === 0 ? (ariaLabel ?? null) : null}
|
|
74
76
|
onkeydown={handleKeyDown}
|
|
75
77
|
data-pw={typeof testId === 'string' ? `${testId}-box` : null}
|
|
76
78
|
testID={typeof testId === 'string' ? `${testId}-box` : null}
|
|
@@ -12,6 +12,11 @@ export type OptionalCheckboxProperties = {
|
|
|
12
12
|
indeterminateIcon?: Snippet;
|
|
13
13
|
classes?: string;
|
|
14
14
|
ariaControls?: string;
|
|
15
|
+
/** Accessible name for the checkbox. Needed whenever the visible label sits
|
|
16
|
+
* outside this component (a table header cell, an icon-only row control),
|
|
17
|
+
* since name-from-content cannot reach it. Ignored when `text` is non-empty:
|
|
18
|
+
* a visible label must stay part of the accessible name (WCAG 2.5.3). */
|
|
19
|
+
ariaLabel?: string;
|
|
15
20
|
};
|
|
16
21
|
export type CheckboxEventProperties = {
|
|
17
22
|
onclick?: (checked: boolean) => void;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DraggableProperties, DragPosition } from './properties';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
x = $bindable(0),
|
|
6
|
+
y = $bindable(0),
|
|
7
|
+
axis = 'both',
|
|
8
|
+
handle,
|
|
9
|
+
bounds = null,
|
|
10
|
+
disabled = false,
|
|
11
|
+
step = 16,
|
|
12
|
+
dragLabel = 'Drag to move',
|
|
13
|
+
children,
|
|
14
|
+
onMoveStart,
|
|
15
|
+
onMove,
|
|
16
|
+
onMoveEnd,
|
|
17
|
+
testId,
|
|
18
|
+
classes
|
|
19
|
+
}: DraggableProperties = $props();
|
|
20
|
+
|
|
21
|
+
let active: {
|
|
22
|
+
pointerId: number;
|
|
23
|
+
startX: number;
|
|
24
|
+
startY: number;
|
|
25
|
+
baseX: number;
|
|
26
|
+
baseY: number;
|
|
27
|
+
} | null = $state(null);
|
|
28
|
+
|
|
29
|
+
function isInteractive(target: EventTarget | null): boolean {
|
|
30
|
+
return (
|
|
31
|
+
target instanceof Element &&
|
|
32
|
+
target.closest('input, textarea, select, button, a, [contenteditable="true"]') !== null
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function withinHandle(target: EventTarget | null): boolean {
|
|
37
|
+
if (typeof handle !== 'string' || handle.length === 0) {
|
|
38
|
+
return !isInteractive(target);
|
|
39
|
+
}
|
|
40
|
+
return target instanceof Element && target.closest(handle) !== null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function clamp(node: HTMLElement, nextX: number, nextY: number): DragPosition {
|
|
44
|
+
if (bounds !== 'viewport' || typeof window === 'undefined') {
|
|
45
|
+
return { x: nextX, y: nextY };
|
|
46
|
+
}
|
|
47
|
+
const rect = node.getBoundingClientRect();
|
|
48
|
+
let resultX = nextX;
|
|
49
|
+
let resultY = nextY;
|
|
50
|
+
if (rect.left + (nextX - x) < 0) {
|
|
51
|
+
resultX = x - rect.left;
|
|
52
|
+
} else if (rect.right + (nextX - x) > window.innerWidth) {
|
|
53
|
+
resultX = x + (window.innerWidth - rect.right);
|
|
54
|
+
}
|
|
55
|
+
if (rect.top + (nextY - y) < 0) {
|
|
56
|
+
resultY = y - rect.top;
|
|
57
|
+
} else if (rect.bottom + (nextY - y) > window.innerHeight) {
|
|
58
|
+
resultY = y + (window.innerHeight - rect.bottom);
|
|
59
|
+
}
|
|
60
|
+
return { x: resultX, y: resultY };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function startDrag(event: PointerEvent & { currentTarget: HTMLElement }): void {
|
|
64
|
+
if (disabled || !withinHandle(event.target)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
active = {
|
|
69
|
+
pointerId: event.pointerId,
|
|
70
|
+
startX: event.clientX,
|
|
71
|
+
startY: event.clientY,
|
|
72
|
+
baseX: x,
|
|
73
|
+
baseY: y
|
|
74
|
+
};
|
|
75
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
76
|
+
onMoveStart?.({ x, y });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function moveDrag(event: PointerEvent & { currentTarget: HTMLElement }): void {
|
|
80
|
+
if (active === null) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const nextX = axis === 'y' ? x : active.baseX + (event.clientX - active.startX);
|
|
84
|
+
const nextY = axis === 'x' ? y : active.baseY + (event.clientY - active.startY);
|
|
85
|
+
const clamped = clamp(event.currentTarget, nextX, nextY);
|
|
86
|
+
x = clamped.x;
|
|
87
|
+
y = clamped.y;
|
|
88
|
+
onMove?.({ x, y });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function endDrag(event: PointerEvent & { currentTarget: HTMLElement }): void {
|
|
92
|
+
if (active === null) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
96
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
97
|
+
}
|
|
98
|
+
active = null;
|
|
99
|
+
onMoveEnd?.({ x, y });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function keyDrag(event: KeyboardEvent & { currentTarget: HTMLElement }): void {
|
|
103
|
+
if (disabled || event.target !== event.currentTarget) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
let nextX = x;
|
|
107
|
+
let nextY = y;
|
|
108
|
+
let moved = false;
|
|
109
|
+
if (axis !== 'y' && event.key === 'ArrowLeft') {
|
|
110
|
+
nextX = x - step;
|
|
111
|
+
moved = true;
|
|
112
|
+
} else if (axis !== 'y' && event.key === 'ArrowRight') {
|
|
113
|
+
nextX = x + step;
|
|
114
|
+
moved = true;
|
|
115
|
+
} else if (axis !== 'x' && event.key === 'ArrowUp') {
|
|
116
|
+
nextY = y - step;
|
|
117
|
+
moved = true;
|
|
118
|
+
} else if (axis !== 'x' && event.key === 'ArrowDown') {
|
|
119
|
+
nextY = y + step;
|
|
120
|
+
moved = true;
|
|
121
|
+
}
|
|
122
|
+
if (moved) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
const clamped = clamp(event.currentTarget, nextX, nextY);
|
|
125
|
+
x = clamped.x;
|
|
126
|
+
y = clamped.y;
|
|
127
|
+
onMove?.({ x, y });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
133
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
134
|
+
<div
|
|
135
|
+
class="draggable {classes ?? ''}"
|
|
136
|
+
class:dragging={active !== null}
|
|
137
|
+
data-pw={typeof testId === 'string' ? testId : null}
|
|
138
|
+
tabindex={disabled ? -1 : 0}
|
|
139
|
+
aria-label={dragLabel}
|
|
140
|
+
style:transform={`translate(${x}px, ${y}px)`}
|
|
141
|
+
onpointerdown={startDrag}
|
|
142
|
+
onpointermove={moveDrag}
|
|
143
|
+
onpointerup={endDrag}
|
|
144
|
+
onkeydown={keyDrag}
|
|
145
|
+
>
|
|
146
|
+
{#if typeof children === 'function'}
|
|
147
|
+
{@render children()}
|
|
148
|
+
{/if}
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<style>
|
|
152
|
+
.draggable {
|
|
153
|
+
box-sizing: border-box;
|
|
154
|
+
width: var(--draggable-width, fit-content);
|
|
155
|
+
height: var(--draggable-height, fit-content);
|
|
156
|
+
cursor: var(--draggable-cursor, grab);
|
|
157
|
+
touch-action: none;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.draggable.dragging {
|
|
161
|
+
cursor: var(--draggable-cursor-active, grabbing);
|
|
162
|
+
user-select: none;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.draggable:focus-visible {
|
|
166
|
+
outline: var(--draggable-focus-outline, 2px solid #3b5bdb);
|
|
167
|
+
outline-offset: var(--draggable-focus-outline-offset, 2px);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@media (prefers-reduced-motion: reduce) {
|
|
171
|
+
.draggable {
|
|
172
|
+
transition: none;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export type DragAxis = 'both' | 'x' | 'y';
|
|
3
|
+
export type DragBounds = 'viewport' | null;
|
|
4
|
+
export type DragPosition = {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
export type DraggableProperties = OptionalDraggableProperties & DraggableEventProperties;
|
|
9
|
+
export type OptionalDraggableProperties = {
|
|
10
|
+
x?: number;
|
|
11
|
+
y?: number;
|
|
12
|
+
axis?: DragAxis;
|
|
13
|
+
handle?: string;
|
|
14
|
+
bounds?: DragBounds;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
step?: number;
|
|
17
|
+
dragLabel?: string;
|
|
18
|
+
children?: Snippet;
|
|
19
|
+
testId?: string;
|
|
20
|
+
classes?: string;
|
|
21
|
+
};
|
|
22
|
+
export type DraggableEventProperties = {
|
|
23
|
+
onMoveStart?: (position: DragPosition) => void;
|
|
24
|
+
onMove?: (position: DragPosition) => void;
|
|
25
|
+
onMoveEnd?: (position: DragPosition) => void;
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|