@neovici/cosmoz-omnitable 8.6.0 → 8.7.2
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/cosmoz-omnitable-group-row.js +2 -2
- package/cosmoz-omnitable-header-row.js +9 -17
- package/cosmoz-omnitable-styles.js +5 -12
- package/cosmoz-omnitable.js +5 -6
- package/lib/cosmoz-omnitable-settings.js +63 -52
- package/lib/cosmoz-omnitable-sort.js +41 -38
- package/lib/use-sort-and-group-options.js +55 -37
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { component } from 'haunted';
|
|
2
2
|
import { nothing } from 'lit-html';
|
|
3
3
|
|
|
4
|
-
const GroupRow = ({ column, item, selected, folded }) => {
|
|
4
|
+
const GroupRow = ({ column, item, selected, folded, group }) => {
|
|
5
5
|
if (!column) {
|
|
6
6
|
return nothing;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
return (column.renderGroup ?? column.renderCell)(column, { item, selected, folded });
|
|
9
|
+
return (column.renderGroup ?? column.renderCell)(column, { item, selected, folded, group });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
customElements.define('cosmoz-omnitable-group-row', component(GroupRow, { useShadowDOM: false }));
|
|
@@ -8,10 +8,6 @@ const /* eslint-disable-next-line max-lines-per-function */
|
|
|
8
8
|
data,
|
|
9
9
|
columns,
|
|
10
10
|
groupOnColumn,
|
|
11
|
-
sortOnColumn,
|
|
12
|
-
setSortOn,
|
|
13
|
-
descending,
|
|
14
|
-
setDescending,
|
|
15
11
|
filters,
|
|
16
12
|
setFilterState,
|
|
17
13
|
}) =>
|
|
@@ -25,19 +21,15 @@ const /* eslint-disable-next-line max-lines-per-function */
|
|
|
25
21
|
title=${column.title}
|
|
26
22
|
name=${column.name}
|
|
27
23
|
>
|
|
28
|
-
${
|
|
29
|
-
column
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
filters[column.name] ?? {},
|
|
38
|
-
(state) => setFilterState(column.name, state),
|
|
39
|
-
column.source(column, data)
|
|
40
|
-
)}
|
|
24
|
+
${[
|
|
25
|
+
column.renderHeader(
|
|
26
|
+
column,
|
|
27
|
+
filters[column.name] ?? {},
|
|
28
|
+
(state) => setFilterState(column.name, state),
|
|
29
|
+
column.source(column, data)
|
|
30
|
+
),
|
|
31
|
+
sort(column.name),
|
|
32
|
+
]}
|
|
41
33
|
</div>`,
|
|
42
34
|
html`<cosmoz-omnitable-resize-nub
|
|
43
35
|
.column=${column}
|
|
@@ -87,7 +87,6 @@ const checkbox = css`
|
|
|
87
87
|
outline: none;
|
|
88
88
|
color: inherit;
|
|
89
89
|
padding: 0;
|
|
90
|
-
order: 112;
|
|
91
90
|
}
|
|
92
91
|
.sort svg {
|
|
93
92
|
display: block;
|
|
@@ -101,22 +100,20 @@ const checkbox = css`
|
|
|
101
100
|
.sort[data-sort='desc'] {
|
|
102
101
|
transform: scaleY(-1);
|
|
103
102
|
}
|
|
104
|
-
:not(:hover) > .sort:not([data-sort]) {
|
|
103
|
+
:not(:hover) > * > .sort:not([data-sort]) {
|
|
105
104
|
display: none;
|
|
106
105
|
}
|
|
107
|
-
|
|
108
106
|
.header-cell {
|
|
109
107
|
display: inline-flex;
|
|
110
108
|
position: relative;
|
|
111
109
|
}
|
|
112
|
-
.header-cell:
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
.header-cell :not(.sort) {
|
|
111
|
+
min-width: 0;
|
|
112
|
+
flex: auto;
|
|
115
113
|
}
|
|
116
|
-
|
|
117
114
|
`;
|
|
118
115
|
|
|
119
|
-
export { checkbox };
|
|
116
|
+
export { checkbox, sort };
|
|
120
117
|
|
|
121
118
|
export default `<style>
|
|
122
119
|
:host {
|
|
@@ -171,10 +168,6 @@ export default `<style>
|
|
|
171
168
|
}
|
|
172
169
|
}
|
|
173
170
|
|
|
174
|
-
.header-cell > * {
|
|
175
|
-
width: 100%;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
171
|
cosmoz-omnitable-header-row {
|
|
179
172
|
white-space: nowrap;
|
|
180
173
|
}
|
package/cosmoz-omnitable.js
CHANGED
|
@@ -46,6 +46,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
46
46
|
<div id="layoutStyle"></div>
|
|
47
47
|
|
|
48
48
|
<div class="mainContainer">
|
|
49
|
+
<sort-and-group-provider value="[[ sortAndGroup ]]">
|
|
49
50
|
<div class="header" id="header">
|
|
50
51
|
<input class="checkbox all" type="checkbox" checked="[[ _allSelected ]]" on-input="_onAllCheckboxChange" disabled$="[[ !_dataIsValid ]]" />
|
|
51
52
|
<cosmoz-omnitable-header-row
|
|
@@ -53,14 +54,11 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
53
54
|
columns="[[ normalizedColumns ]]"
|
|
54
55
|
filters="[[ filters ]]"
|
|
55
56
|
group-on-column="[[ groupOnColumn ]]"
|
|
56
|
-
descending="[[ descending ]]"
|
|
57
|
-
set-descending="[[ setDescending ]]"
|
|
58
|
-
sort-on-column="[[ sortOnColumn ]]"
|
|
59
|
-
set-sort-on="[[ setSortOn ]]"
|
|
60
57
|
content="[[ _renderSettings(normalizedSettings, collapsedColumns, settingsId, hasChangedSettings, hasHiddenFilter, filters) ]]"
|
|
61
58
|
set-filter-state="[[ setFilterState ]]"
|
|
62
59
|
></cosmoz-omnitable-header-row>
|
|
63
60
|
</div>
|
|
61
|
+
</sort-and-group-provider>
|
|
64
62
|
<div class="tableContent" id="tableContent">
|
|
65
63
|
<template is="dom-if" if="[[ !_dataIsValid ]]">
|
|
66
64
|
<div class="tableContent-empty">
|
|
@@ -123,8 +121,9 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
123
121
|
<input class="checkbox" type="checkbox" checked="[[ selected ]]" on-input="_onCheckboxChange" disabled$="[[ !_dataIsValid ]]" />
|
|
124
122
|
<h3 class="groupRow-label">
|
|
125
123
|
<div><span>[[ groupOnColumn.title ]]</span>: </div>
|
|
126
|
-
<cosmoz-omnitable-group-row column="[[ groupOnColumn ]]" item="[[ item.items.0 ]]" selected="[[ selected ]]" folded="[[ folded ]]"
|
|
127
|
-
|
|
124
|
+
<cosmoz-omnitable-group-row column="[[ groupOnColumn ]]" item="[[ item.items.0 ]]" selected="[[ selected ]]" folded="[[ folded ]]"
|
|
125
|
+
group="[[ item ]]"
|
|
126
|
+
></cosmoz-omnitable-group-row>
|
|
128
127
|
</h3>
|
|
129
128
|
<div class="groupRow-badge">[[ item.items.length ]]</div>
|
|
130
129
|
<paper-icon-button class="fold" icon="[[ _getFoldIcon(folded) ]]" on-tap="_toggleGroup"></paper-icon-button>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { html, component, useCallback } from 'haunted';
|
|
2
2
|
import { useMeta } from '@neovici/cosmoz-utils/lib/hooks/use-meta';
|
|
3
|
-
import { checkbox } from '../cosmoz-omnitable-styles';
|
|
3
|
+
import { checkbox, sort as sortStyle } from '../cosmoz-omnitable-styles';
|
|
4
4
|
import { nothing } from 'lit-html';
|
|
5
5
|
import { isEmpty } from '@neovici/cosmoz-utils/lib/template';
|
|
6
6
|
import { defaultPlacement } from '@neovici/cosmoz-dropdown';
|
|
7
|
+
import sort from './cosmoz-omnitable-sort';
|
|
8
|
+
|
|
7
9
|
const placement = ['bottom-right', ...defaultPlacement],
|
|
8
10
|
settingsStyles = `
|
|
9
11
|
:host {
|
|
@@ -54,6 +56,14 @@ const placement = ['bottom-right', ...defaultPlacement],
|
|
|
54
56
|
margin: 4px 0;
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
${sortStyle}
|
|
60
|
+
.sort {
|
|
61
|
+
order: initial;
|
|
62
|
+
margin: 0;
|
|
63
|
+
width: auto;
|
|
64
|
+
padding: 8px;
|
|
65
|
+
}
|
|
66
|
+
|
|
57
67
|
.buttons {
|
|
58
68
|
display: flex;
|
|
59
69
|
gap: 8px;
|
|
@@ -211,58 +221,59 @@ const placement = ['bottom-right', ...defaultPlacement],
|
|
|
211
221
|
},
|
|
212
222
|
renderItem =
|
|
213
223
|
// eslint-disable-next-line max-lines-per-function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
>
|
|
239
|
-
<button class="pull">
|
|
240
|
-
<svg
|
|
241
|
-
width="16"
|
|
242
|
-
height="6"
|
|
243
|
-
viewBox="0 0 16 6"
|
|
244
|
-
fill="currentColor"
|
|
245
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
246
|
-
>
|
|
247
|
-
<rect width="16" height="2" />
|
|
248
|
-
<rect y="4" width="16" height="2" />
|
|
249
|
-
</svg>
|
|
250
|
-
</button>
|
|
251
|
-
<label
|
|
252
|
-
class="title"
|
|
253
|
-
?has-filter=${!isEmpty(filters[column.name]?.filter)}
|
|
254
|
-
>${column.title}</label
|
|
224
|
+
({
|
|
225
|
+
onDragStart,
|
|
226
|
+
onDragEnter,
|
|
227
|
+
onDragOver,
|
|
228
|
+
onDragLeave,
|
|
229
|
+
onDrop,
|
|
230
|
+
onDown,
|
|
231
|
+
onToggle,
|
|
232
|
+
collapsed,
|
|
233
|
+
filters,
|
|
234
|
+
}) =>
|
|
235
|
+
(column, i) => {
|
|
236
|
+
const indeterminate = collapsed?.includes(column.name),
|
|
237
|
+
checked = !column.disabled && !indeterminate;
|
|
238
|
+
return html` <div
|
|
239
|
+
class="item"
|
|
240
|
+
data-index=${i}
|
|
241
|
+
@mousedown=${onDown}
|
|
242
|
+
draggable="true"
|
|
243
|
+
@dragstart=${onDragStart}
|
|
244
|
+
@dragenter=${onDragEnter}
|
|
245
|
+
@dragover=${onDragOver}
|
|
246
|
+
@dragleave=${onDragLeave}
|
|
247
|
+
@drop=${onDrop}
|
|
255
248
|
>
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
249
|
+
<button class="pull">
|
|
250
|
+
<svg
|
|
251
|
+
width="16"
|
|
252
|
+
height="6"
|
|
253
|
+
viewBox="0 0 16 6"
|
|
254
|
+
fill="currentColor"
|
|
255
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
256
|
+
>
|
|
257
|
+
<rect width="16" height="2" />
|
|
258
|
+
<rect y="4" width="16" height="2" />
|
|
259
|
+
</svg>
|
|
260
|
+
</button>
|
|
261
|
+
<label
|
|
262
|
+
class="title"
|
|
263
|
+
?has-filter=${!isEmpty(filters[column.name]?.filter)}
|
|
264
|
+
>${column.title}</label
|
|
265
|
+
>
|
|
266
|
+
${sort(column.name)}
|
|
267
|
+
<input
|
|
268
|
+
class="checkbox"
|
|
269
|
+
type="checkbox"
|
|
270
|
+
.checked=${checked}
|
|
271
|
+
@click=${onToggle}
|
|
272
|
+
.indeterminate=${indeterminate}
|
|
273
|
+
.windeterminate=${indeterminate}
|
|
274
|
+
/>
|
|
275
|
+
</div>`;
|
|
276
|
+
},
|
|
266
277
|
SettingsUI = (host) => {
|
|
267
278
|
const { settings, settingsId, onSave, onReset, hasChanges, ...thru } =
|
|
268
279
|
useSettings(host);
|
|
@@ -2,43 +2,46 @@ import { html } from 'haunted';
|
|
|
2
2
|
import { ifDefined } from 'lit-html/directives/if-defined';
|
|
3
3
|
|
|
4
4
|
const sortIcon = html`<svg
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
</svg> `;
|
|
5
|
+
width="8"
|
|
6
|
+
height="6"
|
|
7
|
+
viewBox="0 0 8 6"
|
|
8
|
+
fill="currentColor"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
>
|
|
11
|
+
<path d="M0.5,0.5h7c0.4,0,0.6,0.4,0.4,0.7L4.4,5.3c-0.2,0.2-0.5,0.2-0.7,0L0.1,1.2
|
|
12
|
+
C-0.1,0.9,0.1,0.5,0.5,0.5z" />
|
|
13
|
+
</svg> `;
|
|
15
14
|
|
|
16
|
-
export default (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
15
|
+
export default (column) => html`
|
|
16
|
+
<sort-and-group-consumer
|
|
17
|
+
style="display: contents"
|
|
18
|
+
.render=${({
|
|
19
|
+
sortOn,
|
|
20
|
+
setSortOn,
|
|
21
|
+
descending,
|
|
22
|
+
setDescending,
|
|
23
|
+
} = {}) => html` <button
|
|
24
|
+
class="sort"
|
|
25
|
+
data-sort=${ifDefined(
|
|
26
|
+
(column === sortOn && (descending ? 'desc' : 'asc')) || undefined
|
|
27
|
+
)}
|
|
28
|
+
@click=${(e) => {
|
|
29
|
+
const sort = e.currentTarget?.dataset.sort;
|
|
30
|
+
if (!sort) {
|
|
31
|
+
setSortOn(column);
|
|
32
|
+
setDescending(false);
|
|
33
|
+
}
|
|
34
|
+
if (sort === 'asc') {
|
|
35
|
+
setDescending(true);
|
|
36
|
+
}
|
|
37
|
+
if (sort === 'desc') {
|
|
38
|
+
setSortOn();
|
|
39
|
+
setDescending(false);
|
|
40
|
+
}
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
${sortIcon}
|
|
44
|
+
</button>`}
|
|
41
45
|
>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
</sort-and-group-consumer>
|
|
47
|
+
`;
|
|
@@ -1,45 +1,63 @@
|
|
|
1
|
-
import { useMemo } from 'haunted';
|
|
1
|
+
import { useMemo, createContext, component, useContext } from 'haunted';
|
|
2
2
|
import { useHashState } from './use-hash-state';
|
|
3
3
|
|
|
4
4
|
const parseBool = (bool) => [true, 'true', 1, 'yes', 'on'].includes(bool),
|
|
5
5
|
boolParam = (p) => p === '' || (p == null ? undefined : parseBool(p));
|
|
6
6
|
|
|
7
7
|
export const useSortAndGroupOptions = (columns, hashParam, initial) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
initial.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
8
|
+
const [sortOn, setSortOn] = useHashState(initial.sortOn, hashParam, {
|
|
9
|
+
suffix: '-sortOn',
|
|
10
|
+
}),
|
|
11
|
+
[descending, setDescending] = useHashState(
|
|
12
|
+
initial.descending,
|
|
13
|
+
hashParam,
|
|
14
|
+
{
|
|
15
|
+
suffix: '-descending',
|
|
16
|
+
read: boolParam,
|
|
17
|
+
}
|
|
18
|
+
),
|
|
19
|
+
[groupOn, setGroupOn] = useHashState(initial.groupOn, hashParam, {
|
|
20
|
+
suffix: '-groupOn',
|
|
21
|
+
}),
|
|
22
|
+
[groupOnDescending, setGroupOnDescending] = useHashState(
|
|
23
|
+
initial.groupOnDescending,
|
|
24
|
+
hashParam,
|
|
25
|
+
{ suffix: '-groupOnDescending', read: boolParam }
|
|
26
|
+
),
|
|
27
|
+
sortOnColumn = useMemo(
|
|
28
|
+
() => columns.find((column) => column.name === sortOn),
|
|
29
|
+
[columns, sortOn]
|
|
30
|
+
),
|
|
31
|
+
groupOnColumn = useMemo(
|
|
32
|
+
() => columns.find((column) => column.name === groupOn),
|
|
33
|
+
[columns, groupOn]
|
|
34
|
+
),
|
|
35
|
+
sortAndGroup_ = {
|
|
36
|
+
groupOn,
|
|
37
|
+
setGroupOn,
|
|
38
|
+
groupOnDescending,
|
|
39
|
+
setGroupOnDescending,
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
sortOn,
|
|
42
|
+
setSortOn,
|
|
43
|
+
descending,
|
|
44
|
+
setDescending,
|
|
45
|
+
},
|
|
46
|
+
sortAndGroup = useMemo(() => sortAndGroup_, Object.values(sortAndGroup_));
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
48
|
+
return {
|
|
49
|
+
...sortAndGroup,
|
|
50
|
+
sortAndGroup,
|
|
51
|
+
groupOnColumn,
|
|
52
|
+
sortOnColumn,
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
SortAndGroupContext = createContext();
|
|
56
|
+
|
|
57
|
+
customElements.define('sort-and-group-provider', SortAndGroupContext.Provider);
|
|
58
|
+
customElements.define(
|
|
59
|
+
'sort-and-group-consumer',
|
|
60
|
+
component(({ render }) => render(useContext(SortAndGroupContext)), {
|
|
61
|
+
useShadowDOM: false,
|
|
62
|
+
})
|
|
63
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-omnitable",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.7.2",
|
|
4
4
|
"description": "[](https://travis-ci.org/Neovici/cosmoz-omnitable)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components"
|