polymorph-ui-components 0.1.0 → 0.4.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.
Files changed (71) hide show
  1. package/dist/Chat/Chat.svelte +144 -0
  2. package/dist/Chat/Chat.svelte.d.ts +4 -0
  3. package/dist/Chat/controller.svelte.d.ts +24 -0
  4. package/dist/Chat/controller.svelte.js +190 -0
  5. package/dist/Chat/properties.d.ts +50 -0
  6. package/dist/Chat/properties.js +1 -0
  7. package/dist/Chat/roles.d.ts +2 -0
  8. package/dist/Chat/roles.js +3 -0
  9. package/dist/Chat/types.d.ts +45 -0
  10. package/dist/Chat/types.js +1 -0
  11. package/dist/ChatBubble/ChatBubble.svelte +418 -0
  12. package/dist/ChatBubble/ChatBubble.svelte.d.ts +4 -0
  13. package/dist/ChatBubble/properties.d.ts +43 -0
  14. package/dist/ChatBubble/properties.js +1 -0
  15. package/dist/ChatComposer/ChatComposer.svelte +284 -0
  16. package/dist/ChatComposer/ChatComposer.svelte.d.ts +4 -0
  17. package/dist/ChatComposer/properties.d.ts +33 -0
  18. package/dist/ChatComposer/properties.js +1 -0
  19. package/dist/ChatHeader/ChatHeader.svelte +165 -0
  20. package/dist/ChatHeader/ChatHeader.svelte.d.ts +4 -0
  21. package/dist/ChatHeader/properties.d.ts +19 -0
  22. package/dist/ChatHeader/properties.js +1 -0
  23. package/dist/ChatMessage/ChatMessage.svelte +325 -0
  24. package/dist/ChatMessage/ChatMessage.svelte.d.ts +4 -0
  25. package/dist/ChatMessage/properties.d.ts +29 -0
  26. package/dist/ChatMessage/properties.js +1 -0
  27. package/dist/ChatMessageList/ChatMessageList.svelte +175 -0
  28. package/dist/ChatMessageList/ChatMessageList.svelte.d.ts +4 -0
  29. package/dist/ChatMessageList/properties.d.ts +21 -0
  30. package/dist/ChatMessageList/properties.js +1 -0
  31. package/dist/ChatSuggestions/ChatSuggestions.svelte +42 -0
  32. package/dist/ChatSuggestions/ChatSuggestions.svelte.d.ts +4 -0
  33. package/dist/ChatSuggestions/properties.d.ts +16 -0
  34. package/dist/ChatSuggestions/properties.js +1 -0
  35. package/dist/ChatToolStatus/ChatToolStatus.svelte +56 -0
  36. package/dist/ChatToolStatus/ChatToolStatus.svelte.d.ts +4 -0
  37. package/dist/ChatToolStatus/properties.d.ts +10 -0
  38. package/dist/ChatToolStatus/properties.js +1 -0
  39. package/dist/Draggable/Draggable.svelte +169 -0
  40. package/dist/Draggable/Draggable.svelte.d.ts +4 -0
  41. package/dist/Draggable/properties.d.ts +25 -0
  42. package/dist/Draggable/properties.js +1 -0
  43. package/dist/MediaPlayer/MediaPlayer.svelte +245 -0
  44. package/dist/MediaPlayer/MediaPlayer.svelte.d.ts +4 -0
  45. package/dist/MediaPlayer/properties.d.ts +27 -0
  46. package/dist/MediaPlayer/properties.js +1 -0
  47. package/dist/MediaUpload/MediaUpload.svelte +524 -0
  48. package/dist/MediaUpload/MediaUpload.svelte.d.ts +4 -0
  49. package/dist/MediaUpload/properties.d.ts +46 -0
  50. package/dist/MediaUpload/properties.js +1 -0
  51. package/dist/Resizable/Resizable.svelte +303 -0
  52. package/dist/Resizable/Resizable.svelte.d.ts +4 -0
  53. package/dist/Resizable/properties.d.ts +27 -0
  54. package/dist/Resizable/properties.js +1 -0
  55. package/dist/assets/add.svg +4 -0
  56. package/dist/assets/attach.svg +3 -0
  57. package/dist/assets/chat.svg +3 -0
  58. package/dist/assets/file.svg +4 -0
  59. package/dist/assets/mic.svg +5 -0
  60. package/dist/assets/mute.svg +5 -0
  61. package/dist/assets/pause.svg +4 -0
  62. package/dist/assets/play.svg +3 -0
  63. package/dist/assets/retry.svg +4 -0
  64. package/dist/assets/send.svg +4 -0
  65. package/dist/assets/stop.svg +3 -0
  66. package/dist/assets/thumb-down.svg +4 -0
  67. package/dist/assets/thumb-up.svg +4 -0
  68. package/dist/assets/volume.svg +5 -0
  69. package/dist/index.d.ts +27 -0
  70. package/dist/index.js +14 -0
  71. package/package.json +1 -1
@@ -0,0 +1,4 @@
1
+ import type { ChatToolStatusProperties } from './properties';
2
+ declare const ChatToolStatus: import("svelte").Component<ChatToolStatusProperties, {}, "">;
3
+ type ChatToolStatus = ReturnType<typeof ChatToolStatus>;
4
+ export default ChatToolStatus;
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type ChatToolStatusProperties = OptionalChatToolStatusProperties & MandatoryChatToolStatusProperties;
3
+ export type MandatoryChatToolStatusProperties = {
4
+ label: string;
5
+ };
6
+ export type OptionalChatToolStatusProperties = {
7
+ icon?: Snippet;
8
+ testId?: string;
9
+ classes?: string;
10
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,169 @@
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
+ ondragstart,
15
+ ondrag,
16
+ ondragend,
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
+ ondragstart?.({ 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
+ ondrag?.({ 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
+ ondragend?.({ 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
+ ondrag?.({ 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={testId}
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
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { DraggableProperties } from './properties';
2
+ declare const Draggable: import("svelte").Component<DraggableProperties, {}, "x" | "y">;
3
+ type Draggable = ReturnType<typeof Draggable>;
4
+ export default Draggable;
@@ -0,0 +1,25 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type DragAxis = 'both' | 'x' | 'y';
3
+ export type DragPosition = {
4
+ x: number;
5
+ y: number;
6
+ };
7
+ export type DraggableProperties = OptionalDraggableProperties & DraggableEventProperties;
8
+ export type OptionalDraggableProperties = {
9
+ x?: number;
10
+ y?: number;
11
+ axis?: DragAxis;
12
+ handle?: string;
13
+ bounds?: 'viewport' | null;
14
+ disabled?: boolean;
15
+ step?: number;
16
+ dragLabel?: string;
17
+ children?: Snippet;
18
+ testId?: string;
19
+ classes?: string;
20
+ };
21
+ export type DraggableEventProperties = {
22
+ ondragstart?: (position: DragPosition) => void;
23
+ ondrag?: (position: DragPosition) => void;
24
+ ondragend?: (position: DragPosition) => void;
25
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,245 @@
1
+ <script lang="ts">
2
+ import Button from '../Button/Button.svelte';
3
+ import Img from '../Img/Img.svelte';
4
+ import playSvg from '../assets/play.svg?raw';
5
+ import pauseSvg from '../assets/pause.svg?raw';
6
+ import volumeSvg from '../assets/volume.svg?raw';
7
+ import muteSvg from '../assets/mute.svg?raw';
8
+ import type { MediaPlayerProperties } from './properties';
9
+
10
+ let {
11
+ src,
12
+ type,
13
+ alt = '',
14
+ autoplay = true,
15
+ loop = false,
16
+ controls = false,
17
+ fallback,
18
+ playing = $bindable(true),
19
+ muted = $bindable(true),
20
+ playIcon,
21
+ pauseIcon,
22
+ muteIcon,
23
+ unmuteIcon,
24
+ onplay,
25
+ onpause,
26
+ onvolumechange,
27
+ testId,
28
+ classes
29
+ }: MediaPlayerProperties = $props();
30
+
31
+ let videoPlayer: HTMLVideoElement | null = $state(null);
32
+
33
+ function togglePlayback(): void {
34
+ if (videoPlayer === null) {
35
+ return;
36
+ }
37
+ if (videoPlayer.paused) {
38
+ videoPlayer.play();
39
+ } else {
40
+ videoPlayer.pause();
41
+ }
42
+ }
43
+
44
+ function toggleMute(): void {
45
+ muted = !muted;
46
+ onvolumechange?.(muted);
47
+ }
48
+
49
+ function handlePlay(event: Event): void {
50
+ playing = true;
51
+ onplay?.(event);
52
+ }
53
+
54
+ function handlePause(event: Event): void {
55
+ playing = false;
56
+ onpause?.(event);
57
+ }
58
+
59
+ function handleVideoKeydown(event: KeyboardEvent): void {
60
+ if (event.key === 'Enter' || event.key === ' ') {
61
+ event.preventDefault();
62
+ togglePlayback();
63
+ }
64
+ }
65
+ </script>
66
+
67
+ <div class="media-player {classes ?? ''}" data-pw={testId}>
68
+ {#if type === 'image'}
69
+ <span class="media-image">
70
+ <Img {src} {alt} {fallback} />
71
+ </span>
72
+ {:else}
73
+ <video
74
+ bind:this={videoPlayer}
75
+ bind:muted
76
+ {src}
77
+ class="media"
78
+ {controls}
79
+ {autoplay}
80
+ {loop}
81
+ playsinline
82
+ onplay={handlePlay}
83
+ onpause={handlePause}
84
+ onclick={togglePlayback}
85
+ onkeydown={handleVideoKeydown}
86
+ role="button"
87
+ tabindex="0"
88
+ aria-label={playing ? 'Pause video' : 'Play video'}
89
+ >
90
+ <track kind="captions" />
91
+ </video>
92
+
93
+ {#if !controls}
94
+ <div class="overlay">
95
+ <div class="center-controls">
96
+ <div class="control center-control">
97
+ <Button onclick={togglePlayback} ariaLabel={playing ? 'Pause video' : 'Play video'}>
98
+ {#if playing}
99
+ {#if typeof pauseIcon === 'function'}
100
+ {@render pauseIcon()}
101
+ {:else}
102
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
103
+ {@html pauseSvg}
104
+ {/if}
105
+ {:else if typeof playIcon === 'function'}
106
+ {@render playIcon()}
107
+ {:else}
108
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
109
+ {@html playSvg}
110
+ {/if}
111
+ </Button>
112
+ </div>
113
+ </div>
114
+ <div class="bottom-controls">
115
+ <div class="control bottom-control">
116
+ <Button onclick={toggleMute} ariaLabel={muted ? 'Unmute' : 'Mute'}>
117
+ {#if muted}
118
+ {#if typeof muteIcon === 'function'}
119
+ {@render muteIcon()}
120
+ {:else}
121
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
122
+ {@html muteSvg}
123
+ {/if}
124
+ {:else if typeof unmuteIcon === 'function'}
125
+ {@render unmuteIcon()}
126
+ {:else}
127
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
128
+ {@html volumeSvg}
129
+ {/if}
130
+ </Button>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ {/if}
135
+ {/if}
136
+ </div>
137
+
138
+ <style>
139
+ .media-player {
140
+ box-sizing: border-box;
141
+ display: flex;
142
+ position: relative;
143
+ height: var(--media-player-height, 400px);
144
+ width: var(--media-player-width, fit-content);
145
+ border-radius: var(--media-player-border-radius, 14px);
146
+ overflow: var(--media-player-overflow, hidden);
147
+ background: var(--media-player-background, transparent);
148
+ }
149
+
150
+ .media {
151
+ height: var(--media-player-media-height, 100%);
152
+ width: var(--media-player-media-width, fit-content);
153
+ object-fit: var(--media-player-media-object-fit, contain);
154
+ border-radius: var(--media-player-media-border-radius, inherit);
155
+ display: block;
156
+ }
157
+
158
+ video.media {
159
+ cursor: var(--media-player-media-cursor, pointer);
160
+ }
161
+
162
+ .media-image {
163
+ display: contents;
164
+ --image-height: var(--media-player-media-height, 100%);
165
+ --image-width: var(--media-player-media-width, fit-content);
166
+ --image-object-fit: var(--media-player-media-object-fit, contain);
167
+ --image-border-radius: var(--media-player-media-border-radius, 0px);
168
+ --image-padding: 0px;
169
+ --image-margin: 0px;
170
+ }
171
+
172
+ .overlay {
173
+ position: absolute;
174
+ inset: 0;
175
+ display: flex;
176
+ flex-direction: column;
177
+ justify-content: center;
178
+ align-items: center;
179
+ box-sizing: border-box;
180
+ z-index: var(--media-player-overlay-z-index, 20);
181
+ border-radius: inherit;
182
+ background-color: var(--media-player-overlay-color, transparent);
183
+ transition: var(--media-player-overlay-transition, background-color 0.2s ease);
184
+ --center-controls-visibility: var(--media-player-center-controls-visibility, hidden);
185
+ --bottom-controls-visibility: var(--media-player-bottom-controls-visibility, hidden);
186
+ }
187
+
188
+ .overlay:hover {
189
+ background-color: var(--media-player-overlay-hover-color, #0000004d);
190
+ --center-controls-visibility: visible;
191
+ --bottom-controls-visibility: visible;
192
+ }
193
+
194
+ .center-controls {
195
+ display: flex;
196
+ flex: 1;
197
+ justify-content: center;
198
+ align-items: center;
199
+ visibility: var(--center-controls-visibility);
200
+ }
201
+
202
+ .bottom-controls {
203
+ display: flex;
204
+ width: 100%;
205
+ height: fit-content;
206
+ justify-content: var(--media-player-bottom-controls-justify, flex-end);
207
+ box-sizing: border-box;
208
+ padding: var(--media-player-bottom-controls-padding, 12px);
209
+ visibility: var(--bottom-controls-visibility);
210
+ }
211
+
212
+ .control {
213
+ --button-padding: var(--media-player-control-padding, 0px);
214
+ --button-border: var(--media-player-control-border, none);
215
+ --button-border-radius: var(--media-player-control-border-radius, 50%);
216
+ --button-color: var(--media-player-control-background-color, transparent);
217
+ --button-text-color: var(--media-player-control-color, #ffffff);
218
+ --button-content-gap: 0px;
219
+ --button-hover-color: var(
220
+ --media-player-control-hover-background-color,
221
+ var(--media-player-control-background-color, transparent)
222
+ );
223
+ --button-hover-text-color: var(
224
+ --media-player-control-hover-color,
225
+ var(--media-player-control-color, #ffffff)
226
+ );
227
+ }
228
+
229
+ .center-control {
230
+ --button-width: var(--media-player-center-control-size, 64px);
231
+ --button-height: var(--media-player-center-control-size, 64px);
232
+ }
233
+
234
+ .bottom-control {
235
+ --button-width: var(--media-player-bottom-control-size, 24px);
236
+ --button-height: var(--media-player-bottom-control-size, 24px);
237
+ }
238
+
239
+ .control :global(svg),
240
+ .control :global(img) {
241
+ height: var(--media-player-control-icon-size, 100%);
242
+ width: var(--media-player-control-icon-size, 100%);
243
+ object-fit: contain;
244
+ }
245
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { MediaPlayerProperties } from './properties';
2
+ declare const MediaPlayer: import("svelte").Component<MediaPlayerProperties, {}, "playing" | "muted">;
3
+ type MediaPlayer = ReturnType<typeof MediaPlayer>;
4
+ export default MediaPlayer;
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type MediaPlayerProperties = OptionalMediaPlayerProperties & MediaPlayerEventProperties & MandatoryMediaPlayerProperties;
3
+ export type MediaType = 'image' | 'video';
4
+ export type MandatoryMediaPlayerProperties = {
5
+ src: string;
6
+ type: MediaType;
7
+ };
8
+ export type OptionalMediaPlayerProperties = {
9
+ alt?: string;
10
+ fallback?: string;
11
+ autoplay?: boolean;
12
+ loop?: boolean;
13
+ controls?: boolean;
14
+ playing?: boolean;
15
+ muted?: boolean;
16
+ playIcon?: Snippet;
17
+ pauseIcon?: Snippet;
18
+ muteIcon?: Snippet;
19
+ unmuteIcon?: Snippet;
20
+ testId?: string;
21
+ classes?: string;
22
+ };
23
+ export type MediaPlayerEventProperties = {
24
+ onplay?: (event: Event) => void;
25
+ onpause?: (event: Event) => void;
26
+ onvolumechange?: (muted: boolean) => void;
27
+ };
@@ -0,0 +1 @@
1
+ export {};