@invopop/popui 0.0.6 → 0.0.8
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/BaseTable.svelte +111 -19
- package/dist/BaseTable.svelte.d.ts +1 -0
- package/dist/BaseTableCell.svelte +10 -3
- package/dist/BaseTableCell.svelte.d.ts +4 -1
- package/dist/BaseTableHeader.svelte +7 -5
- package/dist/BaseTableRow.svelte +16 -9
- package/dist/InputCheckbox.svelte +1 -1
- package/package.json +1 -1
package/dist/BaseTable.svelte
CHANGED
|
@@ -13,6 +13,9 @@ const callback = (entry) => {
|
|
|
13
13
|
};
|
|
14
14
|
const intersectOptions = { callback };
|
|
15
15
|
let metaKeyPressed = false;
|
|
16
|
+
let shiftKeyPressed = false;
|
|
17
|
+
let lastSelected = {};
|
|
18
|
+
let selectWithArrowPosition = -1;
|
|
16
19
|
export let sortBy = "";
|
|
17
20
|
export let sortDirection = "";
|
|
18
21
|
export let fields = [];
|
|
@@ -25,6 +28,7 @@ export let freeWrap = false;
|
|
|
25
28
|
export let selectable = false;
|
|
26
29
|
export let selectedRows = [];
|
|
27
30
|
export let selectedTrackedBy = "id";
|
|
31
|
+
export let hideSelectAll = false;
|
|
28
32
|
$:
|
|
29
33
|
groupedData = groupData(data);
|
|
30
34
|
$:
|
|
@@ -33,6 +37,12 @@ $:
|
|
|
33
37
|
indeterminate = selectedRows.length > 0 && selectedRows.length < data.length;
|
|
34
38
|
$:
|
|
35
39
|
allChecked = selectedRows.length === data.length;
|
|
40
|
+
$:
|
|
41
|
+
flattedData = groupedData.flatMap((d) => d.rows);
|
|
42
|
+
$:
|
|
43
|
+
lastSelectedIndex = flattedData.findIndex(
|
|
44
|
+
(d) => d[selectedTrackedBy] === lastSelected[selectedTrackedBy]
|
|
45
|
+
);
|
|
36
46
|
function groupData(rows) {
|
|
37
47
|
if (rows.length === 0)
|
|
38
48
|
return [];
|
|
@@ -50,40 +60,120 @@ function groupData(rows) {
|
|
|
50
60
|
}
|
|
51
61
|
function toggleAllSelected(selected) {
|
|
52
62
|
selectedRows = [];
|
|
63
|
+
lastSelected = {};
|
|
53
64
|
if (!selected)
|
|
54
65
|
return;
|
|
55
66
|
selectedRows = data;
|
|
56
67
|
}
|
|
68
|
+
function selectRow(row) {
|
|
69
|
+
selectedRows = [.../* @__PURE__ */ new Set([...selectedRows, row])];
|
|
70
|
+
}
|
|
71
|
+
function unselectRow(row) {
|
|
72
|
+
selectedRows = selectedRows.filter((r) => r[selectedTrackedBy] !== row[selectedTrackedBy]);
|
|
73
|
+
if (!selectedRows.length) {
|
|
74
|
+
lastSelected = {};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function selectRange(to) {
|
|
78
|
+
if (lastSelectedIndex < 0)
|
|
79
|
+
return;
|
|
80
|
+
let fromIndex = lastSelectedIndex;
|
|
81
|
+
let toIndex = flattedData.findIndex((d) => d[selectedTrackedBy] === to[selectedTrackedBy]);
|
|
82
|
+
if (fromIndex > toIndex) {
|
|
83
|
+
;
|
|
84
|
+
[fromIndex, toIndex] = [toIndex, fromIndex];
|
|
85
|
+
}
|
|
86
|
+
const itemsToSelect = flattedData.slice(fromIndex, toIndex + 1);
|
|
87
|
+
selectedRows = [.../* @__PURE__ */ new Set([...selectedRows, ...itemsToSelect])];
|
|
88
|
+
}
|
|
57
89
|
</script>
|
|
58
90
|
|
|
59
91
|
<svelte:window
|
|
60
92
|
on:keydown={(event) => {
|
|
93
|
+
if (event.key === 'Escape' || event.key === 'Esc') {
|
|
94
|
+
selectedRows = []
|
|
95
|
+
lastSelected = {}
|
|
96
|
+
}
|
|
97
|
+
|
|
61
98
|
metaKeyPressed = event.metaKey
|
|
99
|
+
shiftKeyPressed = event.shiftKey
|
|
100
|
+
|
|
101
|
+
if (event.key === 'Shift') {
|
|
102
|
+
selectWithArrowPosition = lastSelectedIndex
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (event.key === 'ArrowUp') {
|
|
107
|
+
if (!shiftKeyPressed) return
|
|
108
|
+
const toIndex = lastSelectedIndex - 1
|
|
109
|
+
const to = flattedData[toIndex]
|
|
110
|
+
|
|
111
|
+
if (!to) return
|
|
112
|
+
|
|
113
|
+
if (toIndex < selectWithArrowPosition) {
|
|
114
|
+
selectRow(to)
|
|
115
|
+
} else {
|
|
116
|
+
unselectRow(lastSelected)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
lastSelected = to
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (event.key === 'ArrowDown') {
|
|
123
|
+
if (lastSelectedIndex < 0) {
|
|
124
|
+
selectRow(flattedData[0])
|
|
125
|
+
lastSelected = flattedData[0]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!shiftKeyPressed) return
|
|
129
|
+
|
|
130
|
+
const toIndex = lastSelectedIndex + 1
|
|
131
|
+
const to = flattedData[toIndex]
|
|
132
|
+
|
|
133
|
+
if (!to) return
|
|
134
|
+
|
|
135
|
+
if (toIndex > selectWithArrowPosition) {
|
|
136
|
+
selectRow(to)
|
|
137
|
+
} else {
|
|
138
|
+
unselectRow(lastSelected)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
lastSelected = to
|
|
142
|
+
}
|
|
62
143
|
}}
|
|
63
|
-
on:keyup={() => {
|
|
144
|
+
on:keyup={(event) => {
|
|
64
145
|
metaKeyPressed = false
|
|
146
|
+
shiftKeyPressed = false
|
|
147
|
+
|
|
148
|
+
if (!event.shiftKey) {
|
|
149
|
+
selectWithArrowPosition = -1
|
|
150
|
+
}
|
|
65
151
|
}}
|
|
66
152
|
/>
|
|
67
153
|
|
|
68
|
-
<div class="w-full
|
|
69
|
-
<table class="hidden md:table w-full
|
|
154
|
+
<div class="w-full font-sans">
|
|
155
|
+
<table class="hidden md:table w-full">
|
|
70
156
|
<thead>
|
|
71
157
|
<tr class="border-b border-neutral-100 relative">
|
|
72
158
|
{#if selectable}
|
|
73
159
|
<!-- if table is selectable we need to add an extra header with a checkbox -->
|
|
74
|
-
<th scope="col" class="bg-white sticky top-0 z-10 rounded-tr-md
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
160
|
+
<th scope="col" class="bg-white sticky top-0 z-10 rounded-tr-md">
|
|
161
|
+
{#if !hideSelectAll}
|
|
162
|
+
<label class="pl-5 pr-3 h-[40px] flex items-center" for={undefined}>
|
|
163
|
+
<InputCheckbox
|
|
164
|
+
checked={allChecked}
|
|
165
|
+
{indeterminate}
|
|
166
|
+
on:change={(event) => {
|
|
167
|
+
toggleAllSelected(event.detail)
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
</label>
|
|
171
|
+
{/if}
|
|
82
172
|
</th>
|
|
83
173
|
{/if}
|
|
84
174
|
{#each fields as field, i (i)}
|
|
85
175
|
<BaseTableHeader
|
|
86
|
-
isFirst={i === 0}
|
|
176
|
+
isFirst={i === 0 && !selectable}
|
|
87
177
|
isLast={!addExtraCell && i === fields.length - 1}
|
|
88
178
|
{sortBy}
|
|
89
179
|
{sortDirection}
|
|
@@ -103,8 +193,8 @@ function toggleAllSelected(selected) {
|
|
|
103
193
|
<tr>
|
|
104
194
|
<th
|
|
105
195
|
scope="colgroup"
|
|
106
|
-
colspan={fields.length + 1}
|
|
107
|
-
class="bg-neutral-50 px-
|
|
196
|
+
colspan={fields.length + (selectable ? 2 : 1)}
|
|
197
|
+
class="bg-neutral-50 px-5 text-left text-sm font-medium text-neutral-500 sticky top-11 tracking-normal border-t border-b border-neutral-100 h-8"
|
|
108
198
|
>
|
|
109
199
|
<span>{group.label}</span>
|
|
110
200
|
{#if !hideCounter}
|
|
@@ -137,11 +227,14 @@ function toggleAllSelected(selected) {
|
|
|
137
227
|
}}
|
|
138
228
|
on:checked={(event) => {
|
|
139
229
|
if (event.detail) {
|
|
140
|
-
|
|
230
|
+
if (shiftKeyPressed) {
|
|
231
|
+
selectRange(row)
|
|
232
|
+
} else {
|
|
233
|
+
selectRow(row)
|
|
234
|
+
}
|
|
235
|
+
lastSelected = row
|
|
141
236
|
} else {
|
|
142
|
-
|
|
143
|
-
(r) => r[selectedTrackedBy] !== row[selectedTrackedBy]
|
|
144
|
-
)
|
|
237
|
+
unselectRow(row)
|
|
145
238
|
}
|
|
146
239
|
}}
|
|
147
240
|
on:action
|
|
@@ -170,7 +263,6 @@ function toggleAllSelected(selected) {
|
|
|
170
263
|
{#each fields as field, i (i)}
|
|
171
264
|
<BaseTableCell
|
|
172
265
|
tag="div"
|
|
173
|
-
currentIndex={i}
|
|
174
266
|
{field}
|
|
175
267
|
badge={field.helperBadge ? field.helperBadge(row) : null}
|
|
176
268
|
status={field.helperStatus ? field.helperStatus(row) : null}
|
|
@@ -7,23 +7,30 @@ import { getCountryName } from "./helpers.js";
|
|
|
7
7
|
import UuidCopy from "./UuidCopy.svelte";
|
|
8
8
|
import { Icon } from "@steeze-ui/svelte-icon";
|
|
9
9
|
export let field;
|
|
10
|
-
export let
|
|
10
|
+
export let isFirst = false;
|
|
11
|
+
export let isLast = false;
|
|
11
12
|
export let badge = null;
|
|
12
13
|
export let status = null;
|
|
13
14
|
export let icons = null;
|
|
14
15
|
export let data = "";
|
|
15
16
|
export let freeWrap = false;
|
|
16
17
|
export let tag = "td";
|
|
18
|
+
export let selectable = false;
|
|
19
|
+
export let hasActions = false;
|
|
17
20
|
$:
|
|
18
21
|
cellStyles = clsx(
|
|
19
22
|
{ "tabular-nums slashed-zero lining-nums": field.monospacedNums },
|
|
20
23
|
{ "font-mono": field.monospaced },
|
|
21
|
-
{ "text-neutral-800 font-medium":
|
|
22
|
-
{ "text-neutral-800 md:text-neutral-500":
|
|
24
|
+
{ "text-neutral-800 font-medium": isFirst && !field.grayed },
|
|
25
|
+
{ "text-neutral-800 md:text-neutral-500": !isFirst || field.grayed },
|
|
23
26
|
{ "md:text-right": field.rightAlign },
|
|
24
27
|
{ "md:w-full md:max-w-0": field.fullWidth },
|
|
25
28
|
{ "py-2 md:py-[11.25px]": badge },
|
|
26
29
|
{ "py-2 md:py-[11.75px]": !badge },
|
|
30
|
+
{ "pl-5": isFirst && !selectable },
|
|
31
|
+
{ "pl-3": !isFirst || selectable },
|
|
32
|
+
{ "pr-5": isLast && !hasActions },
|
|
33
|
+
{ "pr-3": !isLast || hasActions },
|
|
27
34
|
{ "px-3": !field.noPadding },
|
|
28
35
|
{ "px-0": field.noPadding },
|
|
29
36
|
{ "whitespace-nowrap truncate": !freeWrap }
|
|
@@ -3,13 +3,16 @@ import type { Badge, FeedItemStatus, TableField, TableIcon } from './types.js';
|
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
5
|
field: TableField;
|
|
6
|
-
|
|
6
|
+
isFirst?: boolean | undefined;
|
|
7
|
+
isLast?: boolean | undefined;
|
|
7
8
|
badge?: Badge | null | undefined;
|
|
8
9
|
status?: FeedItemStatus | null | undefined;
|
|
9
10
|
icons?: TableIcon[] | null | undefined;
|
|
10
11
|
data?: unknown;
|
|
11
12
|
freeWrap?: boolean | undefined;
|
|
12
13
|
tag?: string | undefined;
|
|
14
|
+
selectable?: boolean | undefined;
|
|
15
|
+
hasActions?: boolean | undefined;
|
|
13
16
|
};
|
|
14
17
|
events: {
|
|
15
18
|
copied: CustomEvent<any>;
|
|
@@ -11,14 +11,16 @@ export let isFirst = false;
|
|
|
11
11
|
export let isLast = false;
|
|
12
12
|
$:
|
|
13
13
|
outerStyles = clsx({
|
|
14
|
-
"w-full": field.fullWidth
|
|
15
|
-
"rounded-tl-md": isFirst,
|
|
16
|
-
"rounded-tr-md": isLast
|
|
14
|
+
"w-full": field.fullWidth
|
|
17
15
|
});
|
|
18
16
|
$:
|
|
19
17
|
headerStyles = clsx({
|
|
20
18
|
"justify-end": field.rightAlign,
|
|
21
|
-
"hover:bg-neutral-50 focus:bg-neutral-100": field.sortable
|
|
19
|
+
"hover:bg-neutral-50 focus:bg-neutral-100": field.sortable,
|
|
20
|
+
"pl-5": isFirst,
|
|
21
|
+
"pl-3": !isFirst,
|
|
22
|
+
"pr-5": isLast,
|
|
23
|
+
"pr-3": !isLast
|
|
22
24
|
});
|
|
23
25
|
function handleSortBy(event) {
|
|
24
26
|
sortDirection = event.detail;
|
|
@@ -38,7 +40,7 @@ function handleSortBy(event) {
|
|
|
38
40
|
<BaseDropdown bind:this={sortDropdown} fullWidth>
|
|
39
41
|
<span
|
|
40
42
|
slot="trigger"
|
|
41
|
-
class="{headerStyles} w-full
|
|
43
|
+
class="{headerStyles} w-full py-3 flex items-center justify-start space-x-1 text-left text-base tracking-normal whitespace-nowrap font-normal"
|
|
42
44
|
>
|
|
43
45
|
<span>{field.headerLabel}</span>
|
|
44
46
|
{#if sortBy === field.slug}
|
package/dist/BaseTableRow.svelte
CHANGED
|
@@ -25,6 +25,7 @@ $:
|
|
|
25
25
|
|
|
26
26
|
<tr
|
|
27
27
|
class:cursor-pointer={!disableRowClick}
|
|
28
|
+
class:bg-workspace-accent-50={checked}
|
|
28
29
|
class="hover:bg-neutral-50"
|
|
29
30
|
on:click
|
|
30
31
|
on:contextmenu|preventDefault={() => {
|
|
@@ -34,20 +35,26 @@ $:
|
|
|
34
35
|
}}
|
|
35
36
|
>
|
|
36
37
|
{#if selectable}
|
|
37
|
-
<td
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
<td>
|
|
39
|
+
<!-- for hack is needed in order to be used with the custom checkbox and silence the linter -->
|
|
40
|
+
<label class="pl-5 pr-1.5 h-[40px] flex items-center" for={undefined}>
|
|
41
|
+
<InputCheckbox
|
|
42
|
+
{checked}
|
|
43
|
+
on:change={(event) => {
|
|
44
|
+
dispatch('checked', event.detail)
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
</label>
|
|
44
48
|
</td>
|
|
45
49
|
{/if}
|
|
46
50
|
{#each fields as field, i (i)}
|
|
47
51
|
<BaseTableCell
|
|
48
|
-
|
|
52
|
+
isFirst={i === 0}
|
|
53
|
+
isLast={i === fields.length - 1}
|
|
49
54
|
{field}
|
|
50
55
|
{freeWrap}
|
|
56
|
+
{selectable}
|
|
57
|
+
hasActions={!!actions.length}
|
|
51
58
|
badge={field.helperBadge ? field.helperBadge(row) : null}
|
|
52
59
|
status={field.helperStatus ? field.helperStatus(row) : null}
|
|
53
60
|
icons={field.helperIcons ? field.helperIcons(row) : null}
|
|
@@ -56,7 +63,7 @@ $:
|
|
|
56
63
|
/>
|
|
57
64
|
{/each}
|
|
58
65
|
{#if actions.length}
|
|
59
|
-
<td class="pl-1 pr-
|
|
66
|
+
<td class="pl-1 pr-5">
|
|
60
67
|
<BaseTableActions
|
|
61
68
|
bind:this={actionsDropdown}
|
|
62
69
|
{actions}
|
|
@@ -17,7 +17,7 @@ function updateInput(event) {
|
|
|
17
17
|
type="checkbox"
|
|
18
18
|
{checked}
|
|
19
19
|
{indeterminate}
|
|
20
|
-
class="form-checkbox w-5 h-5 text-workspace-accent focus:text-workspace-accent rounded border border-neutral-200 focus:ring-0 focus:ring-offset-0"
|
|
20
|
+
class="form-checkbox w-5 h-5 text-workspace-accent focus:text-workspace-accent rounded border border-neutral-200 hover:border-neutral-300 focus:ring-0 focus:ring-offset-0"
|
|
21
21
|
on:change={updateInput}
|
|
22
22
|
on:click|stopPropagation
|
|
23
23
|
/>
|