@neovici/cosmoz-omnitable 13.2.5 → 13.4.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.
@@ -64,6 +64,15 @@ export const getString = ({ valuePath }, item) => get(item, valuePath),
64
64
  renderCell: { type: Function },
65
65
  renderEditCell: { type: Function },
66
66
  renderGroup: { type: Function },
67
+
68
+ /**
69
+ * The priority of the column in the mini mode. If missing the column is disabled in the mini mode.
70
+ */
71
+ mini: { type: Number, value: null },
72
+ /**
73
+ * An alternative render to use in mini mode. Takes the same params as `renderCell`.
74
+ */
75
+ renderMini: { type: Function },
67
76
  };
68
77
  }
69
78
 
@@ -82,7 +91,7 @@ export const getString = ({ valuePath }, item) => get(item, valuePath),
82
91
  state: this.legacyFilterToState(filter),
83
92
  },
84
93
  bubbles: true,
85
- })
94
+ }),
86
95
  );
87
96
  }
88
97
 
@@ -135,7 +144,7 @@ export const getString = ({ valuePath }, item) => get(item, valuePath),
135
144
  _propertiesChanged(currentProps, changedProps, oldProps) {
136
145
  super._propertiesChanged(currentProps, changedProps, oldProps);
137
146
  this.dispatchEvent(
138
- new CustomEvent('cosmoz-column-prop-changed', { bubbles: true })
147
+ new CustomEvent('cosmoz-column-prop-changed', { bubbles: true }),
139
148
  );
140
149
  }
141
150
  };
@@ -1,33 +1,39 @@
1
1
  import { component, html } from '@pionjs/pion';
2
+ import { css, sheet } from '@neovici/cosmoz-utils';
2
3
 
3
- const OmnitableItemExpandLine = ({ column }) => html`
4
- <style>
5
- :host {
6
- display: flex;
7
- align-items: center;
8
- flex-wrap: wrap;
9
- }
4
+ const style = css`
5
+ :host {
6
+ display: flex;
7
+ align-items: center;
8
+ flex-wrap: wrap;
9
+ }
10
10
 
11
- .item-expand-label {
12
- overflow: hidden;
13
- text-overflow: ellipsis;
14
- white-space: nowrap;
15
- flex: initial;
16
- align-self: start;
17
- }
11
+ .label {
12
+ overflow: hidden;
13
+ text-overflow: ellipsis;
14
+ white-space: nowrap;
15
+ flex: initial;
16
+ align-self: start;
17
+ }
18
18
 
19
- .item-expand-value {
20
- text-align: right;
21
- flex-grow: 1 !important;
22
- flex-basis: 100px !important;
23
- white-space: nowrap;
24
- }
19
+ .value {
20
+ text-align: right;
21
+ flex-grow: 1;
22
+ flex-basis: 100px;
23
+ white-space: nowrap;
24
+ }
25
+ `;
25
26
 
26
- </style>
27
- <div class="item-expand-label" title=${ column.title } part="item-expand-label">${ column.title }</div>
28
- <div class="item-expand-value" part="item-expand-value">
27
+ const ItemExpandLine = ({ column }) => html`
28
+ <div class="label" title="${column.title}" part="item-expand-label">
29
+ ${column.title}
30
+ </div>
31
+ <div class="value" part="item-expand-value">
29
32
  <slot></slot>
30
33
  </div>
31
34
  `;
32
35
 
33
- customElements.define('cosmoz-omnitable-item-expand-line', component(OmnitableItemExpandLine));
36
+ customElements.define(
37
+ 'cosmoz-omnitable-item-expand-line',
38
+ component(ItemExpandLine, {styleSheets: [sheet(style)]}),
39
+ );
@@ -1,48 +1,28 @@
1
- /* eslint-disable object-curly-newline */
2
- import { component, useEffect } from '@pionjs/pion';
3
- import { html, nothing } from 'lit-html';
1
+ import { component } from '@pionjs/pion';
2
+ import { html } from 'lit-html';
3
+ import { map } from 'lit-html/directives/map.js';
4
4
  import './cosmoz-omnitable-item-expand-line';
5
5
 
6
- const renderExpandList = ({
6
+ const ItemExpand = ({ columns, item, selected, expanded, groupOnColumn }) => {
7
+ return map(
7
8
  columns,
8
- item,
9
- selected,
10
- expanded,
11
- groupOnColumn,
12
- }) =>
13
- columns.map(
14
- (column) => html`<cosmoz-omnitable-item-expand-line
9
+ (column) =>
10
+ html`<cosmoz-omnitable-item-expand-line
15
11
  .column=${column}
16
12
  ?hidden=${column === groupOnColumn}
17
- exportparts="item-expand-label,item-expand-value"
13
+ exportparts="item-expand-label, item-expand-value"
18
14
  >${column.renderCell(column, {
19
15
  item,
20
16
  selected,
21
17
  expanded,
22
18
  })}</cosmoz-omnitable-item-expand-line
23
- >`
24
- ),
25
- ExpandList = (host) => {
26
- const { columns } = host;
27
-
28
- useEffect(() => {
29
- if (columns?.length > 0) {
30
- return;
31
- }
32
-
33
- host.setAttribute('hidden', '');
34
- return () => host.removeAttribute('hidden');
35
- }, [columns?.length]);
36
-
37
- return Array.isArray(columns) && columns.length > 0 && host.expanded
38
- ? renderExpandList(host)
39
- : nothing;
40
- };
19
+ >`,
20
+ );
21
+ };
41
22
 
42
23
  customElements.define(
43
24
  'cosmoz-omnitable-item-expand',
44
- component(ExpandList, {
25
+ component(ItemExpand, {
45
26
  useShadowDOM: false,
46
- observedAttributes: ['expanded'],
47
- })
27
+ }),
48
28
  );
@@ -1,20 +1,37 @@
1
1
  import { component, html } from '@pionjs/pion';
2
2
  import { repeat } from 'lit-html/directives/repeat.js';
3
3
 
4
- const
5
- renderCell = (column, data, onItemChange) => column.editable
4
+ const renderCell = (column, data, onItemChange) =>
5
+ column.editable
6
6
  ? column.renderEditCell(column, data, onItemChange(column, data.item))
7
- : column.renderCell(column, data),
8
- ItemRow = ({ columns, groupOnColumn, item, index, selected, expanded, onItemChange }) => {
9
- return repeat(columns, column => column.name, column => {
7
+ : column.renderCell(column, data);
8
+
9
+ const ItemRow = ({
10
+ columns,
11
+ groupOnColumn,
12
+ item,
13
+ index,
14
+ selected,
15
+ expanded,
16
+ onItemChange,
17
+ }) =>
18
+ repeat(
19
+ columns,
20
+ (column) => column.name,
21
+ (column) => {
10
22
  return html`<div
11
- class="cell itemRow-cell ${ column.cellClass ?? '' }"
12
- ?hidden=${ column === groupOnColumn }
13
- ?editable=${ column.editable }
14
- title=${ column.cellTitleFn(column, item) }
15
- name=${ column.name }
16
- >${ renderCell(column, { item, index, selected, expanded }, onItemChange) }</div>`;
17
- });
18
- };
23
+ class="cell itemRow-cell ${column.cellClass ?? ''}"
24
+ ?hidden="${column === groupOnColumn}"
25
+ ?editable="${column.editable}"
26
+ title="${column.cellTitleFn(column, item)}"
27
+ name="${column.name}"
28
+ >
29
+ ${renderCell(column, { item, index, selected, expanded }, onItemChange)}
30
+ </div>`;
31
+ },
32
+ );
19
33
 
20
- customElements.define('cosmoz-omnitable-item-row', component(ItemRow, { useShadowDOM: false }));
34
+ customElements.define(
35
+ 'cosmoz-omnitable-item-row',
36
+ component(ItemRow, { useShadowDOM: false }),
37
+ );
@@ -162,6 +162,7 @@ export default css`
162
162
  --cosmoz-input-padding: 0;
163
163
  --cosmoz-input-label-text-transform: var(--cosmoz-omnitable-header-text-transform, none);
164
164
  --cosmoz-input-label-font-weight: var(--cosmoz-omnitable-header-font-weight, normal);
165
+ --cosmoz-input-padding: 0;
165
166
  }
166
167
 
167
168
  cosmoz-omnitable-header-row {
@@ -317,11 +318,6 @@ export default css`
317
318
  left: 0;
318
319
  }
319
320
 
320
- .item-row-wrapper {
321
- display: block;
322
- width: 100%;
323
- }
324
-
325
321
  .itemRow {
326
322
  border-bottom-color: var(--cosmoz-omnitable-border-color, #e1e2e5);
327
323
  border-bottom-width: 1px;
@@ -330,10 +326,12 @@ export default css`
330
326
  solid
331
327
  );
332
328
  /* set a min-height for rows so that rows with empty values are visible */
333
- min-height: var(--item-row-min-height, 24px);
334
- padding-right: 8px;
329
+ }
330
+ .itemRow-wrapper {
335
331
  display: flex;
336
332
  align-items: center;
333
+ min-height: var(--item-row-min-height, 39px);
334
+ padding-right: 8px;
337
335
  }
338
336
 
339
337
  .itemRow[selected] {
@@ -357,9 +355,8 @@ export default css`
357
355
  background-color: #fafafa;
358
356
  }
359
357
 
360
- cosmoz-omnitable-item-expand[hidden],
361
358
  cosmoz-omnitable-item-expand:not([expanded]) {
362
- display: none !important;
359
+ display: none;
363
360
  }
364
361
 
365
362
  .groupRow {
@@ -447,7 +444,7 @@ export default css`
447
444
  .itemRow:hover {
448
445
  box-shadow: inset 1px 0 0 #dadce0, inset -1px 0 0 #dadce0,
449
446
  0 1px 2px 0 rgb(60 64 67 / 30%), 0 1px 3px 1px rgb(60 64 67 / 15%);
450
- background: var(--cosmoz-omnitable-hover-color);
447
+ /* background: var(--cosmoz-omnitable-hover-color); */
451
448
  }
452
449
  .groupRow:hover .checkbox:not(:checked):not(:hover),
453
450
  .itemRow:hover .checkbox:not(:checked):not(:hover) {
@@ -530,4 +527,32 @@ export default css`
530
527
  min-width: 0;
531
528
  flex: auto;
532
529
  }
530
+
531
+ :host([mini]) .itemRow .expand,
532
+ :host([mini]) cosmoz-omnitable-item-expand {
533
+ display: none;
534
+ }
535
+
536
+ .itemRow-minis {
537
+ display: flex;
538
+ justify-content: space-between;
539
+ margin: 0 8px 8px 8px;
540
+ }
541
+
542
+ :host([mini]) .itemRow {
543
+ border-radius: 8px;
544
+ border: 1px solid var(--cosmoz-omnitable-border-color, #e1e2e5);
545
+ margin: 4px 8px;
546
+ }
547
+ :host([mini]) .itemRow:not([selected]) {
548
+ background: var(--cosmoz-omnitable-mini-item-background, #fdfdfd);
549
+ }
550
+
551
+ :host([mini]) .itemRow:hover {
552
+ box-shadow: none;
553
+ }
554
+
555
+ :host([mini]) .header {
556
+ margin: 0 8px;
557
+ }
533
558
  `;
@@ -63,6 +63,7 @@ customElements.define(
63
63
  'no-local-sort',
64
64
  'no-local-filter',
65
65
  'loading',
66
+ 'mini-breakpoint',
66
67
  ],
67
68
  }) {
68
69
  connectedCallback() {
@@ -71,7 +72,7 @@ customElements.define(
71
72
  notifyProperty(this, 'visibleData', []);
72
73
  notifyProperty(this, 'sortedFilteredGroupedItems', []);
73
74
  }
74
- }
75
+ },
75
76
  );
76
77
 
77
78
  const tmplt = `
@@ -12,7 +12,8 @@ export default css`
12
12
  }
13
13
 
14
14
  .headline {
15
- box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.15),
15
+ box-shadow:
16
+ inset 0px -1px 0px rgba(0, 0, 0, 0.15),
16
17
  inset 0px 1px 0px rgba(0, 0, 0, 0.15);
17
18
  font-weight: 500;
18
19
  font-size: 16px;
@@ -63,7 +64,8 @@ export default css`
63
64
  transform: scaleY(-1);
64
65
  }
65
66
  cosmoz-collapse[opened] + .heading {
66
- box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.15),
67
+ box-shadow:
68
+ inset 0px -1px 0px rgba(0, 0, 0, 0.15),
67
69
  inset 0px 1px 0px rgba(0, 0, 0, 0.15);
68
70
  }
69
71
 
@@ -7,7 +7,7 @@ import { useDOMColumns } from '../use-dom-columns';
7
7
  export default ({ settingsId, host }) => {
8
8
  const initial = useMemo(
9
9
  () => Object.fromEntries(sgProps.map((k) => [k, host[k]])),
10
- []
10
+ [],
11
11
  ),
12
12
  resetRef = useRef(),
13
13
  onReset = useCallback(() => {
@@ -19,7 +19,7 @@ export default ({ settingsId, host }) => {
19
19
  settingsId,
20
20
  settings,
21
21
  setSettings,
22
- onReset
22
+ onReset,
23
23
  ),
24
24
  { enabledColumns } = host,
25
25
  columns = useDOMColumns(host, { enabledColumns }),
@@ -31,14 +31,14 @@ export default ({ settingsId, host }) => {
31
31
  savedSettings,
32
32
  initial,
33
33
  }),
34
- [columns, settings, savedSettings]
34
+ [columns, settings, savedSettings],
35
35
  ),
36
36
  normalizedColumns = useMemo(
37
37
  () =>
38
38
  normalizedSettings.columns
39
39
  .map((s) => columns.find((c) => c.name === s.name))
40
40
  .filter(Boolean),
41
- [columns, ...normalizedSettings.columns.map((s) => s.name)]
41
+ [columns, ...normalizedSettings.columns.map((s) => s.name)],
42
42
  );
43
43
 
44
44
  return {
@@ -1,8 +1,10 @@
1
1
  import { useState } from '@pionjs/pion';
2
2
  import { useTrackSize } from './use-track-size';
3
3
 
4
- export const useCanvasWidth = host => {
5
- const [canvasWidth, setCanvasWidth] = useState(() => host.getBoundingClientRect().width);
4
+ export const useCanvasWidth = (host) => {
5
+ const [canvasWidth, setCanvasWidth] = useState(
6
+ () => host.getBoundingClientRect().width,
7
+ );
6
8
 
7
9
  useTrackSize(host, setCanvasWidth);
8
10
 
@@ -1,155 +1,167 @@
1
- import { useEffect, useLayoutEffect, useState } from '@pionjs/pion';
1
+ import { useLayoutEffect, useState } from '@pionjs/pion';
2
2
  import { memooize } from '@neovici/cosmoz-utils/memoize';
3
3
 
4
- const columnSymbol = Symbol('column'),
5
- verifyColumnSetup = (columns) => {
6
- let ok = true;
7
- const columnNames = columns.map((c) => c.name);
8
- // Check if column names are set
9
- columns.forEach((column) => {
10
- if (column.name != null) {
11
- return;
12
- }
13
- ok = false;
14
- // eslint-disable-next-line no-console
15
- console.error(
16
- 'The name attribute needs to be set on all columns! Missing on column',
17
- column,
18
- );
19
- });
20
-
21
- columns.forEach((column) => {
22
- if (
23
- columnNames.indexOf(column.name) ===
24
- columnNames.lastIndexOf(column.name)
25
- ) {
26
- return;
27
- }
28
- ok = false;
29
- // eslint-disable-next-line no-console
30
- console.error(
31
- 'The name attribute needs to be unique among all columns! Not unique on column',
32
- column,
33
- );
34
- });
35
- return ok;
36
- },
37
- // eslint-disable-next-line max-lines-per-function
38
- domColumnsToConfig = (host, { enabledColumns }) => {
39
- const domColumns = host.shadowRoot
40
- .querySelector('#columnsSlot')
41
- .assignedElements({ flatten: true })
42
- .filter((child) => child.isOmnitableColumn && !child.hidden);
43
-
44
- if (!verifyColumnSetup(domColumns)) {
45
- return [];
4
+ const columnSymbol = Symbol('column');
5
+ const verifyColumnSetup = (columns) => {
6
+ let ok = true;
7
+ const columnNames = columns.map((c) => c.name);
8
+ // Check if column names are set
9
+ columns.forEach((column) => {
10
+ if (column.name != null) {
11
+ return;
46
12
  }
47
-
48
- const columns = Array.isArray(enabledColumns)
49
- ? domColumns.filter((column) => enabledColumns.includes(column.name))
50
- : domColumns.filter((column) => !column.disabled);
51
-
52
- // eslint-disable-next-line max-lines-per-function
53
- return columns.map((column) => {
54
- const valuePath = column.valuePath ?? column.name;
55
-
56
- return {
57
- name: column.name,
58
- title: column.title,
59
-
60
- valuePath,
61
- groupOn: column.groupOn ?? valuePath,
62
- sortOn: column.sortOn ?? valuePath,
63
-
64
- minWidth: column.minWidth,
65
- width: column.width,
66
- flex: column.flex,
67
- priority: column.priority,
68
-
69
- getString: column.getString,
70
- getComparableValue: column.getComparableValue,
71
- serializeFilter: column.serializeFilter,
72
- deserializeFilter: column.deserializeFilter,
73
- toXlsxValue: column.toXlsxValue,
74
-
75
- renderHeader: column.renderHeader,
76
- renderCell: column.renderCell,
77
- renderEditCell: column.renderEditCell,
78
- renderGroup: column.renderGroup,
79
- cellTitleFn: column.cellTitleFn,
80
- getFilterFn: column.getFilterFn,
81
- headerCellClass: column.headerCellClass,
82
- cellClass: column.cellClass,
83
-
84
- editable: column.editable,
85
-
86
- values: column.values,
87
- source: memooize(column.computeSource),
88
-
89
- noLocalFilter: column.noLocalFilter,
90
-
91
- // @deprecated
92
- loading: column.loading,
93
- externalValues: column.externalValues,
94
- computeSource: column.computeSource,
95
-
96
- // boolean columns
97
- trueLabel: column.trueLabel,
98
- falseLabel: column.falseLabel,
99
-
100
- // list columns
101
- valueProperty: column.valueProperty,
102
- textProperty: column.textProperty,
103
- emptyLabel: column.emptyLabel,
104
- emptyValue: column.emptyValue,
105
-
106
- // range columns
107
- min: column.min,
108
- max: column.max,
109
- locale: column.locale,
110
- autoupdate: column.autoupdate,
111
-
112
- // number columns
113
- maximumFractionDigits: column.maximumFractionDigits,
114
- minimumFractionDigits: column.minimumFractionDigits,
115
-
116
- // amount columns
117
- currency: column.currency,
118
- rates: column.rates,
119
- autodetect: column.autodetect,
120
-
121
- // treenode columns
122
- ownerTree: column.ownerTree,
123
- keyProperty: column.keyProperty,
124
-
125
- ...column.getConfig?.(column),
126
-
127
- [columnSymbol]: column,
128
- };
129
- });
130
- },
131
- useDOMColumns = (host, { enabledColumns }) => {
132
- const [columns, setColumns] = useState([]);
133
-
134
- useLayoutEffect(() => {
135
- setColumns(domColumnsToConfig(host, { enabledColumns }));
136
- }, []);
137
-
138
- useEffect(() => {
139
- const slot = host.shadowRoot.querySelector('#columnsSlot'),
140
- handler = () =>
141
- setColumns(domColumnsToConfig(host, { enabledColumns }));
142
-
143
- handler();
144
- slot.addEventListener('slotchange', handler);
145
- host.addEventListener('cosmoz-column-prop-changed', handler);
146
- return () => {
147
- slot.removeEventListener('slotchange', handler);
148
- host.removeEventListener('cosmoz-column-prop-changed', handler);
149
- };
150
- }, [enabledColumns]);
151
-
152
- return columns;
13
+ ok = false;
14
+ // eslint-disable-next-line no-console
15
+ console.error(
16
+ 'The name attribute needs to be set on all columns! Missing on column',
17
+ column,
18
+ );
19
+ });
20
+
21
+ columns.forEach((column) => {
22
+ if (
23
+ columnNames.indexOf(column.name) === columnNames.lastIndexOf(column.name)
24
+ ) {
25
+ return;
26
+ }
27
+ ok = false;
28
+ // eslint-disable-next-line no-console
29
+ console.error(
30
+ 'The name attribute needs to be unique among all columns! Not unique on column',
31
+ column,
32
+ );
33
+ });
34
+ return ok;
35
+ };
36
+
37
+ // eslint-disable-next-line max-lines-per-function
38
+ const normalizeColumn = (column) => {
39
+ const valuePath = column.valuePath ?? column.name;
40
+
41
+ return {
42
+ name: column.name,
43
+ title: column.title,
44
+
45
+ valuePath,
46
+ groupOn: column.groupOn ?? valuePath,
47
+ sortOn: column.sortOn ?? valuePath,
48
+
49
+ minWidth: column.minWidth,
50
+ width: column.width,
51
+ flex: column.flex,
52
+ priority: column.priority,
53
+
54
+ getString: column.getString,
55
+ getComparableValue: column.getComparableValue,
56
+ serializeFilter: column.serializeFilter,
57
+ deserializeFilter: column.deserializeFilter,
58
+ toXlsxValue: column.toXlsxValue,
59
+
60
+ renderHeader: column.renderHeader,
61
+ renderCell: column.renderCell,
62
+ renderEditCell: column.renderEditCell,
63
+ renderGroup: column.renderGroup,
64
+ cellTitleFn: column.cellTitleFn,
65
+ getFilterFn: column.getFilterFn,
66
+ headerCellClass: column.headerCellClass,
67
+ cellClass: column.cellClass,
68
+
69
+ editable: column.editable,
70
+
71
+ values: column.values,
72
+ source: memooize(column.computeSource),
73
+
74
+ noLocalFilter: column.noLocalFilter,
75
+
76
+ mini: column.mini,
77
+ renderMini: column.renderMini,
78
+
79
+ // @deprecated
80
+ loading: column.loading,
81
+ externalValues: column.externalValues,
82
+ computeSource: column.computeSource,
83
+
84
+ // boolean columns
85
+ trueLabel: column.trueLabel,
86
+ falseLabel: column.falseLabel,
87
+
88
+ // list columns
89
+ valueProperty: column.valueProperty,
90
+ textProperty: column.textProperty,
91
+ emptyLabel: column.emptyLabel,
92
+ emptyValue: column.emptyValue,
93
+
94
+ // range columns
95
+ min: column.min,
96
+ max: column.max,
97
+ locale: column.locale,
98
+ autoupdate: column.autoupdate,
99
+
100
+ // number columns
101
+ maximumFractionDigits: column.maximumFractionDigits,
102
+ minimumFractionDigits: column.minimumFractionDigits,
103
+
104
+ // amount columns
105
+ currency: column.currency,
106
+ rates: column.rates,
107
+ autodetect: column.autodetect,
108
+
109
+ // treenode columns
110
+ ownerTree: column.ownerTree,
111
+ keyProperty: column.keyProperty,
112
+
113
+ ...column.getConfig?.(column),
114
+
115
+ [columnSymbol]: column,
153
116
  };
117
+ };
118
+
119
+ const isVisibleColumn = (child) => child.isOmnitableColumn && !child.hidden;
120
+
121
+ const collectDomColumns = (slot) => {
122
+ const domColumns = slot
123
+ .assignedElements({ flatten: true })
124
+ .filter(isVisibleColumn);
125
+
126
+ if (!verifyColumnSetup(domColumns)) return [];
127
+ return domColumns;
128
+ };
129
+
130
+ const normalizeColumns = (domColumns, enabledColumns) => {
131
+ const columns = Array.isArray(enabledColumns)
132
+ ? domColumns.filter((column) => enabledColumns.includes(column.name))
133
+ : domColumns.filter((column) => !column.disabled);
134
+
135
+ return columns.map(normalizeColumn);
136
+ };
137
+
138
+ export const useDOMColumns = (host, { enabledColumns }) => {
139
+ const [columns, setColumns] = useState([]);
140
+
141
+ useLayoutEffect(() => {
142
+ let sched;
143
+ const slot = host.shadowRoot.querySelector('#columnsSlot');
144
+ const update = () => {
145
+ setColumns(normalizeColumns(collectDomColumns(slot), enabledColumns));
146
+ };
147
+ const scheduleUpdate = () => {
148
+ cancelAnimationFrame(sched);
149
+ sched = requestAnimationFrame(update);
150
+ };
151
+
152
+ scheduleUpdate();
153
+
154
+ slot.addEventListener('slotchange', scheduleUpdate);
155
+ host.addEventListener('cosmoz-column-prop-changed', scheduleUpdate);
156
+
157
+ return () => {
158
+ slot.removeEventListener('slotchange', scheduleUpdate);
159
+ host.removeEventListener('cosmoz-column-prop-changed', scheduleUpdate);
160
+ cancelAnimationFrame(sched);
161
+ };
162
+ }, [enabledColumns]);
163
+
164
+ return columns;
165
+ };
154
166
 
155
- export { columnSymbol, useDOMColumns };
167
+ export { columnSymbol };
@@ -5,6 +5,7 @@ import { useCanvasWidth } from './use-canvas-width';
5
5
  import { useTweenArray } from './use-tween-array';
6
6
  import { useLayout } from './use-layout';
7
7
  import { useStyleSheet } from '@neovici/cosmoz-utils/hooks/use-stylesheet';
8
+ import { useMini } from './use-mini';
8
9
 
9
10
  export const useFastLayout = ({
10
11
  host,
@@ -15,16 +16,18 @@ export const useFastLayout = ({
15
16
  sortAndGroupOptions,
16
17
  }) => {
17
18
  const canvasWidth = useCanvasWidth(host),
19
+ { miniColumn, miniColumns } = useMini({ host, canvasWidth, columns }),
18
20
  { groupOnColumn } = sortAndGroupOptions,
19
21
  layout = useLayout({
20
22
  canvasWidth,
21
23
  groupOnColumn,
24
+ miniColumn,
22
25
  config: settings.columns,
23
26
  }),
24
27
  tweenedlayout = useTweenArray(layout, resizeSpeedFactor),
25
28
  layoutCss = useMemo(
26
29
  () => toCss(tweenedlayout, settings.columns),
27
- [tweenedlayout],
30
+ [tweenedlayout, settings.columns],
28
31
  ),
29
32
  collapsedColumns = useMemo(
30
33
  () =>
@@ -49,5 +52,5 @@ export const useFastLayout = ({
49
52
 
50
53
  useStyleSheet(layoutCss);
51
54
 
52
- return { collapsedColumns };
55
+ return { collapsedColumns, miniColumns };
53
56
  };
package/lib/use-layout.js CHANGED
@@ -1,28 +1,32 @@
1
1
  import { useMemo } from '@pionjs/pion';
2
2
  import { computeLayout } from './compute-layout';
3
3
 
4
- export const useLayout = ({ canvasWidth, groupOnColumn, config }) => useMemo(() => {
5
- if (!Array.isArray(config) || canvasWidth == null || canvasWidth === 0) {
6
- return [];
7
- }
4
+ export const useLayout = ({ canvasWidth, groupOnColumn, config, miniColumn }) =>
5
+ useMemo(() => {
6
+ if (!Array.isArray(config) || canvasWidth == null || canvasWidth === 0) {
7
+ return [];
8
+ }
8
9
 
9
- const columnConfigs = config
10
- .map((c, index) => ({
11
- minWidth: c.minWidth,
12
- width: c.width,
13
- flex: c.flex,
14
- priority: c.priority,
15
- name: c.name,
16
- index,
17
- hidden: c.name === groupOnColumn?.name || c.disabled
18
- }))
19
- .sort(
20
- (
21
- { index: aIndex, priority: aPriority },
22
- { index: bIndex, priority: bPriority }
23
- ) =>
24
- aPriority === bPriority ? bIndex - aIndex : aPriority - bPriority
25
- );
10
+ const columnConfigs = config
11
+ .map((c, index) => ({
12
+ minWidth: c.minWidth,
13
+ width: c.width,
14
+ flex: c.flex,
15
+ priority: c.priority,
16
+ name: c.name,
17
+ index,
18
+ hidden: c.name === groupOnColumn?.name || c.disabled,
19
+ }))
20
+ .map((c) =>
21
+ miniColumn ? { ...c, hidden: miniColumn.name !== c.name } : c,
22
+ )
23
+ .sort(
24
+ (
25
+ { index: aIndex, priority: aPriority },
26
+ { index: bIndex, priority: bPriority },
27
+ ) =>
28
+ aPriority === bPriority ? bIndex - aIndex : aPriority - bPriority,
29
+ );
26
30
 
27
- return computeLayout(columnConfigs, canvasWidth, columnConfigs.length);
28
- }, [canvasWidth, groupOnColumn, config]);
31
+ return computeLayout(columnConfigs, canvasWidth, columnConfigs.length);
32
+ }, [canvasWidth, groupOnColumn, config]);
package/lib/use-list.js CHANGED
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable max-lines-per-function */
2
2
  import { html, useCallback, useEffect, useMemo, useRef } from '@pionjs/pion';
3
- import { indexSymbol } from './utils';
3
+ import { when } from 'lit-html/directives/when.js';
4
4
  import { isEmpty } from '@neovici/cosmoz-utils/template';
5
+ import { indexSymbol } from './utils';
5
6
  import { onItemChange as _onItemChange } from './utils-data';
6
7
 
7
8
  const arrow = html`
@@ -19,10 +20,26 @@ const arrow = html`
19
20
  const _getGroupRowClasses = (folded) =>
20
21
  folded ? 'groupRow groupRow-folded' : 'groupRow';
21
22
 
23
+ const renderMinis = (item) => (columns) =>
24
+ when(
25
+ columns?.length > 0,
26
+ () => html`
27
+ <div class="itemRow-minis" part="item-minis">
28
+ ${columns.map(
29
+ (column) =>
30
+ html`<div class="itemRow-mini" part="item-mini">
31
+ ${(column.renderMini ?? column.renderCell)(column, { item })}
32
+ </div>`,
33
+ )}
34
+ </div>
35
+ `,
36
+ );
37
+
22
38
  const renderItem =
23
39
  ({
24
40
  columns,
25
41
  collapsedColumns,
42
+ miniColumns,
26
43
  onItemClick,
27
44
  onCheckboxChange,
28
45
  dataIsValid,
@@ -30,22 +47,22 @@ const renderItem =
30
47
  onItemChange,
31
48
  rowPartFn,
32
49
  }) =>
33
- (item, index, { selected, expanded, toggleCollapse }) =>
34
- html` <div class="item-row-wrapper">
35
- <div
36
- ?selected=${selected}
37
- part="${[
38
- 'itemRow',
39
- `itemRow-${item[indexSymbol]}`,
40
- rowPartFn?.(item, index),
41
- ]
42
- .filter(Boolean)
43
- .join(' ')}"
44
- .dataIndex=${item[indexSymbol]}
45
- .dataItem=${item}
46
- class="itemRow"
47
- @click=${onItemClick}
48
- >
50
+ (item, index, { selected, expanded, toggleCollapse }) => html`
51
+ <div
52
+ ?selected=${selected}
53
+ part="${[
54
+ 'itemRow',
55
+ `itemRow-${item[indexSymbol]}`,
56
+ rowPartFn?.(item, index),
57
+ ]
58
+ .filter(Boolean)
59
+ .join(' ')}"
60
+ .dataIndex=${item[indexSymbol]}
61
+ .dataItem=${item}
62
+ class="itemRow"
63
+ @click=${onItemClick}
64
+ >
65
+ <div class="itemRow-wrapper">
49
66
  <input
50
67
  class="checkbox"
51
68
  type="checkbox"
@@ -65,7 +82,6 @@ const renderItem =
65
82
  .onItemChange=${onItemChange}
66
83
  >
67
84
  </cosmoz-omnitable-item-row>
68
-
69
85
  <button
70
86
  class="expand"
71
87
  ?hidden="${isEmpty(collapsedColumns.length)}"
@@ -75,17 +91,19 @@ const renderItem =
75
91
  ${arrow}
76
92
  </button>
77
93
  </div>
78
- <cosmoz-omnitable-item-expand
79
- .columns=${collapsedColumns}
80
- .item=${item}
81
- .index=${index}
82
- ?selected=${selected}
83
- ?expanded=${expanded}
84
- .groupOnColumn=${groupOnColumn}
85
- part="item-expand"
86
- >
87
- </cosmoz-omnitable-item-expand>
88
- </div>`;
94
+ ${renderMinis(item)(miniColumns)}
95
+ </div>
96
+ <cosmoz-omnitable-item-expand
97
+ .columns=${collapsedColumns}
98
+ .item=${item}
99
+ .index=${index}
100
+ ?selected=${selected}
101
+ ?expanded=${expanded}
102
+ .groupOnColumn=${groupOnColumn}
103
+ part="item-expand"
104
+ >
105
+ </cosmoz-omnitable-item-expand>
106
+ `;
89
107
 
90
108
  const renderGroup =
91
109
  ({ onCheckboxChange, dataIsValid, groupOnColumn }) =>
@@ -125,6 +143,7 @@ export const useList = ({
125
143
  processedItems,
126
144
  columns,
127
145
  collapsedColumns,
146
+ miniColumns,
128
147
  sortAndGroupOptions,
129
148
  rowPartFn,
130
149
  ...rest
@@ -204,6 +223,7 @@ export const useList = ({
204
223
  renderItem({
205
224
  columns,
206
225
  collapsedColumns,
226
+ miniColumns,
207
227
  onItemClick,
208
228
  onCheckboxChange,
209
229
  dataIsValid,
@@ -0,0 +1,28 @@
1
+ import { useMemo, useEffect } from '@pionjs/pion';
2
+
3
+ export const useMini = ({ host, canvasWidth, columns: _columns }) => {
4
+ const breakpoint = host.miniBreakpoint ?? 480;
5
+ const isMiniSize = useMemo(
6
+ () => canvasWidth <= breakpoint,
7
+ [canvasWidth, breakpoint],
8
+ );
9
+ const columns = useMemo(
10
+ () =>
11
+ isMiniSize
12
+ ? _columns
13
+ ?.filter((c) => c.mini !== null)
14
+ .sort((a, b) => (a.mini ?? 0) - (b.mini ?? 0))
15
+ : [],
16
+ [_columns, isMiniSize],
17
+ );
18
+ const [miniColumn, ...miniColumns] = columns ?? [];
19
+
20
+ useEffect(() => {
21
+ host.toggleAttribute('mini', !!miniColumn);
22
+ }, [miniColumn]);
23
+
24
+ return {
25
+ miniColumn,
26
+ miniColumns,
27
+ };
28
+ };
@@ -19,7 +19,7 @@ export const useOmnitable = (host) => {
19
19
  noLocalSort = noLocal,
20
20
  noLocalFilter = noLocal,
21
21
  error,
22
- rowPartFn
22
+ rowPartFn,
23
23
  } = host,
24
24
  settingS = useSettings({ settingsId, host }),
25
25
  { settings, setSettings, columns, resetRef } = settingS,
@@ -28,7 +28,7 @@ export const useOmnitable = (host) => {
28
28
  hashParam,
29
29
  settings,
30
30
  setSettings,
31
- resetRef
31
+ resetRef,
32
32
  ),
33
33
  // TODO: drop filterFunctions
34
34
  { processedItems, visibleData, filters, setFilterState, filterFunctions } =
@@ -40,7 +40,7 @@ export const useOmnitable = (host) => {
40
40
  noLocalSort,
41
41
  noLocalFilter,
42
42
  }),
43
- { collapsedColumns } = useFastLayout({
43
+ { collapsedColumns, miniColumns } = useFastLayout({
44
44
  host,
45
45
  columns,
46
46
  settings,
@@ -86,8 +86,9 @@ export const useOmnitable = (host) => {
86
86
  setSelectedItems,
87
87
  columns,
88
88
  collapsedColumns,
89
+ miniColumns,
89
90
  sortAndGroupOptions,
90
- rowPartFn
91
+ rowPartFn,
91
92
  }),
92
93
  footer: useFooter({
93
94
  host,
@@ -18,7 +18,7 @@ export const useResizableColumns = ({
18
18
  newConfig = [],
19
19
  maxPriority = config.reduce(
20
20
  (p, c) => Math.max(p, c.priority),
21
- -Infinity
21
+ -Infinity,
22
22
  );
23
23
 
24
24
  for (let i = 0; i < layout.length; i++) {
@@ -45,7 +45,7 @@ export const useResizableColumns = ({
45
45
 
46
46
  newConfig[i].width = Math.min(
47
47
  maxNewSize,
48
- Math.max(newWidth, config[i].minWidth)
48
+ Math.max(newWidth, config[i].minWidth),
49
49
  );
50
50
  newConfig[i].flex = 0;
51
51
  newConfig[i].priority = maxPriority;
@@ -10,10 +10,10 @@ export const useTrackSize = (host, setCanvasWidth) =>
10
10
  requestAnimationFrame(() =>
11
11
  setCanvasWidth(
12
12
  entry.contentRect?.width -
13
- 20 /* scrollbar width */ -
14
- 44 /* checkbox width */ -
15
- 24 /* expand button width */
16
- )
13
+ 20 /* scrollbar width */ -
14
+ 44 /* checkbox width */ -
15
+ 24 /* expand button width */,
16
+ ),
17
17
  );
18
18
  },
19
19
  observer = new ResizeObserver(onResize);
@@ -21,4 +21,3 @@ export const useTrackSize = (host, setCanvasWidth) =>
21
21
  observer.observe(host);
22
22
  return () => observer.unobserve(host);
23
23
  }, []);
24
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neovici/cosmoz-omnitable",
3
- "version": "13.2.5",
3
+ "version": "13.4.0",
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"
@@ -30,7 +30,7 @@
30
30
  "start": "wds",
31
31
  "test": "wtr --coverage",
32
32
  "test:watch": "wtr --watch",
33
- "prepare": "husky install"
33
+ "prepare": "husky"
34
34
  },
35
35
  "release": {
36
36
  "plugins": [
@@ -80,8 +80,8 @@
80
80
  "lit-html": "^2.0.0 || ^3.0.0"
81
81
  },
82
82
  "devDependencies": {
83
- "@commitlint/cli": "^18.0.0",
84
- "@commitlint/config-conventional": "^18.0.0",
83
+ "@commitlint/cli": "^19.0.0",
84
+ "@commitlint/config-conventional": "^19.0.0",
85
85
  "@neovici/cfg": "^1.18.0",
86
86
  "@neovici/cosmoz-viewinfo": "^4.0.0",
87
87
  "@open-wc/testing": "^4.0.0",
@@ -92,8 +92,8 @@
92
92
  "@polymer/paper-toggle-button": "^3.0.0",
93
93
  "@semantic-release/changelog": "^6.0.0",
94
94
  "@semantic-release/git": "^10.0.0",
95
- "husky": "^8.0.0",
96
- "semantic-release": "^22.0.0",
97
- "sinon": "^17.0.0"
95
+ "husky": "^9.0.0",
96
+ "semantic-release": "^23.0.0",
97
+ "sinon": "^18.0.0"
98
98
  }
99
99
  }