@juspay/svelte-ui-components 4.36.0 → 4.37.1

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.
@@ -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,
@@ -497,6 +498,7 @@
497
498
  <div
498
499
  class="chat-composer {classes ?? ''}"
499
500
  class:disabled
501
+ class:pill={variant === 'pill'}
500
502
  data-has-slash={slashCommands !== null ? '' : null}
501
503
  data-pw={typeof testId === 'string' ? testId : null}
502
504
  testID={typeof testId === 'string' ? testId : null}
@@ -623,6 +625,10 @@
623
625
  opacity: var(--chat-composer-disabled-opacity, 0.6);
624
626
  }
625
627
 
628
+ .chat-composer.pill {
629
+ border-radius: var(--chat-composer-pill-border-radius, 999px);
630
+ }
631
+
626
632
  /* .input below sets outline: none with nothing standing in for it, so the
627
633
  visible replacement lives here on the surrounding surface instead --
628
634
  :focus-within lights up whenever the textarea inside is focused, the same
@@ -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
  /**
@@ -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,4 @@
1
+ import type { DockPanelProperties } from './properties';
2
+ declare const DockPanel: import("svelte").Component<DockPanelProperties, {}, "state" | "width" | "reservedWidth">;
3
+ type DockPanel = ReturnType<typeof DockPanel>;
4
+ export default DockPanel;
@@ -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 {};
@@ -142,11 +142,11 @@
142
142
  let handled = false;
143
143
 
144
144
  if (dir.x !== 0 && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) {
145
- nextWidth = clampWidth(nextWidth + (event.key === 'ArrowRight' ? step : -step));
145
+ nextWidth = clampWidth(nextWidth + dir.x * (event.key === 'ArrowRight' ? step : -step));
146
146
  handled = true;
147
147
  }
148
148
  if (dir.y !== 0 && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
149
- nextHeight = clampHeight(nextHeight + (event.key === 'ArrowDown' ? step : -step));
149
+ nextHeight = clampHeight(nextHeight + dir.y * (event.key === 'ArrowDown' ? step : -step));
150
150
  handled = true;
151
151
  }
152
152
 
@@ -1228,6 +1228,7 @@
1228
1228
  value={[String(effectivePageSize)]}
1229
1229
  disabled={pagination.isLoading ?? false}
1230
1230
  usePortal
1231
+ ariaLabel={labels?.rowsPerPage ?? 'Rows per page'}
1231
1232
  testId={pagination.testId && `${pagination.testId}-page-size`}
1232
1233
  onchange={(selectedSizes) => {
1233
1234
  if (selectedSizes.length > 0) {
@@ -520,8 +520,9 @@ export type TableProperties = OptionalTableProperties & TableEventProperties;
520
520
  * Accessible names Table generates for its own controls, for callers who do
521
521
  * not ship an English UI.
522
522
  *
523
- * Every member is optional and falls back to the English string Table has
524
- * always used, so adding this prop changes nothing for existing consumers.
523
+ * Every member is optional and falls back to an English default. All but
524
+ * `rowsPerPage` keep the string Table has always used; `rowsPerPage` adds a
525
+ * name to a control that previously had none.
525
526
  *
526
527
  * The two that depend on a column, and the one that depends on a row, are
527
528
  * functions rather than templates with a placeholder: a translator needs to
@@ -546,6 +547,8 @@ export type TableLabels = {
546
547
  clearSearch?: string;
547
548
  /** Button that dismisses the search box. Default: `Close search`. */
548
549
  closeSearch?: string;
550
+ /** Page-size selector in the built-in paginator footer. Default: `Rows per page`. */
551
+ rowsPerPage?: string;
549
552
  };
550
553
  export type OptionalTableProperties = {
551
554
  labels?: TableLabels;
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';
@@ -169,6 +169,9 @@
169
169
  --chat-header-close-hover-background-color: #252535;
170
170
  --chat-header-expand-color: #9ca3af;
171
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;
172
175
 
173
176
  /* ChatMessageList */
174
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` (88) */
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",