@juspay/svelte-ui-components 4.35.1 → 4.37.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/ChatComposer/ChatComposer.svelte +18 -0
- package/dist/ChatComposer/ChatComposer.svelte.d.ts +3 -1
- package/dist/ChatComposer/properties.d.ts +5 -0
- package/dist/ChatHeader/ChatHeader.svelte +42 -0
- package/dist/ChatHeader/ChatHeader.svelte.d.ts +1 -1
- package/dist/ChatHeader/properties.d.ts +5 -0
- package/dist/DockPanel/DockPanel.svelte +193 -0
- package/dist/DockPanel/DockPanel.svelte.d.ts +4 -0
- package/dist/DockPanel/properties.d.ts +30 -0
- package/dist/DockPanel/properties.js +1 -0
- package/dist/Resizable/Resizable.svelte +15 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/styles/theme-dark.css +5 -0
- package/dist-codemod/codemod/migration-assets/legacy-display.css +2 -1
- package/dist-codemod/codemod/migration-assets/wc-display.json +5 -0
- package/dist-wc/index.js +2911 -2415
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
let {
|
|
22
22
|
value = $bindable(''),
|
|
23
23
|
layout = 'row',
|
|
24
|
+
variant = 'default',
|
|
24
25
|
placeholder = '',
|
|
25
26
|
disabled = false,
|
|
26
27
|
textDisabled = null,
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
actionLabel = 'Voice conversation',
|
|
61
62
|
actionText,
|
|
62
63
|
leading,
|
|
64
|
+
trailing,
|
|
63
65
|
statusText,
|
|
64
66
|
statusTestId,
|
|
65
67
|
slashCommands = null,
|
|
@@ -71,6 +73,7 @@
|
|
|
71
73
|
slashItem,
|
|
72
74
|
onsubmit,
|
|
73
75
|
oninput,
|
|
76
|
+
oninputfocus,
|
|
74
77
|
onkeydown,
|
|
75
78
|
onpaste,
|
|
76
79
|
onstop,
|
|
@@ -92,6 +95,11 @@
|
|
|
92
95
|
}: ChatComposerProperties = $props();
|
|
93
96
|
|
|
94
97
|
let fileInput: HTMLInputElement | null = $state(null);
|
|
98
|
+
let inputElement: HTMLTextAreaElement | null = $state(null);
|
|
99
|
+
|
|
100
|
+
export const focus = (options?: FocusOptions): void => {
|
|
101
|
+
inputElement?.focus(options);
|
|
102
|
+
};
|
|
95
103
|
|
|
96
104
|
let showVoice = $derived(typeof onvoice === 'function');
|
|
97
105
|
let showAttach = $derived(typeof onattach === 'function' || typeof onattachclick === 'function');
|
|
@@ -391,6 +399,7 @@
|
|
|
391
399
|
{#snippet textInput()}
|
|
392
400
|
<textarea
|
|
393
401
|
class="input"
|
|
402
|
+
bind:this={inputElement}
|
|
394
403
|
data-pw={inputTestId ?? null}
|
|
395
404
|
bind:value
|
|
396
405
|
{placeholder}
|
|
@@ -404,6 +413,7 @@
|
|
|
404
413
|
aria-activedescendant={slashActiveId}
|
|
405
414
|
maxlength={maxLength > 0 ? maxLength : null}
|
|
406
415
|
oninput={handleInput}
|
|
416
|
+
onfocus={(event) => oninputfocus?.(event)}
|
|
407
417
|
onkeydown={handleKeydown}
|
|
408
418
|
onpaste={(event) => onpaste?.(event)}
|
|
409
419
|
use:autoGrow={value}
|
|
@@ -480,11 +490,15 @@
|
|
|
480
490
|
</Button>
|
|
481
491
|
</div>
|
|
482
492
|
{/if}
|
|
493
|
+
{#if typeof trailing === 'function'}
|
|
494
|
+
{@render trailing()}
|
|
495
|
+
{/if}
|
|
483
496
|
{/snippet}
|
|
484
497
|
|
|
485
498
|
<div
|
|
486
499
|
class="chat-composer {classes ?? ''}"
|
|
487
500
|
class:disabled
|
|
501
|
+
class:pill={variant === 'pill'}
|
|
488
502
|
data-has-slash={slashCommands !== null ? '' : null}
|
|
489
503
|
data-pw={typeof testId === 'string' ? testId : null}
|
|
490
504
|
testID={typeof testId === 'string' ? testId : null}
|
|
@@ -611,6 +625,10 @@
|
|
|
611
625
|
opacity: var(--chat-composer-disabled-opacity, 0.6);
|
|
612
626
|
}
|
|
613
627
|
|
|
628
|
+
.chat-composer.pill {
|
|
629
|
+
border-radius: var(--chat-composer-pill-border-radius, 999px);
|
|
630
|
+
}
|
|
631
|
+
|
|
614
632
|
/* .input below sets outline: none with nothing standing in for it, so the
|
|
615
633
|
visible replacement lives here on the surrounding surface instead --
|
|
616
634
|
:focus-within lights up whenever the textarea inside is focused, the same
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ChatComposerProperties } from './properties';
|
|
2
|
-
declare const ChatComposer: import("svelte").Component<ChatComposerProperties, {
|
|
2
|
+
declare const ChatComposer: import("svelte").Component<ChatComposerProperties, {
|
|
3
|
+
focus: (options?: FocusOptions) => void;
|
|
4
|
+
}, "value" | "attachments">;
|
|
3
5
|
type ChatComposer = ReturnType<typeof ChatComposer>;
|
|
4
6
|
export default ChatComposer;
|
|
@@ -5,6 +5,7 @@ export type OptionalChatComposerProperties = {
|
|
|
5
5
|
value?: string;
|
|
6
6
|
/** Text above a separate control row when stacked; row preserves the default. */
|
|
7
7
|
layout?: 'row' | 'stacked';
|
|
8
|
+
variant?: 'default' | 'pill';
|
|
8
9
|
placeholder?: string;
|
|
9
10
|
disabled?: boolean;
|
|
10
11
|
/**
|
|
@@ -85,6 +86,8 @@ export type OptionalChatComposerProperties = {
|
|
|
85
86
|
/** Optional visible text beside the idle action icon; omitted keeps icon-only markup. */
|
|
86
87
|
actionText?: string;
|
|
87
88
|
leading?: Snippet;
|
|
89
|
+
/** Additional controls after the send/stop control. */
|
|
90
|
+
trailing?: Snippet;
|
|
88
91
|
/**
|
|
89
92
|
* Opt-in sr-only status region (`role="status" aria-live="polite"`) for
|
|
90
93
|
* narrating composer state changes -- e.g. "Recording. Press Escape to stop
|
|
@@ -145,6 +148,8 @@ export type ChatComposerEventProperties = {
|
|
|
145
148
|
*/
|
|
146
149
|
onsubmit?: (value: string, attachments: File[]) => boolean | void | Promise<boolean | void>;
|
|
147
150
|
oninput?: (value: string, event: Event) => void;
|
|
151
|
+
/** Textarea focus, named separately from the native HTMLElement onfocus accessor. */
|
|
152
|
+
oninputfocus?: (event: FocusEvent) => void;
|
|
148
153
|
onkeydown?: (event: KeyboardEvent) => void;
|
|
149
154
|
onpaste?: (event: ClipboardEvent) => void;
|
|
150
155
|
onstop?: () => void;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import Button from '../Button/Button.svelte';
|
|
3
3
|
import Img from '../Img/Img.svelte';
|
|
4
4
|
import closeSvg from '../assets/close.svg?raw';
|
|
5
|
+
import fullscreenSvg from '../assets/fullscreen.svg?raw';
|
|
6
|
+
import exitFullscreenSvg from '../assets/exit-fullscreen.svg?raw';
|
|
5
7
|
import type { ChatHeaderProperties } from './properties';
|
|
6
8
|
|
|
7
9
|
let {
|
|
@@ -11,6 +13,11 @@
|
|
|
11
13
|
imageAlt = '',
|
|
12
14
|
avatar,
|
|
13
15
|
actions,
|
|
16
|
+
expanded = $bindable(false),
|
|
17
|
+
showExpand,
|
|
18
|
+
expandLabel = 'Expand',
|
|
19
|
+
collapseLabel = 'Collapse',
|
|
20
|
+
onexpandchange,
|
|
14
21
|
closeIcon,
|
|
15
22
|
closeLabel = 'Close',
|
|
16
23
|
showClose,
|
|
@@ -21,6 +28,12 @@
|
|
|
21
28
|
}: ChatHeaderProperties = $props();
|
|
22
29
|
|
|
23
30
|
let displayClose = $derived(showClose ?? typeof onclose === 'function');
|
|
31
|
+
let displayExpand = $derived(showExpand ?? typeof onexpandchange === 'function');
|
|
32
|
+
|
|
33
|
+
const toggleExpanded = (): void => {
|
|
34
|
+
expanded = !expanded;
|
|
35
|
+
onexpandchange?.(expanded);
|
|
36
|
+
};
|
|
24
37
|
</script>
|
|
25
38
|
|
|
26
39
|
<header
|
|
@@ -53,6 +66,18 @@
|
|
|
53
66
|
{#if typeof actions === 'function'}
|
|
54
67
|
{@render actions()}
|
|
55
68
|
{/if}
|
|
69
|
+
{#if displayExpand}
|
|
70
|
+
<div class="expand">
|
|
71
|
+
<Button
|
|
72
|
+
variant="ghost"
|
|
73
|
+
onclick={toggleExpanded}
|
|
74
|
+
ariaLabel={expanded ? collapseLabel : expandLabel}
|
|
75
|
+
>
|
|
76
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
77
|
+
{@html expanded ? exitFullscreenSvg : fullscreenSvg}
|
|
78
|
+
</Button>
|
|
79
|
+
</div>
|
|
80
|
+
{/if}
|
|
56
81
|
{#if displayClose}
|
|
57
82
|
<div class="close">
|
|
58
83
|
<Button onclick={() => onclose?.()} ariaLabel={closeLabel}>
|
|
@@ -166,4 +191,21 @@
|
|
|
166
191
|
height: 100%;
|
|
167
192
|
width: 100%;
|
|
168
193
|
}
|
|
194
|
+
|
|
195
|
+
.expand {
|
|
196
|
+
--button-width: var(--chat-header-expand-size, var(--chat-header-close-size, 36px));
|
|
197
|
+
--button-height: var(--chat-header-expand-size, var(--chat-header-close-size, 36px));
|
|
198
|
+
--button-padding: var(--chat-header-expand-padding, var(--chat-header-close-padding, 8px));
|
|
199
|
+
--button-border-radius: var(--chat-header-expand-border-radius, 50%);
|
|
200
|
+
--button-color: var(--chat-header-expand-background-color, transparent);
|
|
201
|
+
--button-text-color: var(--chat-header-expand-color, #52525b);
|
|
202
|
+
--button-hover-text-color: var(--chat-header-expand-color, #52525b);
|
|
203
|
+
--button-content-gap: 0px;
|
|
204
|
+
--button-hover-color: var(--chat-header-expand-hover-background-color, #f4f4f5);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.expand :global(svg) {
|
|
208
|
+
height: 100%;
|
|
209
|
+
width: 100%;
|
|
210
|
+
}
|
|
169
211
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ChatHeaderProperties } from './properties';
|
|
2
|
-
declare const ChatHeader: import("svelte").Component<ChatHeaderProperties, {}, "">;
|
|
2
|
+
declare const ChatHeader: import("svelte").Component<ChatHeaderProperties, {}, "expanded">;
|
|
3
3
|
type ChatHeader = ReturnType<typeof ChatHeader>;
|
|
4
4
|
export default ChatHeader;
|
|
@@ -7,6 +7,10 @@ export type OptionalChatHeaderProperties = {
|
|
|
7
7
|
imageAlt?: string;
|
|
8
8
|
avatar?: Snippet;
|
|
9
9
|
actions?: Snippet;
|
|
10
|
+
expanded?: boolean;
|
|
11
|
+
showExpand?: boolean;
|
|
12
|
+
expandLabel?: string;
|
|
13
|
+
collapseLabel?: string;
|
|
10
14
|
closeIcon?: Snippet;
|
|
11
15
|
closeLabel?: string;
|
|
12
16
|
showClose?: boolean;
|
|
@@ -16,4 +20,5 @@ export type OptionalChatHeaderProperties = {
|
|
|
16
20
|
};
|
|
17
21
|
export type ChatHeaderEventProperties = {
|
|
18
22
|
onclose?: () => void;
|
|
23
|
+
onexpandchange?: (expanded: boolean) => void;
|
|
19
24
|
};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Resizable from '../Resizable/Resizable.svelte';
|
|
3
|
+
import { registerDismissible } from '../_interaction/dismissal';
|
|
4
|
+
import type { ResizeSize } from '../Resizable/properties';
|
|
5
|
+
import type { DockPanelProperties, DockPanelSnapshot, DockPanelState } from './properties';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
state: panelState = $bindable('closed'),
|
|
9
|
+
width = $bindable(380),
|
|
10
|
+
minWidth = 300,
|
|
11
|
+
maxWidth = 600,
|
|
12
|
+
reservedWidth = $bindable(0),
|
|
13
|
+
label = 'Panel',
|
|
14
|
+
resizeLabel = 'Resize panel',
|
|
15
|
+
header,
|
|
16
|
+
body,
|
|
17
|
+
footer,
|
|
18
|
+
children,
|
|
19
|
+
testId,
|
|
20
|
+
classes,
|
|
21
|
+
onstatechange,
|
|
22
|
+
onwidthchange
|
|
23
|
+
}: DockPanelProperties = $props();
|
|
24
|
+
|
|
25
|
+
const lowerWidth = $derived(Number.isFinite(minWidth) ? Math.max(0, minWidth) : 300);
|
|
26
|
+
const upperWidth = $derived(
|
|
27
|
+
Number.isFinite(maxWidth) ? Math.max(lowerWidth, maxWidth) : Math.max(lowerWidth, 600)
|
|
28
|
+
);
|
|
29
|
+
const clampedWidth = $derived(
|
|
30
|
+
Math.min(upperWidth, Math.max(lowerWidth, Number.isFinite(width) ? width : 380))
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const changeState = (nextState: DockPanelState): void => {
|
|
34
|
+
if (panelState !== nextState) {
|
|
35
|
+
panelState = nextState;
|
|
36
|
+
onstatechange?.(nextState);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const expand = (): void => changeState('expanded');
|
|
40
|
+
const collapse = (): void => changeState('docked');
|
|
41
|
+
const close = (): void => changeState('closed');
|
|
42
|
+
|
|
43
|
+
const handleResize = (size: ResizeSize): void => {
|
|
44
|
+
const nextWidth = Math.min(upperWidth, Math.max(lowerWidth, size.width));
|
|
45
|
+
if (width !== nextWidth) {
|
|
46
|
+
width = nextWidth;
|
|
47
|
+
onwidthchange?.(width);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const synchronizePanel = (node: HTMLElement, snapshot: DockPanelSnapshot) => {
|
|
52
|
+
let releaseDismissal: (() => void) | null = null;
|
|
53
|
+
const update = (nextSnapshot: DockPanelSnapshot): void => {
|
|
54
|
+
if (width !== nextSnapshot.width) {
|
|
55
|
+
width = nextSnapshot.width;
|
|
56
|
+
onwidthchange?.(width);
|
|
57
|
+
}
|
|
58
|
+
const nextReservation = nextSnapshot.state === 'docked' ? nextSnapshot.width : 0;
|
|
59
|
+
if (reservedWidth !== nextReservation) {
|
|
60
|
+
reservedWidth = nextReservation;
|
|
61
|
+
}
|
|
62
|
+
if (nextSnapshot.state === 'expanded' && releaseDismissal === null) {
|
|
63
|
+
releaseDismissal = registerDismissible({ element: () => node, onEscape: collapse });
|
|
64
|
+
} else if (nextSnapshot.state !== 'expanded' && releaseDismissal !== null) {
|
|
65
|
+
releaseDismissal();
|
|
66
|
+
releaseDismissal = null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
update(snapshot);
|
|
70
|
+
return { update, destroy: () => releaseDismissal?.() };
|
|
71
|
+
};
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<div
|
|
75
|
+
class="dock-panel {classes ?? ''}"
|
|
76
|
+
class:closed={panelState === 'closed'}
|
|
77
|
+
class:expanded={panelState === 'expanded'}
|
|
78
|
+
data-state={panelState}
|
|
79
|
+
data-pw={typeof testId === 'string' ? testId : null}
|
|
80
|
+
testID={typeof testId === 'string' ? testId : null}
|
|
81
|
+
role="complementary"
|
|
82
|
+
aria-label={label}
|
|
83
|
+
inert={panelState === 'closed'}
|
|
84
|
+
use:synchronizePanel={{ state: panelState, width: clampedWidth }}
|
|
85
|
+
style:width={panelState === 'expanded' ? null : `${clampedWidth}px`}
|
|
86
|
+
>
|
|
87
|
+
<Resizable
|
|
88
|
+
width={panelState === 'docked' ? clampedWidth : null}
|
|
89
|
+
minWidth={lowerWidth}
|
|
90
|
+
maxWidth={upperWidth}
|
|
91
|
+
handles={panelState === 'docked' ? ['left'] : []}
|
|
92
|
+
handleLabel={resizeLabel}
|
|
93
|
+
onresize={handleResize}
|
|
94
|
+
classes="dock-panel-frame"
|
|
95
|
+
>
|
|
96
|
+
{#if typeof header === 'function'}
|
|
97
|
+
<div class="header">{@render header({ state: panelState, expand, collapse, close })}</div>
|
|
98
|
+
{/if}
|
|
99
|
+
<div class="body">
|
|
100
|
+
{#if typeof body === 'function'}
|
|
101
|
+
{@render body()}
|
|
102
|
+
{:else if typeof children === 'function'}
|
|
103
|
+
{@render children()}
|
|
104
|
+
{/if}
|
|
105
|
+
</div>
|
|
106
|
+
{#if typeof footer === 'function'}
|
|
107
|
+
<div class="footer">{@render footer()}</div>
|
|
108
|
+
{/if}
|
|
109
|
+
</Resizable>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<style>
|
|
113
|
+
.dock-panel {
|
|
114
|
+
box-sizing: border-box;
|
|
115
|
+
position: var(--dock-panel-position, fixed);
|
|
116
|
+
top: var(--dock-panel-top, 0px);
|
|
117
|
+
right: var(--dock-panel-right, 0px);
|
|
118
|
+
bottom: var(--dock-panel-bottom, 0px);
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
z-index: var(--dock-panel-z-index, 30);
|
|
123
|
+
background: var(--dock-panel-background, #ffffff);
|
|
124
|
+
color: var(--dock-panel-color, #18181b);
|
|
125
|
+
border-radius: var(--dock-panel-border-radius, 0px);
|
|
126
|
+
box-shadow: var(--dock-panel-box-shadow, -4px 0 16px #00000012);
|
|
127
|
+
opacity: 1;
|
|
128
|
+
transform: translateX(0);
|
|
129
|
+
transition:
|
|
130
|
+
opacity
|
|
131
|
+
var(--dock-panel-transition-duration, var(--duration-base, var(--motion-duration, 200ms)))
|
|
132
|
+
var(--dock-panel-transition-easing, var(--ease-smooth-out, var(--motion-easing, ease-out))),
|
|
133
|
+
transform
|
|
134
|
+
var(--dock-panel-transition-duration, var(--duration-base, var(--motion-duration, 200ms)))
|
|
135
|
+
var(--dock-panel-transition-easing, var(--ease-smooth-out, var(--motion-easing, ease-out))),
|
|
136
|
+
display
|
|
137
|
+
var(--dock-panel-transition-duration, var(--duration-base, var(--motion-duration, 200ms)))
|
|
138
|
+
allow-discrete;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.dock-panel.closed {
|
|
142
|
+
display: none;
|
|
143
|
+
opacity: 0;
|
|
144
|
+
transform: translateX(var(--dock-panel-enter-distance, var(--distance-base, 8px)));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.dock-panel.expanded {
|
|
148
|
+
left: var(--dock-panel-left, 0px);
|
|
149
|
+
width: calc(100% - var(--dock-panel-left, 0px) - var(--dock-panel-right, 0px));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.dock-panel :global(.dock-panel-frame) {
|
|
153
|
+
display: flex;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
flex: 1;
|
|
156
|
+
min-height: 0;
|
|
157
|
+
min-width: 0;
|
|
158
|
+
border: var(--dock-panel-border, 1px solid #e4e4e7);
|
|
159
|
+
--resizable-transition: none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.header {
|
|
163
|
+
flex-shrink: 0;
|
|
164
|
+
padding: var(--dock-panel-header-padding, 0px);
|
|
165
|
+
border-bottom: var(--dock-panel-header-border, none);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.body {
|
|
169
|
+
flex: 1;
|
|
170
|
+
min-height: 0;
|
|
171
|
+
overflow: auto;
|
|
172
|
+
padding: var(--dock-panel-body-padding, 0px);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.footer {
|
|
176
|
+
flex-shrink: 0;
|
|
177
|
+
padding: var(--dock-panel-footer-padding, 0px);
|
|
178
|
+
border-top: var(--dock-panel-footer-border, none);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@starting-style {
|
|
182
|
+
.dock-panel:not(.closed) {
|
|
183
|
+
opacity: 0;
|
|
184
|
+
transform: translateX(var(--dock-panel-enter-distance, var(--distance-base, 8px)));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@media (prefers-reduced-motion: reduce) {
|
|
189
|
+
.dock-panel {
|
|
190
|
+
transition: none;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export type DockPanelState = 'closed' | 'docked' | 'expanded';
|
|
3
|
+
export type DockPanelControls = {
|
|
4
|
+
state: DockPanelState;
|
|
5
|
+
expand: () => void;
|
|
6
|
+
collapse: () => void;
|
|
7
|
+
close: () => void;
|
|
8
|
+
};
|
|
9
|
+
export type DockPanelSnapshot = {
|
|
10
|
+
state: DockPanelState;
|
|
11
|
+
width: number;
|
|
12
|
+
};
|
|
13
|
+
export type DockPanelProperties = {
|
|
14
|
+
state?: DockPanelState;
|
|
15
|
+
width?: number;
|
|
16
|
+
minWidth?: number;
|
|
17
|
+
maxWidth?: number;
|
|
18
|
+
/** Published layout reservation. Bind to observe; zero when closed or expanded. */
|
|
19
|
+
reservedWidth?: number;
|
|
20
|
+
label?: string;
|
|
21
|
+
resizeLabel?: string;
|
|
22
|
+
header?: Snippet<[DockPanelControls]>;
|
|
23
|
+
body?: Snippet;
|
|
24
|
+
footer?: Snippet;
|
|
25
|
+
children?: Snippet;
|
|
26
|
+
testId?: string;
|
|
27
|
+
classes?: string;
|
|
28
|
+
onstatechange?: (state: DockPanelState) => void;
|
|
29
|
+
onwidthchange?: (width: number) => void;
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -88,8 +88,13 @@
|
|
|
88
88
|
event.preventDefault();
|
|
89
89
|
const startW = clampWidth(measuredWidth());
|
|
90
90
|
const startH = clampHeight(measuredHeight());
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const direction = DIRS[edge];
|
|
92
|
+
if (direction.x !== 0) {
|
|
93
|
+
width = startW;
|
|
94
|
+
}
|
|
95
|
+
if (direction.y !== 0) {
|
|
96
|
+
height = startH;
|
|
97
|
+
}
|
|
93
98
|
active = {
|
|
94
99
|
edge,
|
|
95
100
|
pointerId: event.pointerId,
|
|
@@ -137,18 +142,22 @@
|
|
|
137
142
|
let handled = false;
|
|
138
143
|
|
|
139
144
|
if (dir.x !== 0 && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {
|
|
140
|
-
nextWidth = clampWidth(nextWidth + (event.key === 'ArrowRight' ? step : -step));
|
|
145
|
+
nextWidth = clampWidth(nextWidth + dir.x * (event.key === 'ArrowRight' ? step : -step));
|
|
141
146
|
handled = true;
|
|
142
147
|
}
|
|
143
148
|
if (dir.y !== 0 && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
144
|
-
nextHeight = clampHeight(nextHeight + (event.key === 'ArrowDown' ? step : -step));
|
|
149
|
+
nextHeight = clampHeight(nextHeight + dir.y * (event.key === 'ArrowDown' ? step : -step));
|
|
145
150
|
handled = true;
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
if (handled) {
|
|
149
154
|
event.preventDefault();
|
|
150
|
-
|
|
151
|
-
|
|
155
|
+
if (dir.x !== 0 && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {
|
|
156
|
+
width = nextWidth;
|
|
157
|
+
}
|
|
158
|
+
if (dir.y !== 0 && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
159
|
+
height = nextHeight;
|
|
160
|
+
}
|
|
152
161
|
onresize?.({ width: nextWidth, height: nextHeight });
|
|
153
162
|
}
|
|
154
163
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { default as ArmedButton } from './ArmedButton/ArmedButton.svelte';
|
|
2
2
|
export { default as Modal } from './Modal/Modal.svelte';
|
|
3
|
+
export { default as DockPanel } from './DockPanel/DockPanel.svelte';
|
|
4
|
+
export type { DockPanelState, DockPanelControls, DockPanelProperties } from './DockPanel/properties';
|
|
3
5
|
export { default as BrandLoader } from './BrandLoader/BrandLoader.svelte';
|
|
4
6
|
export { default as Button } from './Button/Button.svelte';
|
|
5
7
|
export { default as Input } from './Input/Input.svelte';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as ArmedButton } from './ArmedButton/ArmedButton.svelte';
|
|
2
2
|
export { default as Modal } from './Modal/Modal.svelte';
|
|
3
|
+
export { default as DockPanel } from './DockPanel/DockPanel.svelte';
|
|
3
4
|
export { default as BrandLoader } from './BrandLoader/BrandLoader.svelte';
|
|
4
5
|
export { default as Button } from './Button/Button.svelte';
|
|
5
6
|
export { default as Input } from './Input/Input.svelte';
|
|
@@ -167,6 +167,11 @@
|
|
|
167
167
|
--chat-header-subtitle-color: #9ca3af;
|
|
168
168
|
--chat-header-close-color: #9ca3af;
|
|
169
169
|
--chat-header-close-hover-background-color: #252535;
|
|
170
|
+
--chat-header-expand-color: #9ca3af;
|
|
171
|
+
--chat-header-expand-hover-background-color: #252535;
|
|
172
|
+
--dock-panel-background: #17171f;
|
|
173
|
+
--dock-panel-color: #e5e7eb;
|
|
174
|
+
--dock-panel-border: 1px solid #30303d;
|
|
170
175
|
|
|
171
176
|
/* ChatMessageList */
|
|
172
177
|
--chat-message-list-jump-background-color: #1e1e2e;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* stylesheet is a crutch for the migration window, not a permanent override.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
/* components whose new default is `block` (
|
|
20
|
+
/* components whose new default is `block` (89) */
|
|
21
21
|
sui-accordion { --sui-accordion-display: inline; }
|
|
22
22
|
sui-area-chart { --sui-area-chart-display: inline; }
|
|
23
23
|
sui-aspect-ratio { --sui-aspect-ratio-display: inline; }
|
|
@@ -47,6 +47,7 @@ sui-color-picker { --sui-color-picker-display: inline; }
|
|
|
47
47
|
sui-combobox { --sui-combobox-display: inline; }
|
|
48
48
|
sui-command-menu { --sui-command-menu-display: inline; }
|
|
49
49
|
sui-context-menu { --sui-context-menu-display: inline; }
|
|
50
|
+
sui-dock-panel { --sui-dock-panel-display: inline; }
|
|
50
51
|
sui-draggable { --sui-draggable-display: inline; }
|
|
51
52
|
sui-dual-axis-bar-chart { --sui-dual-axis-bar-chart-display: inline; }
|
|
52
53
|
sui-empty-state { --sui-empty-state-display: inline; }
|
|
@@ -174,6 +174,11 @@
|
|
|
174
174
|
"property": "--sui-delta-indicator-display",
|
|
175
175
|
"default": "inline-block"
|
|
176
176
|
},
|
|
177
|
+
{
|
|
178
|
+
"tag": "sui-dock-panel",
|
|
179
|
+
"property": "--sui-dock-panel-display",
|
|
180
|
+
"default": "block"
|
|
181
|
+
},
|
|
177
182
|
{
|
|
178
183
|
"tag": "sui-draggable",
|
|
179
184
|
"property": "--sui-draggable-display",
|