@juspay/svelte-ui-components 2.125.0 → 2.126.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.
@@ -5,6 +5,7 @@
5
5
  import type { JSONValue } from 'type-decoder';
6
6
  import { SvelteSet } from 'svelte/reactivity';
7
7
  import Button from '../Button/Button.svelte';
8
+ import Input from '../Input/Input.svelte';
8
9
  import Menu from '../Menu/Menu.svelte';
9
10
  import Tooltip from '../Tooltip/Tooltip.svelte';
10
11
  import Pagination from '../Pagination/Pagination.svelte';
@@ -169,23 +170,39 @@
169
170
  let hasSearchConfig = $derived(!!searchConfig);
170
171
  let isServerSearch = $derived(typeof onSearchChange === 'function');
171
172
  let searchInputRef = $state<HTMLInputElement | null>(null);
173
+ let inlineSearchInputRef = $state<{ focus: () => void } | null>(null);
174
+ let isInlineSearch = $derived(searchConfig?.displayMode === 'inline');
175
+ let isInlineSearchExpanded = $state(false);
176
+
177
+ const updateSearch = (term: string): void => {
178
+ searchTerm = term;
179
+ pageOverride = 1;
180
+ pagination?.onPageChange?.(1);
181
+ if (isServerSearch) {
182
+ onSearchChange?.(term);
183
+ }
184
+ };
172
185
 
173
186
  const handleSearchInput = (): void => {
174
187
  if (!searchInputRef) {
175
188
  return;
176
189
  }
177
- searchTerm = searchInputRef.value;
178
- pageOverride = 1;
179
- if (isServerSearch) {
180
- onSearchChange?.(searchTerm);
181
- }
190
+ updateSearch(searchInputRef.value);
182
191
  };
183
192
 
184
193
  const clearSearch = (): void => {
185
- searchTerm = '';
186
- pageOverride = 1;
187
- if (isServerSearch) {
188
- onSearchChange?.('');
194
+ updateSearch('');
195
+ isInlineSearchExpanded = false;
196
+ };
197
+
198
+ const expandInlineSearch = (): void => {
199
+ isInlineSearchExpanded = true;
200
+ queueMicrotask(() => inlineSearchInputRef?.focus());
201
+ };
202
+
203
+ const collapseInlineSearchIfEmpty = (): void => {
204
+ if (searchTerm.trim() === '') {
205
+ clearSearch();
189
206
  }
190
207
  };
191
208
 
@@ -561,7 +578,7 @@
561
578
  </div>
562
579
  {/if}
563
580
 
564
- {#if hasSearchConfig}
581
+ {#if hasSearchConfig && !isInlineSearch}
565
582
  <div class="table-search">
566
583
  <span class="table-search-icon">
567
584
  <!-- eslint-disable svelte/no-at-html-tags -->
@@ -773,6 +790,51 @@
773
790
  </Button>
774
791
  </div>
775
792
  {/if}
793
+ {#if hasSearchConfig && isInlineSearch && colIndex === effectiveHeaders.length - 1}
794
+ <span class="table-header-inline-search">
795
+ {#if isInlineSearchExpanded}
796
+ <Input
797
+ bind:this={inlineSearchInputRef}
798
+ bind:value={searchTerm}
799
+ placeholder={searchConfig?.placeholder ?? 'Search…'}
800
+ testId={searchConfig?.testId ?? ''}
801
+ ariaLabel={searchConfig?.placeholder ?? 'Search'}
802
+ autoComplete="off"
803
+ onInput={(value: string) => updateSearch(value)}
804
+ onBlur={collapseInlineSearchIfEmpty}
805
+ classes="table-inline-search-input"
806
+ />
807
+ <span class="table-inline-search-clear">
808
+ <Button
809
+ variant="ghost"
810
+ iconOnly={true}
811
+ ariaLabel="Close search"
812
+ onclick={clearSearch}
813
+ >
814
+ {#snippet icon()}
815
+ <!-- eslint-disable svelte/no-at-html-tags -->
816
+ {@html closeSvg}
817
+ {/snippet}
818
+ </Button>
819
+ </span>
820
+ {:else}
821
+ <span class="table-inline-search-trigger">
822
+ <Button
823
+ variant="ghost"
824
+ iconOnly={true}
825
+ ariaLabel={searchConfig?.placeholder ?? 'Search'}
826
+ testId={searchConfig?.testId && `${searchConfig.testId}-trigger`}
827
+ onclick={expandInlineSearch}
828
+ >
829
+ {#snippet icon()}
830
+ <!-- eslint-disable svelte/no-at-html-tags -->
831
+ {@html searchSvg}
832
+ {/snippet}
833
+ </Button>
834
+ </span>
835
+ {/if}
836
+ </span>
837
+ {/if}
776
838
  </span>
777
839
  </th>
778
840
  {/each}
@@ -1052,6 +1114,43 @@
1052
1114
  height: var(--table-search-clear-icon-size, 14px);
1053
1115
  }
1054
1116
 
1117
+ .table-header-inline-search {
1118
+ display: inline-flex;
1119
+ align-items: center;
1120
+ gap: var(--table-inline-search-gap, 6px);
1121
+ margin-left: auto;
1122
+ }
1123
+
1124
+ .table-inline-search-trigger {
1125
+ --button-color: transparent;
1126
+ --button-border: none;
1127
+ --button-padding: var(--table-inline-search-trigger-padding, 4px);
1128
+ --button-text-color: var(--table-inline-search-icon-color, #9ca3af);
1129
+ }
1130
+
1131
+ .table-inline-search-trigger :global(svg) {
1132
+ width: var(--table-inline-search-icon-size, 16px);
1133
+ height: var(--table-inline-search-icon-size, 16px);
1134
+ display: block;
1135
+ }
1136
+
1137
+ .table-inline-search-input {
1138
+ --input-margin: 0;
1139
+ width: var(--table-inline-search-input-width, 160px);
1140
+ }
1141
+
1142
+ .table-inline-search-clear {
1143
+ --button-color: transparent;
1144
+ --button-border: none;
1145
+ --button-padding: var(--table-inline-search-clear-padding, 2px);
1146
+ --button-text-color: var(--table-inline-search-clear-color, #6b7280);
1147
+ }
1148
+
1149
+ .table-inline-search-clear :global(svg) {
1150
+ width: var(--table-inline-search-clear-icon-size, 14px);
1151
+ height: var(--table-inline-search-clear-icon-size, 14px);
1152
+ }
1153
+
1055
1154
  /* ── Container ──────────────────────────────────────────────────────────── */
1056
1155
  .table-container {
1057
1156
  border: var(--table-border, 1px solid #e5e7eb);
@@ -361,6 +361,7 @@ export type TableSearchConfig = {
361
361
  placeholder?: string;
362
362
  searchableColumnIndices?: number[];
363
363
  testId?: string;
364
+ displayMode?: 'toolbar' | 'inline';
364
365
  };
365
366
  export type TableProperties = OptionalTableProperties & TableEventProperties;
366
367
  export type OptionalTableProperties = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.125.0",
3
+ "version": "2.126.0",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",