@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.
@@ -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
- ${sort({
29
- column,
30
- sortOnColumn,
31
- setSortOn,
32
- descending,
33
- setDescending,
34
- })}
35
- ${column.renderHeader(
36
- column,
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:hover .sort + *,
113
- .header-cell .sort[data-sort] + * {
114
- max-width: calc(100% - 10px);
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
  }
@@ -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>: &nbsp;</div>
126
- <cosmoz-omnitable-group-row column="[[ groupOnColumn ]]" item="[[ item.items.0 ]]" selected="[[ selected ]]" folded="[[ folded ]]">
127
- </cosmoz-omnitable-group-row>
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
- onDragStart,
216
- onDragEnter,
217
- onDragOver,
218
- onDragLeave,
219
- onDrop,
220
- onDown,
221
- onToggle,
222
- collapsed,
223
- filters,
224
- }) =>
225
- (column, i) => {
226
- const indeterminate = collapsed?.includes(column.name),
227
- checked = !column.disabled && !indeterminate;
228
- return html` <div
229
- class="item"
230
- data-index=${i}
231
- @mousedown=${onDown}
232
- draggable="true"
233
- @dragstart=${onDragStart}
234
- @dragenter=${onDragEnter}
235
- @dragover=${onDragOver}
236
- @dragleave=${onDragLeave}
237
- @drop=${onDrop}
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
- <input
257
- class="checkbox"
258
- type="checkbox"
259
- .checked=${checked}
260
- @click=${onToggle}
261
- .indeterminate=${indeterminate}
262
- .windeterminate=${indeterminate}
263
- />
264
- </div>`;
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
- 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
12
- d="M3.56699 0.75C3.75944 0.416666 4.24056 0.416667 4.43301 0.75L7.03109 5.25C7.22354 5.58333 6.98298 6 6.59808 6L1.40192 6C1.01702 6 0.776461 5.58333 0.968911 5.25L3.56699 0.75Z"
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
- column,
18
- sortOnColumn,
19
- setSortOn,
20
- descending,
21
- setDescending,
22
- }) => html` <button
23
- class="sort"
24
- data-sort=${ifDefined(
25
- (column === sortOnColumn && (descending ? 'desc' : 'asc')) || undefined
26
- )}
27
- @click=${(e) => {
28
- const sort = e.currentTarget?.dataset.sort;
29
- if (!sort) {
30
- setSortOn(column.name);
31
- setDescending(false);
32
- }
33
- if (sort === 'asc') {
34
- setDescending(true);
35
- }
36
- if (sort === 'desc') {
37
- setSortOn();
38
- setDescending(false);
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
- ${sortIcon}
43
- </button>`;
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
- const [sortOn, setSortOn] = useHashState(initial.sortOn, hashParam, {
9
- suffix: '-sortOn',
10
- }),
11
- [descending, setDescending] = useHashState(initial.descending, hashParam, {
12
- suffix: '-descending',
13
- read: boolParam,
14
- }),
15
- [groupOn, setGroupOn] = useHashState(initial.groupOn, hashParam, {
16
- suffix: '-groupOn',
17
- }),
18
- [groupOnDescending, setGroupOnDescending] = useHashState(
19
- initial.groupOnDescending,
20
- hashParam,
21
- { suffix: '-groupOnDescending', read: boolParam }
22
- ),
23
- sortOnColumn = useMemo(
24
- () => columns.find((column) => column.name === sortOn),
25
- [columns, sortOn]
26
- ),
27
- groupOnColumn = useMemo(
28
- () => columns.find((column) => column.name === groupOn),
29
- [columns, groupOn]
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
- return {
33
- groupOn,
34
- setGroupOn,
35
- groupOnColumn,
36
- groupOnDescending,
37
- setGroupOnDescending,
41
+ sortOn,
42
+ setSortOn,
43
+ descending,
44
+ setDescending,
45
+ },
46
+ sortAndGroup = useMemo(() => sortAndGroup_, Object.values(sortAndGroup_));
38
47
 
39
- sortOn,
40
- setSortOn,
41
- sortOnColumn,
42
- descending,
43
- setDescending,
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.6.0",
3
+ "version": "8.7.2",
4
4
  "description": "[![Build Status](https://travis-ci.org/Neovici/cosmoz-omnitable.svg?branch=master)](https://travis-ci.org/Neovici/cosmoz-omnitable)",
5
5
  "keywords": [
6
6
  "web-components"