@lobb-js/studio 0.44.0 → 0.45.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.
@@ -210,6 +210,7 @@
210
210
  });
211
211
 
212
212
  let selectedRecords = $state([]);
213
+ let searchTerm = $state('');
213
214
  let totalCount = $state(0);
214
215
  let serverData: TableProps["data"] = $state([]);
215
216
  let loading = $state(true);
@@ -228,14 +229,15 @@
228
229
  const showLeftTools = $derived(!isSelectMode);
229
230
  let childrenDrawerEntry = $state<Record<string, any> | null>(null);
230
231
 
231
- // requests the data from the server when the params is changed
232
+ // requests the data from the server when params or searchTerm changes
232
233
  $effect(() => {
233
- loadData(params);
234
+ loadData(params, searchTerm);
234
235
  });
235
236
 
236
- async function loadData(params: any) {
237
+ async function loadData(params: any, search: string = '') {
237
238
  loading = true;
238
239
  const paramsCopy = $state.snapshot(params);
240
+ if (search.trim()) paramsCopy.search = search.trim();
239
241
  const sort: TableProps["sort"] = paramsCopy.sort;
240
242
  const sortStrings: string[] = [];
241
243
  if (sort) {
@@ -417,6 +419,7 @@
417
419
  onLink={isRecordingMode ? handleLink : undefined}
418
420
  onCreate={isRecordingMode ? handleCreate : undefined}
419
421
  {excludeIds}
422
+ bind:searchTerm
420
423
  >
421
424
  {#snippet left()}
422
425
  {@render headerLeft?.()}
@@ -477,7 +477,12 @@
477
477
  {@const kind = getFieldKind(rule.field)}
478
478
  {@const FieldIcon = getFieldIcon(ctx, rule.field, collectionName)}
479
479
  <!-- Field picker — typeahead popover, same widget Sort uses -->
480
- <Popover.Root bind:open={fieldPickerOpen[rule.id]}>
480
+ <Popover.Root
481
+ bind:open={
482
+ () => fieldPickerOpen[rule.id] ?? false,
483
+ (v) => (fieldPickerOpen[rule.id] = v)
484
+ }
485
+ >
481
486
  <Popover.Trigger
482
487
  class="inline-flex h-7 w-36 items-center justify-between gap-1.5 rounded-md border bg-muted px-2 text-xs"
483
488
  >
@@ -64,6 +64,7 @@
64
64
  {/if}
65
65
  </Popover.Trigger>
66
66
  <Popover.Content
67
+ trapFocus={false}
67
68
  class="
68
69
  w-screen p-0
69
70
  transition-[max-width] duration-150
@@ -3,7 +3,7 @@
3
3
  import type { Changes } from "../detailView/utils";
4
4
  import type { ParentContext } from "./dataTable.svelte";
5
5
  import CanAccess from "../canAccess.svelte";
6
- import { Download, ListRestart, LoaderCircle, Plus, Trash, Link } from "lucide-svelte";
6
+ import { Download, ListRestart, LoaderCircle, Plus, Trash, Link, Search } from "lucide-svelte";
7
7
  import FilterButton from "./filterButton.svelte";
8
8
  import SortButton from "./sortButton.svelte";
9
9
  import Button from "../ui/button/button.svelte";
@@ -30,6 +30,7 @@
30
30
  loading?: boolean;
31
31
  left?: Snippet<[]>;
32
32
  excludeIds?: (string | number)[];
33
+ searchTerm?: string;
33
34
  }
34
35
 
35
36
  let {
@@ -45,6 +46,7 @@
45
46
  loading = false,
46
47
  left,
47
48
  excludeIds = [],
49
+ searchTerm = $bindable(''),
48
50
  }: Props = $props();
49
51
 
50
52
  function handleLink(record: any) {
@@ -139,9 +141,18 @@
139
141
  bind:sort={params.sort}
140
142
  showText={!headerIsSmall}
141
143
  />
144
+ <div class="relative flex items-center">
145
+ <Search size="13" class="absolute left-2 text-muted-foreground pointer-events-none" />
146
+ <input
147
+ type="text"
148
+ placeholder="Search..."
149
+ bind:value={searchTerm}
150
+ class="h-8 rounded-md border bg-muted pl-7 pr-2 text-xs outline-none focus:ring-1 focus:ring-ring w-40"
151
+ />
152
+ </div>
142
153
  {/if}
143
154
  </div>
144
- <div>
155
+ <div class="flex items-center gap-1">
145
156
  <Button
146
157
  variant="ghost"
147
158
  size="sm"
@@ -14,7 +14,8 @@ interface Props {
14
14
  loading?: boolean;
15
15
  left?: Snippet<[]>;
16
16
  excludeIds?: (string | number)[];
17
+ searchTerm?: string;
17
18
  }
18
- declare const Header: import("svelte").Component<Props, {}, "selectedRecords" | "params">;
19
+ declare const Header: import("svelte").Component<Props, {}, "selectedRecords" | "params" | "searchTerm">;
19
20
  type Header = ReturnType<typeof Header>;
20
21
  export default Header;
@@ -208,6 +208,7 @@
208
208
  class="
209
209
  sticky top-0 z-10
210
210
  flex items-center p-2.5 text-xs h-10
211
+ min-w-0
211
212
  bg-muted
212
213
  {lastColumn && !showLastColumnBorder ? '' : 'border-r'}
213
214
  border-b gap-2
@@ -276,7 +277,7 @@
276
277
  onclick={() => {
277
278
  select?.onSelect(entry);
278
279
  }}
279
- class="flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip bg-card {select ? 'cursor-pointer hover:bg-accent' : ''} {lastColumn && !showLastColumnBorder ? '' : 'border-r'} {onCellClass?.(entry, index + 1) ?? ''}"
280
+ class="flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip min-w-0 bg-card {select ? 'cursor-pointer hover:bg-accent' : ''} {lastColumn && !showLastColumnBorder ? '' : 'border-r'} {onCellClass?.(entry, index + 1) ?? ''}"
280
281
  >
281
282
  {#if overrideCell}
282
283
  {@render overrideCell(fieldValue, column, entry)}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lobb-js/studio",
3
3
  "license": "UNLICENSED",
4
- "version": "0.44.0",
4
+ "version": "0.45.0",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -45,7 +45,7 @@
45
45
  "postpublish": "./scripts/postpublish.sh"
46
46
  },
47
47
  "devDependencies": {
48
- "@lobb-js/core": "^0.38.0",
48
+ "@lobb-js/core": "^0.39.0",
49
49
  "@chromatic-com/storybook": "^4.1.2",
50
50
  "@playwright/test": "^1.60.0",
51
51
  "@storybook/addon-a11y": "^10.0.1",
@@ -210,6 +210,7 @@
210
210
  });
211
211
 
212
212
  let selectedRecords = $state([]);
213
+ let searchTerm = $state('');
213
214
  let totalCount = $state(0);
214
215
  let serverData: TableProps["data"] = $state([]);
215
216
  let loading = $state(true);
@@ -228,14 +229,15 @@
228
229
  const showLeftTools = $derived(!isSelectMode);
229
230
  let childrenDrawerEntry = $state<Record<string, any> | null>(null);
230
231
 
231
- // requests the data from the server when the params is changed
232
+ // requests the data from the server when params or searchTerm changes
232
233
  $effect(() => {
233
- loadData(params);
234
+ loadData(params, searchTerm);
234
235
  });
235
236
 
236
- async function loadData(params: any) {
237
+ async function loadData(params: any, search: string = '') {
237
238
  loading = true;
238
239
  const paramsCopy = $state.snapshot(params);
240
+ if (search.trim()) paramsCopy.search = search.trim();
239
241
  const sort: TableProps["sort"] = paramsCopy.sort;
240
242
  const sortStrings: string[] = [];
241
243
  if (sort) {
@@ -417,6 +419,7 @@
417
419
  onLink={isRecordingMode ? handleLink : undefined}
418
420
  onCreate={isRecordingMode ? handleCreate : undefined}
419
421
  {excludeIds}
422
+ bind:searchTerm
420
423
  >
421
424
  {#snippet left()}
422
425
  {@render headerLeft?.()}
@@ -477,7 +477,12 @@
477
477
  {@const kind = getFieldKind(rule.field)}
478
478
  {@const FieldIcon = getFieldIcon(ctx, rule.field, collectionName)}
479
479
  <!-- Field picker — typeahead popover, same widget Sort uses -->
480
- <Popover.Root bind:open={fieldPickerOpen[rule.id]}>
480
+ <Popover.Root
481
+ bind:open={
482
+ () => fieldPickerOpen[rule.id] ?? false,
483
+ (v) => (fieldPickerOpen[rule.id] = v)
484
+ }
485
+ >
481
486
  <Popover.Trigger
482
487
  class="inline-flex h-7 w-36 items-center justify-between gap-1.5 rounded-md border bg-muted px-2 text-xs"
483
488
  >
@@ -64,6 +64,7 @@
64
64
  {/if}
65
65
  </Popover.Trigger>
66
66
  <Popover.Content
67
+ trapFocus={false}
67
68
  class="
68
69
  w-screen p-0
69
70
  transition-[max-width] duration-150
@@ -3,7 +3,7 @@
3
3
  import type { Changes } from "../detailView/utils";
4
4
  import type { ParentContext } from "./dataTable.svelte";
5
5
  import CanAccess from "../canAccess.svelte";
6
- import { Download, ListRestart, LoaderCircle, Plus, Trash, Link } from "lucide-svelte";
6
+ import { Download, ListRestart, LoaderCircle, Plus, Trash, Link, Search } from "lucide-svelte";
7
7
  import FilterButton from "./filterButton.svelte";
8
8
  import SortButton from "./sortButton.svelte";
9
9
  import Button from "../ui/button/button.svelte";
@@ -30,6 +30,7 @@
30
30
  loading?: boolean;
31
31
  left?: Snippet<[]>;
32
32
  excludeIds?: (string | number)[];
33
+ searchTerm?: string;
33
34
  }
34
35
 
35
36
  let {
@@ -45,6 +46,7 @@
45
46
  loading = false,
46
47
  left,
47
48
  excludeIds = [],
49
+ searchTerm = $bindable(''),
48
50
  }: Props = $props();
49
51
 
50
52
  function handleLink(record: any) {
@@ -139,9 +141,18 @@
139
141
  bind:sort={params.sort}
140
142
  showText={!headerIsSmall}
141
143
  />
144
+ <div class="relative flex items-center">
145
+ <Search size="13" class="absolute left-2 text-muted-foreground pointer-events-none" />
146
+ <input
147
+ type="text"
148
+ placeholder="Search..."
149
+ bind:value={searchTerm}
150
+ class="h-8 rounded-md border bg-muted pl-7 pr-2 text-xs outline-none focus:ring-1 focus:ring-ring w-40"
151
+ />
152
+ </div>
142
153
  {/if}
143
154
  </div>
144
- <div>
155
+ <div class="flex items-center gap-1">
145
156
  <Button
146
157
  variant="ghost"
147
158
  size="sm"
@@ -208,6 +208,7 @@
208
208
  class="
209
209
  sticky top-0 z-10
210
210
  flex items-center p-2.5 text-xs h-10
211
+ min-w-0
211
212
  bg-muted
212
213
  {lastColumn && !showLastColumnBorder ? '' : 'border-r'}
213
214
  border-b gap-2
@@ -276,7 +277,7 @@
276
277
  onclick={() => {
277
278
  select?.onSelect(entry);
278
279
  }}
279
- class="flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip bg-card {select ? 'cursor-pointer hover:bg-accent' : ''} {lastColumn && !showLastColumnBorder ? '' : 'border-r'} {onCellClass?.(entry, index + 1) ?? ''}"
280
+ class="flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip min-w-0 bg-card {select ? 'cursor-pointer hover:bg-accent' : ''} {lastColumn && !showLastColumnBorder ? '' : 'border-r'} {onCellClass?.(entry, index + 1) ?? ''}"
280
281
  >
281
282
  {#if overrideCell}
282
283
  {@render overrideCell(fieldValue, column, entry)}