@lobb-js/studio 0.43.0 → 0.44.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.
- package/dist/components/dataTable/dataTable.svelte +7 -1
- package/dist/components/dataTable/filter.svelte +30 -22
- package/dist/components/dataTable/filterButton.svelte +1 -0
- package/dist/components/dataTable/header.svelte +17 -13
- package/dist/components/dataTable/header.svelte.d.ts +1 -0
- package/dist/components/dataTable/table.svelte +17 -9
- package/dist/components/dataTable/table.svelte.d.ts +1 -0
- package/dist/components/foreingKeyInput.svelte +26 -149
- package/dist/components/polymorphicInput.svelte +19 -92
- package/package.json +2 -2
- package/src/app.css +2 -2
- package/src/lib/components/dataTable/dataTable.svelte +7 -1
- package/src/lib/components/dataTable/filter.svelte +30 -22
- package/src/lib/components/dataTable/filterButton.svelte +1 -0
- package/src/lib/components/dataTable/header.svelte +17 -13
- package/src/lib/components/dataTable/table.svelte +17 -9
- package/src/lib/components/foreingKeyInput.svelte +26 -149
- package/src/lib/components/polymorphicInput.svelte +19 -92
|
@@ -4,12 +4,8 @@
|
|
|
4
4
|
import DataTable from "./dataTable/dataTable.svelte";
|
|
5
5
|
import Drawer from "./drawer.svelte";
|
|
6
6
|
import * as Popover from "./ui/popover/index";
|
|
7
|
-
import {
|
|
8
|
-
import { ArrowLeft, Link, ChevronDown, Plus, Pencil, Unlink, Trash, RotateCcw, RefreshCw } from "lucide-svelte";
|
|
7
|
+
import { ArrowLeft, Link, ChevronDown, Plus } from "lucide-svelte";
|
|
9
8
|
import CreateDetailView from "./detailView/create/createDetailView.svelte";
|
|
10
|
-
import UpdateDetailView from "./detailView/update/updateDetailView.svelte";
|
|
11
|
-
|
|
12
|
-
const { ctx, lobb } = getStudioContext();
|
|
13
9
|
|
|
14
10
|
interface Props {
|
|
15
11
|
collectionField: string;
|
|
@@ -29,41 +25,33 @@
|
|
|
29
25
|
destructive,
|
|
30
26
|
}: Props = $props();
|
|
31
27
|
|
|
32
|
-
|
|
33
28
|
const selectedCollection = $derived(entry[collectionField] ?? null);
|
|
34
29
|
const selectedId = $derived(entry[idField] ?? null);
|
|
35
30
|
const virtualVal = $derived(entry[virtualField] ?? null);
|
|
36
31
|
|
|
37
32
|
let initialId = $state<number | null | undefined>(undefined);
|
|
38
|
-
let
|
|
39
|
-
onMount(() => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
let initialCollection = $state<string | null | undefined>(undefined);
|
|
34
|
+
onMount(() => {
|
|
35
|
+
initialId = entry[idField] ?? null;
|
|
36
|
+
initialCollection = entry[collectionField] ?? null;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const isPendingCreate = $derived(virtualVal && typeof virtualVal === 'object' && virtualVal.create);
|
|
40
|
+
const isChanged = $derived(
|
|
41
|
+
initialId !== undefined &&
|
|
42
|
+
!isPendingCreate &&
|
|
43
|
+
(selectedId !== initialId || selectedCollection !== initialCollection)
|
|
44
|
+
);
|
|
50
45
|
|
|
51
46
|
const bgClass = $derived(
|
|
52
|
-
isPendingCreate ? '!bg-green-500/5 border-green-500/40'
|
|
53
|
-
|
|
54
|
-
isReplaced ? '!bg-orange-500/5 border-orange-500/40' :
|
|
55
|
-
isPendingEdit ? '!bg-orange-500/5 border-orange-500/40' :
|
|
56
|
-
isStagedUnlink ? '!bg-slate-500/5 border-slate-500/40' :
|
|
57
|
-
isStagedDelete ? '!bg-red-500/5 border-red-500/40' :
|
|
47
|
+
isPendingCreate ? '!bg-green-500/5 border-green-500/40' :
|
|
48
|
+
isChanged ? '!bg-orange-500/5' :
|
|
58
49
|
''
|
|
59
50
|
);
|
|
60
51
|
|
|
61
52
|
let collectionPopoverOpen = $state(false);
|
|
62
53
|
let recordDrawerOpen = $state(false);
|
|
63
54
|
let createDrawerOpen = $state(false);
|
|
64
|
-
let editDrawerOpen = $state(false);
|
|
65
|
-
let editValues: Record<string, any> | undefined = $state(undefined);
|
|
66
|
-
let originalSnapshot: { collection: string; id: number } | null = $state(null);
|
|
67
55
|
|
|
68
56
|
function onCollectionChange(col: string) {
|
|
69
57
|
collectionPopoverOpen = false;
|
|
@@ -75,7 +63,7 @@
|
|
|
75
63
|
function onIdChange(e: Event) {
|
|
76
64
|
const raw = (e.target as HTMLInputElement).value;
|
|
77
65
|
const id = raw === "" ? null : Number(raw);
|
|
78
|
-
entry = { ...entry, [idField]: id };
|
|
66
|
+
entry = { ...entry, [idField]: id, [virtualField]: undefined };
|
|
79
67
|
}
|
|
80
68
|
|
|
81
69
|
function onRecordSelect(record: any) {
|
|
@@ -90,50 +78,9 @@
|
|
|
90
78
|
entry = { ...entry, [idField]: record.id, [virtualField]: undefined };
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
|
-
|
|
94
|
-
async function openEdit() {
|
|
95
|
-
const res = await lobb.findAll(selectedCollection!, { filter: { id: selectedId }, limit: 1 });
|
|
96
|
-
const result = await res.json();
|
|
97
|
-
editValues = result.data[0];
|
|
98
|
-
editDrawerOpen = true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function handleEditChanges(changes: import('./detailView/utils').Changes) {
|
|
102
|
-
if (Object.keys(changes.data).length === 0) {
|
|
103
|
-
entry = { ...entry, [virtualField]: undefined };
|
|
104
|
-
} else {
|
|
105
|
-
entry = { ...entry, [virtualField]: { collection: selectedCollection, id: selectedId, update: changes.data } };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function handleUnlink() {
|
|
110
|
-
if (hasRealValue) {
|
|
111
|
-
originalSnapshot = { collection: selectedCollection!, id: selectedId! };
|
|
112
|
-
unlinked = true;
|
|
113
|
-
entry = { ...entry, [collectionField]: null, [idField]: null, [virtualField]: undefined };
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function handleDelete() {
|
|
118
|
-
if (hasRealValue) {
|
|
119
|
-
originalSnapshot = { collection: selectedCollection!, id: selectedId! };
|
|
120
|
-
entry = { ...entry, [virtualField]: { delete: true } };
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function handleRevert() {
|
|
125
|
-
if (originalSnapshot) {
|
|
126
|
-
entry = { ...entry, [collectionField]: originalSnapshot.collection, [idField]: originalSnapshot.id, [virtualField]: undefined };
|
|
127
|
-
originalSnapshot = null;
|
|
128
|
-
} else {
|
|
129
|
-
entry = { ...entry, [collectionField]: null, [idField]: null, [virtualField]: undefined };
|
|
130
|
-
}
|
|
131
|
-
unlinked = false;
|
|
132
|
-
}
|
|
133
81
|
</script>
|
|
134
82
|
|
|
135
83
|
<div class="flex h-9 w-full items-center gap-1.5 rounded-md border pl-1.5 pr-9 text-xs bg-muted {bgClass} {destructive ? '!bg-destructive/10 border-destructive' : ''}">
|
|
136
|
-
<!-- Collection picker -->
|
|
137
84
|
<Popover.Root bind:open={collectionPopoverOpen}>
|
|
138
85
|
<Popover.Trigger>
|
|
139
86
|
{#snippet child({ props })}
|
|
@@ -161,25 +108,15 @@
|
|
|
161
108
|
</Popover.Content>
|
|
162
109
|
</Popover.Root>
|
|
163
110
|
|
|
164
|
-
<!-- ID input (only editable when real value or empty) -->
|
|
165
111
|
<input
|
|
166
|
-
placeholder="NULL"
|
|
112
|
+
placeholder={isPendingCreate ? "AUTO GENERATED" : "NULL"}
|
|
167
113
|
type="number"
|
|
168
114
|
class="min-w-0 flex-1 bg-transparent outline-none text-xs placeholder:text-muted-foreground"
|
|
169
|
-
value={
|
|
170
|
-
disabled={isPendingCreate || isPendingEdit}
|
|
115
|
+
value={selectedId ?? ""}
|
|
171
116
|
oninput={onIdChange}
|
|
172
117
|
/>
|
|
173
118
|
|
|
174
|
-
|
|
175
|
-
{#if isStagedUnlink || isStagedDelete || isPendingCreate || isPendingEdit}
|
|
176
|
-
<Button class="h-5 w-5 px-0 shrink-0 hover:bg-transparent text-muted-foreground" variant="ghost" Icon={RotateCcw} onclick={handleRevert} title="Revert"></Button>
|
|
177
|
-
{:else if hasRealValue}
|
|
178
|
-
<Button class="h-5 w-5 px-0 shrink-0 hover:bg-transparent text-muted-foreground" variant="ghost" Icon={Trash} onclick={handleDelete} title="Delete record"></Button>
|
|
179
|
-
<Button class="h-5 w-5 px-0 shrink-0 hover:bg-transparent text-muted-foreground" variant="ghost" Icon={Unlink} onclick={handleUnlink} title="Unlink"></Button>
|
|
180
|
-
<Button class="h-5 w-5 px-0 shrink-0 hover:bg-transparent text-muted-foreground" variant="ghost" Icon={Pencil} onclick={openEdit} title="Edit record"></Button>
|
|
181
|
-
<Button class="h-5 w-5 px-0 shrink-0 hover:bg-transparent text-muted-foreground" variant="ghost" Icon={RefreshCw} onclick={() => (recordDrawerOpen = true)} title="Replace"></Button>
|
|
182
|
-
{:else if selectedCollection && !isPendingCreate}
|
|
119
|
+
{#if selectedCollection}
|
|
183
120
|
<Button class="h-6 shrink-0 px-2 font-normal text-xs" variant="outline" onclick={() => (createDrawerOpen = true)}>
|
|
184
121
|
<Plus size="13" />
|
|
185
122
|
Create
|
|
@@ -218,13 +155,3 @@
|
|
|
218
155
|
onCancel={async () => { createDrawerOpen = false; }}
|
|
219
156
|
/>
|
|
220
157
|
{/if}
|
|
221
|
-
|
|
222
|
-
{#if editDrawerOpen && editValues && selectedCollection}
|
|
223
|
-
<UpdateDetailView
|
|
224
|
-
collectionName={selectedCollection}
|
|
225
|
-
recordId={String(editValues.id)}
|
|
226
|
-
values={editValues}
|
|
227
|
-
onChanges={handleEditChanges}
|
|
228
|
-
onCancel={async () => { editDrawerOpen = false; editValues = undefined; }}
|
|
229
|
-
/>
|
|
230
|
-
{/if}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/studio",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.44.1",
|
|
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.
|
|
48
|
+
"@lobb-js/core": "^0.38.1",
|
|
49
49
|
"@chromatic-com/storybook": "^4.1.2",
|
|
50
50
|
"@playwright/test": "^1.60.0",
|
|
51
51
|
"@storybook/addon-a11y": "^10.0.1",
|
package/src/app.css
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
--secondary: oklch(0.97 0.001 138);
|
|
25
25
|
--secondary-foreground: oklch(0.20 0.012 138);
|
|
26
26
|
|
|
27
|
-
--muted: oklch(0.
|
|
27
|
+
--muted: oklch(0.98 0.001 138);
|
|
28
28
|
--muted-foreground: oklch(0.55 0.012 138);
|
|
29
29
|
|
|
30
30
|
--accent: oklch(0.95 0.001 138);
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
--secondary: oklch(0.24 0.012 138);
|
|
53
53
|
--secondary-foreground: oklch(0.94 0.012 138);
|
|
54
54
|
|
|
55
|
-
--muted: oklch(0.
|
|
55
|
+
--muted: oklch(0.28 0.012 138);
|
|
56
56
|
--muted-foreground: oklch(0.65 0.012 138);
|
|
57
57
|
|
|
58
58
|
--accent: oklch(0.27 0.012 138);
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
}: Props = $props();
|
|
76
76
|
|
|
77
77
|
const isRecordingMode = onChanges !== undefined;
|
|
78
|
+
const isSelectMode = $derived(tableProps?.select != null);
|
|
78
79
|
let localChanges = $state<ChildrenChanges>(
|
|
79
80
|
untrack(() => changes) ?? { created: [], updated: [], deleted: [], linked: [], unlinked: [] }
|
|
80
81
|
);
|
|
@@ -222,6 +223,9 @@
|
|
|
222
223
|
(ctx.meta.collections[collectionName]?.children ?? [])
|
|
223
224
|
.some((c: any) => c.type === "fk" || c.type === "m2m" || c.type === "polymorphic")
|
|
224
225
|
);
|
|
226
|
+
// Select-mode drawer has no checkbox, edit, delete, or unlink — the
|
|
227
|
+
// left-sticky tools column would render empty, so drop it entirely.
|
|
228
|
+
const showLeftTools = $derived(!isSelectMode);
|
|
225
229
|
let childrenDrawerEntry = $state<Record<string, any> | null>(null);
|
|
226
230
|
|
|
227
231
|
// requests the data from the server when the params is changed
|
|
@@ -407,6 +411,7 @@
|
|
|
407
411
|
bind:selectedRecords
|
|
408
412
|
{showImport}
|
|
409
413
|
{showFilter}
|
|
414
|
+
showCreate={!isSelectMode}
|
|
410
415
|
{loading}
|
|
411
416
|
{parentContext}
|
|
412
417
|
onLink={isRecordingMode ? handleLink : undefined}
|
|
@@ -463,6 +468,7 @@
|
|
|
463
468
|
bind:selectedRecords
|
|
464
469
|
bind:tableWidth={dataTableWidth}
|
|
465
470
|
{...tableProps}
|
|
471
|
+
{showLeftTools}
|
|
466
472
|
rowActions={hasRowActions ? rowActionsSnippet : undefined}
|
|
467
473
|
onCellClass={isRecordingMode ? onCellClass : undefined}>
|
|
468
474
|
{#snippet preTools(entry)}
|
|
@@ -480,7 +486,7 @@
|
|
|
480
486
|
{/snippet}
|
|
481
487
|
{#snippet tools(entry)}
|
|
482
488
|
{#if entry._recordingState !== 'deleted' && entry._recordingState !== 'unlinked'}
|
|
483
|
-
{#if showEdit}
|
|
489
|
+
{#if showEdit && !isSelectMode}
|
|
484
490
|
{@const isPending = entry._recordingState === 'created'}
|
|
485
491
|
<CanAccess collection={collectionName} action="update">
|
|
486
492
|
<UpdateDetailViewButton
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
// • anything else → explicit $and/$or arrays.
|
|
21
21
|
|
|
22
22
|
import * as Select from "../ui/select/index.js";
|
|
23
|
+
import * as Popover from "../ui/popover/index.js";
|
|
23
24
|
import Button from "../ui/button/button.svelte";
|
|
24
|
-
import { Plus, X, Boxes, Settings2 } from "lucide-svelte";
|
|
25
|
+
import { ChevronDown, Plus, X, Boxes, Settings2 } from "lucide-svelte";
|
|
25
26
|
import { getStudioContext } from "../../context";
|
|
26
27
|
import { getFieldIcon } from "./utils";
|
|
27
28
|
import { getFieldRelationTarget } from "../../relations";
|
|
29
|
+
import FieldPicker from "./fieldPicker.svelte";
|
|
28
30
|
|
|
29
31
|
const { ctx } = getStudioContext();
|
|
30
32
|
|
|
@@ -43,6 +45,9 @@
|
|
|
43
45
|
isEmpty = $bindable(true),
|
|
44
46
|
}: Props = $props();
|
|
45
47
|
|
|
48
|
+
// Per-rule open state for the field-picker popovers.
|
|
49
|
+
let fieldPickerOpen = $state<Record<string, boolean>>({});
|
|
50
|
+
|
|
46
51
|
type OperatorDef = {
|
|
47
52
|
value: string;
|
|
48
53
|
label: string;
|
|
@@ -471,30 +476,33 @@
|
|
|
471
476
|
{@const currentOp = ops.find((o) => o.value === rule.operator) ?? ops[0]}
|
|
472
477
|
{@const kind = getFieldKind(rule.field)}
|
|
473
478
|
{@const FieldIcon = getFieldIcon(ctx, rule.field, collectionName)}
|
|
474
|
-
<!-- Field picker -->
|
|
475
|
-
<
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
+
<!-- Field picker — typeahead popover, same widget Sort uses -->
|
|
480
|
+
<Popover.Root
|
|
481
|
+
bind:open={
|
|
482
|
+
() => fieldPickerOpen[rule.id] ?? false,
|
|
483
|
+
(v) => (fieldPickerOpen[rule.id] = v)
|
|
484
|
+
}
|
|
479
485
|
>
|
|
480
|
-
<
|
|
481
|
-
|
|
486
|
+
<Popover.Trigger
|
|
487
|
+
class="inline-flex h-7 w-36 items-center justify-between gap-1.5 rounded-md border bg-muted px-2 text-xs"
|
|
488
|
+
>
|
|
489
|
+
<div class="inline-flex items-center gap-1.5 truncate">
|
|
482
490
|
<FieldIcon size="13" />
|
|
483
|
-
{rule.field}
|
|
491
|
+
<span class="truncate">{rule.field}</span>
|
|
484
492
|
</div>
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
</
|
|
497
|
-
</
|
|
493
|
+
<ChevronDown size="13" class="text-muted-foreground shrink-0" />
|
|
494
|
+
</Popover.Trigger>
|
|
495
|
+
<Popover.Content class="w-64 p-2">
|
|
496
|
+
<FieldPicker
|
|
497
|
+
{collectionName}
|
|
498
|
+
placeholder="Pick a field…"
|
|
499
|
+
onPick={(fname: string) => {
|
|
500
|
+
patchRuleInPlace(rule.id, { field: fname });
|
|
501
|
+
fieldPickerOpen[rule.id] = false;
|
|
502
|
+
}}
|
|
503
|
+
/>
|
|
504
|
+
</Popover.Content>
|
|
505
|
+
</Popover.Root>
|
|
498
506
|
|
|
499
507
|
<!-- Operator picker -->
|
|
500
508
|
<Select.Root
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
onCreate?: (changes: Changes) => void;
|
|
27
27
|
showImport?: boolean;
|
|
28
28
|
showFilter?: boolean;
|
|
29
|
+
showCreate?: boolean;
|
|
29
30
|
loading?: boolean;
|
|
30
31
|
left?: Snippet<[]>;
|
|
31
32
|
excludeIds?: (string | number)[];
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
onCreate,
|
|
41
42
|
showImport = true,
|
|
42
43
|
showFilter = true,
|
|
44
|
+
showCreate = true,
|
|
43
45
|
loading = false,
|
|
44
46
|
left,
|
|
45
47
|
excludeIds = [],
|
|
@@ -154,7 +156,7 @@
|
|
|
154
156
|
{headerIsSmall ? "" : "Refresh"}
|
|
155
157
|
{/if}
|
|
156
158
|
</Button>
|
|
157
|
-
{#if showImport}
|
|
159
|
+
{#if showImport && showCreate}
|
|
158
160
|
<CanAccess collection={collectionName} action="create">
|
|
159
161
|
<ImportButton
|
|
160
162
|
{collectionName}
|
|
@@ -183,17 +185,19 @@
|
|
|
183
185
|
{headerIsSmall ? "" : "Link"}
|
|
184
186
|
</SelectRecord>
|
|
185
187
|
{/if}
|
|
186
|
-
|
|
187
|
-
<
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
{#if showCreate}
|
|
189
|
+
<CanAccess collection={collectionName} action="create">
|
|
190
|
+
<CreateDetailViewButton
|
|
191
|
+
{collectionName}
|
|
192
|
+
variant="default"
|
|
193
|
+
size="sm"
|
|
194
|
+
Icon={Plus}
|
|
195
|
+
onChanges={onCreate ? handleCreate : undefined}
|
|
196
|
+
onSuccessfullSave={onCreate ? undefined : handleCreate}
|
|
197
|
+
>
|
|
198
|
+
{headerIsSmall ? "" : "Create"}
|
|
199
|
+
</CreateDetailViewButton>
|
|
200
|
+
</CanAccess>
|
|
201
|
+
{/if}
|
|
198
202
|
</div>
|
|
199
203
|
</div>
|
|
@@ -39,6 +39,11 @@
|
|
|
39
39
|
select?: Select;
|
|
40
40
|
tableWidth?: number;
|
|
41
41
|
|
|
42
|
+
// Hide the left sticky tools column entirely when the caller knows
|
|
43
|
+
// nothing inside it would render (e.g. select-mode drawer with no
|
|
44
|
+
// checkboxes, no edit/delete buttons, and no children-network icon).
|
|
45
|
+
showLeftTools?: boolean;
|
|
46
|
+
|
|
42
47
|
// recording mode row visuals — cellIndex 0 = tools cell, 1+ = data/action cells
|
|
43
48
|
onCellClass?: (entry: Entry, cellIndex: number) => string;
|
|
44
49
|
}
|
|
@@ -77,13 +82,14 @@
|
|
|
77
82
|
rowActions,
|
|
78
83
|
select,
|
|
79
84
|
tableWidth = $bindable(),
|
|
85
|
+
showLeftTools = true,
|
|
80
86
|
onCellClass,
|
|
81
87
|
}: TableProps = $props();
|
|
82
88
|
|
|
83
89
|
// calculate columns count
|
|
84
|
-
const toolsExists = selectedRecords || tools || preTools ? 1 : 0;
|
|
90
|
+
const toolsExists = $derived(showLeftTools && (selectedRecords || tools || preTools) ? 1 : 0);
|
|
85
91
|
const rowActionsExists = $derived(rowActions ? 1 : 0);
|
|
86
|
-
const columnsLength = columns.length + toolsExists;
|
|
92
|
+
const columnsLength = $derived(columns.length + toolsExists);
|
|
87
93
|
|
|
88
94
|
// set table width
|
|
89
95
|
let columnsWidths: number[] = $state([]);
|
|
@@ -166,13 +172,14 @@
|
|
|
166
172
|
</script>
|
|
167
173
|
|
|
168
174
|
<div
|
|
175
|
+
class="min-w-max"
|
|
169
176
|
style="
|
|
170
177
|
display: grid;
|
|
171
|
-
grid-template-columns:
|
|
178
|
+
grid-template-columns: fit-content(10rem) repeat({columnsLength - 1}, fit-content(15rem)){rowActionsExists ? ' fit-content(7.5rem)' : ''};
|
|
172
179
|
grid-template-rows: 2.5rem;
|
|
173
180
|
"
|
|
174
181
|
>
|
|
175
|
-
{#if selectedRecords || tools || preTools}
|
|
182
|
+
{#if showLeftTools && (selectedRecords || tools || preTools)}
|
|
176
183
|
<div
|
|
177
184
|
bind:clientWidth={columnsWidths[0]}
|
|
178
185
|
class="
|
|
@@ -180,7 +187,7 @@
|
|
|
180
187
|
flex items-center p-2.5 text-xs h-10
|
|
181
188
|
border-r border-b gap-2
|
|
182
189
|
{headerBorderTop ? 'border-t' : ''}
|
|
183
|
-
bg-muted
|
|
190
|
+
bg-muted
|
|
184
191
|
"
|
|
185
192
|
>
|
|
186
193
|
{#if selectedRecords && showCheckboxes}
|
|
@@ -201,7 +208,8 @@
|
|
|
201
208
|
class="
|
|
202
209
|
sticky top-0 z-10
|
|
203
210
|
flex items-center p-2.5 text-xs h-10
|
|
204
|
-
|
|
211
|
+
min-w-0
|
|
212
|
+
bg-muted
|
|
205
213
|
{lastColumn && !showLastColumnBorder ? '' : 'border-r'}
|
|
206
214
|
border-b gap-2
|
|
207
215
|
{headerBorderTop ? 'border-t' : ''}
|
|
@@ -228,7 +236,7 @@
|
|
|
228
236
|
class="
|
|
229
237
|
sticky top-0 right-0 z-20
|
|
230
238
|
flex items-center p-2.5 h-10
|
|
231
|
-
bg-muted
|
|
239
|
+
bg-muted
|
|
232
240
|
border-l border-b
|
|
233
241
|
{headerBorderTop ? 'border-t' : ''}
|
|
234
242
|
"
|
|
@@ -238,7 +246,7 @@
|
|
|
238
246
|
{#each data as entry, index}
|
|
239
247
|
{@const isDisabled = Boolean(entry.__disabled)}
|
|
240
248
|
{@const lastRow = data.length - 1 === index}
|
|
241
|
-
{#if selectedRecords || tools || preTools}
|
|
249
|
+
{#if showLeftTools && (selectedRecords || tools || preTools)}
|
|
242
250
|
<div
|
|
243
251
|
class="sticky left-0 flex items-center p-2.5 text-xs h-10 bg-card border-r gap-2 {onCellClass?.(entry, 0) ?? ''}"
|
|
244
252
|
>
|
|
@@ -269,7 +277,7 @@
|
|
|
269
277
|
onclick={() => {
|
|
270
278
|
select?.onSelect(entry);
|
|
271
279
|
}}
|
|
272
|
-
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) ?? ''}"
|
|
273
281
|
>
|
|
274
282
|
{#if overrideCell}
|
|
275
283
|
{@render overrideCell(fieldValue, column, entry)}
|