@digital-realty/ix-grid 1.0.6 → 1.0.11

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/IxGrid.d.ts CHANGED
@@ -20,6 +20,7 @@ export interface Column {
20
20
  }
21
21
  export declare class IxGrid extends LitElement {
22
22
  static readonly styles: import("lit").CSSResult[];
23
+ grid: HTMLElement;
23
24
  columns: Column[];
24
25
  rows: Row[];
25
26
  defaultEmptyText: string;
@@ -33,12 +34,16 @@ export declare class IxGrid extends LitElement {
33
34
  recordCount: number;
34
35
  localStorageID: string | undefined;
35
36
  private filters;
37
+ _columns: Column[];
36
38
  isLoading: boolean;
37
39
  isExpanded: boolean;
38
40
  get columnNames(): string[];
39
41
  private updatePage;
40
42
  handleSort(column?: string): void;
41
43
  private renderColumnHeader;
44
+ connectedCallback(): void;
45
+ reorderColumnsFromTable(): Promise<void>;
46
+ reorderColumnsFromFilter(e: CustomEvent): Promise<void>;
42
47
  private renderHeader;
43
48
  private renderRowLimitControls;
44
49
  private renderPaginationControls;
package/dist/IxGrid.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html, LitElement, nothing } from 'lit';
3
- import { property, state } from 'lit/decorators.js';
3
+ import { property, state, query } from 'lit/decorators.js';
4
4
  import { ifDefined } from 'lit/directives/if-defined.js';
5
5
  import '@vaadin/grid';
6
6
  import { columnBodyRenderer, columnHeaderRenderer } from '@vaadin/grid/lit.js';
@@ -27,6 +27,7 @@ export class IxGrid extends LitElement {
27
27
  this.recordCount = 0;
28
28
  this.localStorageID = undefined;
29
29
  this.filters = [];
30
+ this._columns = [];
30
31
  this.isLoading = false;
31
32
  this.isExpanded = false;
32
33
  this.renderColumnHeader = (column) => html `
@@ -54,18 +55,19 @@ export class IxGrid extends LitElement {
54
55
  </h2>
55
56
  <div class="grid-menu">
56
57
  <ix-grid-column-filter
57
- .columns=${this.columns}
58
+ .columns=${this._columns}
58
59
  localStorageID=${ifDefined(this.localStorageID)}
59
60
  @columnFilter=${(e) => {
60
61
  e.detail.columns.forEach((column, id) => {
61
- this.columns[id].hidden = column.hidden;
62
+ this._columns[id].hidden = column.hidden;
62
63
  });
63
64
  this.updatePage();
64
65
  }}
66
+ @reorderColumns=${this.reorderColumnsFromFilter}
65
67
  ></ix-grid-column-filter>
66
68
  <ix-icon-button icon="download"></ix-icon-button>
67
69
  <ix-grid-row-filter
68
- .columns=${this.columns}
70
+ .columns=${this._columns}
69
71
  @rowFilter=${(e) => {
70
72
  this.filters = e.detail.filters;
71
73
  this.updatePage();
@@ -107,7 +109,7 @@ export class IxGrid extends LitElement {
107
109
  `;
108
110
  }
109
111
  get columnNames() {
110
- return this.columns.map((column) => column.name);
112
+ return this._columns.map((column) => column.name);
111
113
  }
112
114
  async updatePage() {
113
115
  const filters = this.filters.reduce((columnFilters, { columnField, value }) => ({
@@ -147,30 +149,65 @@ export class IxGrid extends LitElement {
147
149
  this.sortedColumn = column;
148
150
  this.updatePage();
149
151
  }
152
+ connectedCallback() {
153
+ super.connectedCallback();
154
+ this._columns = this.columns;
155
+ }
156
+ async reorderColumnsFromTable() {
157
+ var _a, _b;
158
+ // calulate column order from table header flex order
159
+ const headerNodes = Array.from(((_b = (_a = this.grid) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('th')) || []);
160
+ if (headerNodes.length) {
161
+ const columnOrder = headerNodes
162
+ .map((el, id) => ({ id, flexPosition: Number(el.style.order) }))
163
+ .sort((a, b) => a.flexPosition - b.flexPosition)
164
+ .map(el => el.id);
165
+ headerNodes.forEach((el, id) => {
166
+ this._columns[id].width = el.style.width;
167
+ });
168
+ const columnsCorrectlyOrdered = columnOrder.every((x, i) => i === 0 || x > columnOrder[i - 1]);
169
+ if (!columnsCorrectlyOrdered) {
170
+ const reorderedColumns = columnOrder.map(id => this._columns[id]);
171
+ this._columns = [...reorderedColumns];
172
+ this.isLoading = true;
173
+ await this.updateComplete;
174
+ this.isLoading = false;
175
+ }
176
+ }
177
+ }
178
+ async reorderColumnsFromFilter(e) {
179
+ this._columns = [...e.detail.reorderedColumns];
180
+ this.isLoading = true;
181
+ await this.updateComplete;
182
+ this.isLoading = false;
183
+ }
150
184
  render() {
151
185
  var _a;
152
186
  return html `
153
187
  <div class=${`grid-container ${this.isLoading ? 'loading' : ''}`}>
154
188
  ${this.hideHeader ? nothing : this.renderHeader()}
155
- <vaadin-grid
156
- .items=${this.rowLimit > 0 && !this.isExpanded
157
- ? this.rows.slice(0, this.rowLimit)
158
- : this.rows}
159
- all-rows-visible
160
- column-reordering-allowed
161
- theme="no-border"
162
- >
163
- ${(_a = this.columns) === null || _a === void 0 ? void 0 : _a.map((column) => column.name
164
- ? html `<vaadin-grid-column
165
- ${columnHeaderRenderer(() => this.renderColumnHeader(column), this.sortDirection)}
166
- ${columnBodyRenderer(column.bodyRenderer, [])}
167
- resizable
168
- width=${ifDefined(column.width)}
169
- ?hidden=${column.hidden}
170
- ?frozen-to-end=${column.frozenToEnd}
171
- ></vaadin-grid-column>`
172
- : nothing)}
173
- </vaadin-grid>
189
+ ${!this.isLoading
190
+ ? html `<vaadin-grid
191
+ .items=${this.rowLimit > 0 && !this.isExpanded
192
+ ? this.rows.slice(0, this.rowLimit)
193
+ : this.rows}
194
+ all-rows-visible
195
+ column-reordering-allowed
196
+ theme="no-border"
197
+ @mouseup=${this.reorderColumnsFromTable}
198
+ >
199
+ ${(_a = this._columns) === null || _a === void 0 ? void 0 : _a.map((column) => column.name
200
+ ? html `<vaadin-grid-column
201
+ ${columnHeaderRenderer(() => this.renderColumnHeader(column), this.sortDirection)}
202
+ ${columnBodyRenderer(column.bodyRenderer, [])}
203
+ resizable
204
+ width=${ifDefined(column.width)}
205
+ ?hidden=${column.hidden}
206
+ ?frozen-to-end=${column.frozenToEnd}
207
+ ></vaadin-grid-column>`
208
+ : nothing)}
209
+ </vaadin-grid>`
210
+ : nothing}
174
211
  ${this.rowLimit > 0
175
212
  ? this.renderRowLimitControls()
176
213
  : this.renderPaginationControls()}
@@ -179,6 +216,9 @@ export class IxGrid extends LitElement {
179
216
  }
180
217
  }
181
218
  IxGrid.styles = [IxGridViewStyles];
219
+ __decorate([
220
+ query('vaadin-grid')
221
+ ], IxGrid.prototype, "grid", void 0);
182
222
  __decorate([
183
223
  property({ type: Array })
184
224
  ], IxGrid.prototype, "columns", void 0);
@@ -218,6 +258,9 @@ __decorate([
218
258
  __decorate([
219
259
  state()
220
260
  ], IxGrid.prototype, "filters", void 0);
261
+ __decorate([
262
+ state()
263
+ ], IxGrid.prototype, "_columns", void 0);
221
264
  __decorate([
222
265
  state()
223
266
  ], IxGrid.prototype, "isLoading", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"IxGrid.js","sourceRoot":"","sources":["../src/IxGrid.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport '@vaadin/grid';\nimport { columnBodyRenderer, columnHeaderRenderer } from '@vaadin/grid/lit.js';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport '@digital-realty/ix-icon/ix-icon.js';\nimport './components/IxPagination.js';\nimport './components/IxGridColumnFilter.js';\nimport './components/IxGridRowFilter.js';\nimport type { Filter } from './components/IxGridRowFilter.js';\nimport { IxGridViewStyles } from './grid-view-styles.js';\nimport { copy } from './ix-grid-copy.js';\n\nexport interface Row {\n [key: string]: string;\n}\n\nexport interface Column {\n name: string;\n header: string;\n bodyRenderer: (row: Row) => any;\n width?: string;\n sortable?: boolean;\n filterable?: boolean;\n hidden?: boolean;\n frozenToEnd?: boolean;\n}\n\nexport class IxGrid extends LitElement {\n static readonly styles = [IxGridViewStyles];\n\n @property({ type: Array }) columns: Column[] = [];\n\n @property({ type: Array }) rows: Row[] = [];\n\n @property({ type: String }) defaultEmptyText = 'No data to display';\n\n @property({ type: String }) sortedColumn = '';\n\n @property({ type: String }) sortDirection = '';\n\n @property({ type: Boolean }) hideHeader = false;\n\n @property({ type: Number }) rowLimit: number = 0;\n\n @property({ type: Number }) page = 1;\n\n @property({ type: Number }) pageSize = 10;\n\n @property({ type: Array }) pageSizes: number[] = [5, 10, 25, 100];\n\n @property({ type: Number }) recordCount = 0;\n\n @property({ type: String }) localStorageID: string | undefined = undefined;\n\n @state() private filters: Filter[] = [];\n\n @state() isLoading = false;\n\n @state() isExpanded = false;\n\n get columnNames() {\n return this.columns.map((column: Column) => column.name);\n }\n\n private async updatePage() {\n const filters = this.filters.reduce(\n (columnFilters: { [key: string]: string }, { columnField, value }) => ({\n ...columnFilters,\n [columnField]: value,\n }),\n {}\n );\n\n const urlParams: { [key: string]: string } = {\n sort: this.sortedColumn,\n order: this.sortDirection,\n page: this.page.toString(),\n size: this.pageSize.toString(),\n ...filters,\n };\n\n const url = new URL(window.location.href);\n const searchParams = new URLSearchParams(urlParams);\n url.search = searchParams.toString();\n window.history.replaceState(null, '', url.toString());\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {\n columnName: this.sortedColumn,\n sortOrder: this.sortDirection,\n page: this.page,\n pageSize: this.pageSize,\n filters,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n handleSort(column: string = '') {\n if (this.sortedColumn !== column) {\n this.sortDirection = 'asc';\n } else {\n this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';\n }\n this.sortedColumn = column;\n\n this.updatePage();\n }\n\n private renderColumnHeader = (column: Column) => html`\n <div\n @click=${() => column.sortable && this.handleSort(column.name)}\n @keyDown=${() => column.sortable && this.handleSort(column.name)}\n class=\"header\"\n >\n ${column.header}\n ${column.sortable\n ? html`<ix-icon title=\"Sort\" class=\"header-sort-icon\"\n >${this.sortDirection === 'desc' &&\n this.sortedColumn === column.name\n ? `arrow_upward`\n : `arrow_downward`}</ix-icon\n >`\n : nothing}\n </div>\n `;\n\n private renderHeader = () => html`\n <div class=\"grid-header\">\n <h2>\n ${html`${this.recordCount}\n ${copy.user}${this.recordCount === 1 ? '' : 's'}`}\n </h2>\n <div class=\"grid-menu\">\n <ix-grid-column-filter\n .columns=${this.columns}\n localStorageID=${ifDefined(this.localStorageID)}\n @columnFilter=${(e: CustomEvent) => {\n e.detail.columns.forEach((column: Column, id: number) => {\n this.columns[id].hidden = column.hidden;\n });\n this.updatePage();\n }}\n ></ix-grid-column-filter>\n <ix-icon-button icon=\"download\"></ix-icon-button>\n <ix-grid-row-filter\n .columns=${this.columns}\n @rowFilter=${(e: CustomEvent) => {\n this.filters = e.detail.filters;\n this.updatePage();\n }}\n ></ix-grid-row-filter>\n </div>\n </div>\n `;\n\n private renderRowLimitControls = () => {\n if (this.rows.length <= this.rowLimit) return nothing;\n\n return html`\n <div class=\"row-limit\">\n <ix-button\n appearance=\"text\"\n @click=${() => {\n this.isExpanded = !this.isExpanded;\n }}\n has-icon\n >\n ${this.isExpanded ? copy.viewLess : copy.viewMore}\n <ix-icon slot=\"icon\">${this.isExpanded ? 'remove' : 'add'}</ix-icon>\n </ix-button>\n </div>\n `;\n };\n\n private renderPaginationControls = () => html`\n <ix-pagination\n .page=${this.page}\n .pageSize=${this.pageSize}\n .pageSizes=${this.pageSizes}\n .recordCount=${this.recordCount}\n @updatePagination=${(e: CustomEvent) => {\n this.page = e.detail.page;\n this.pageSize = e.detail.pageSize;\n this.updatePage();\n }}\n ></ix-pagination>\n `;\n\n render() {\n return html`\n <div class=${`grid-container ${this.isLoading ? 'loading' : ''}`}>\n ${this.hideHeader ? nothing : this.renderHeader()}\n <vaadin-grid\n .items=${this.rowLimit > 0 && !this.isExpanded\n ? this.rows.slice(0, this.rowLimit)\n : this.rows}\n all-rows-visible\n column-reordering-allowed\n theme=\"no-border\"\n >\n ${this.columns?.map((column: Column) =>\n column.name\n ? html`<vaadin-grid-column\n ${columnHeaderRenderer(\n () => this.renderColumnHeader(column),\n this.sortDirection\n )}\n ${columnBodyRenderer(column.bodyRenderer, [])}\n resizable\n width=${ifDefined(column.width)}\n ?hidden=${column.hidden}\n ?frozen-to-end=${column.frozenToEnd}\n ></vaadin-grid-column>`\n : nothing\n )}\n </vaadin-grid>\n ${this.rowLimit > 0\n ? this.renderRowLimitControls()\n : this.renderPaginationControls()}\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"IxGrid.js","sourceRoot":"","sources":["../src/IxGrid.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing } from 'lit';\nimport { property, state, query } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport '@vaadin/grid';\nimport { columnBodyRenderer, columnHeaderRenderer } from '@vaadin/grid/lit.js';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport '@digital-realty/ix-icon/ix-icon.js';\nimport './components/IxPagination.js';\nimport './components/IxGridColumnFilter.js';\nimport './components/IxGridRowFilter.js';\nimport type { Filter } from './components/IxGridRowFilter.js';\nimport { IxGridViewStyles } from './grid-view-styles.js';\nimport { copy } from './ix-grid-copy.js';\n\nexport interface Row {\n [key: string]: string;\n}\n\nexport interface Column {\n name: string;\n header: string;\n bodyRenderer: (row: Row) => any;\n width?: string;\n sortable?: boolean;\n filterable?: boolean;\n hidden?: boolean;\n frozenToEnd?: boolean;\n}\n\nexport class IxGrid extends LitElement {\n static readonly styles = [IxGridViewStyles];\n\n @query('vaadin-grid') grid!: HTMLElement;\n\n @property({ type: Array }) columns: Column[] = [];\n\n @property({ type: Array }) rows: Row[] = [];\n\n @property({ type: String }) defaultEmptyText = 'No data to display';\n\n @property({ type: String }) sortedColumn = '';\n\n @property({ type: String }) sortDirection = '';\n\n @property({ type: Boolean }) hideHeader = false;\n\n @property({ type: Number }) rowLimit: number = 0;\n\n @property({ type: Number }) page = 1;\n\n @property({ type: Number }) pageSize = 10;\n\n @property({ type: Array }) pageSizes: number[] = [5, 10, 25, 100];\n\n @property({ type: Number }) recordCount = 0;\n\n @property({ type: String }) localStorageID: string | undefined = undefined;\n\n @state() private filters: Filter[] = [];\n\n @state() _columns: Column[] = [];\n\n @state() isLoading = false;\n\n @state() isExpanded = false;\n\n get columnNames() {\n return this._columns.map((column: Column) => column.name);\n }\n\n private async updatePage() {\n const filters = this.filters.reduce(\n (columnFilters: { [key: string]: string }, { columnField, value }) => ({\n ...columnFilters,\n [columnField]: value,\n }),\n {}\n );\n\n const urlParams: { [key: string]: string } = {\n sort: this.sortedColumn,\n order: this.sortDirection,\n page: this.page.toString(),\n size: this.pageSize.toString(),\n ...filters,\n };\n\n const url = new URL(window.location.href);\n const searchParams = new URLSearchParams(urlParams);\n url.search = searchParams.toString();\n window.history.replaceState(null, '', url.toString());\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {\n columnName: this.sortedColumn,\n sortOrder: this.sortDirection,\n page: this.page,\n pageSize: this.pageSize,\n filters,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n handleSort(column: string = '') {\n if (this.sortedColumn !== column) {\n this.sortDirection = 'asc';\n } else {\n this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';\n }\n this.sortedColumn = column;\n\n this.updatePage();\n }\n\n private renderColumnHeader = (column: Column) => html`\n <div\n @click=${() => column.sortable && this.handleSort(column.name)}\n @keyDown=${() => column.sortable && this.handleSort(column.name)}\n class=\"header\"\n >\n ${column.header}\n ${column.sortable\n ? html`<ix-icon title=\"Sort\" class=\"header-sort-icon\"\n >${this.sortDirection === 'desc' &&\n this.sortedColumn === column.name\n ? `arrow_upward`\n : `arrow_downward`}</ix-icon\n >`\n : nothing}\n </div>\n `;\n\n connectedCallback() {\n super.connectedCallback();\n this._columns = this.columns;\n }\n\n async reorderColumnsFromTable() {\n // calulate column order from table header flex order\n const headerNodes = Array.from(\n this.grid?.shadowRoot?.querySelectorAll('th') || []\n );\n if (headerNodes.length) {\n const columnOrder = headerNodes\n .map((el, id) => ({ id, flexPosition: Number(el.style.order) }))\n .sort((a, b) => a.flexPosition - b.flexPosition)\n .map(el => el.id);\n headerNodes.forEach((el, id) => {\n this._columns[id].width = el.style.width;\n });\n const columnsCorrectlyOrdered = columnOrder.every(\n (x, i) => i === 0 || x > columnOrder[i - 1]\n );\n if (!columnsCorrectlyOrdered) {\n const reorderedColumns = columnOrder.map(id => this._columns[id]);\n this._columns = [...reorderedColumns];\n this.isLoading = true;\n await this.updateComplete;\n this.isLoading = false;\n }\n }\n }\n\n async reorderColumnsFromFilter(e: CustomEvent) {\n this._columns = [...e.detail.reorderedColumns];\n this.isLoading = true;\n await this.updateComplete;\n this.isLoading = false;\n }\n\n private renderHeader = () => html`\n <div class=\"grid-header\">\n <h2>\n ${html`${this.recordCount}\n ${copy.user}${this.recordCount === 1 ? '' : 's'}`}\n </h2>\n <div class=\"grid-menu\">\n <ix-grid-column-filter\n .columns=${this._columns}\n localStorageID=${ifDefined(this.localStorageID)}\n @columnFilter=${(e: CustomEvent) => {\n e.detail.columns.forEach((column: Column, id: number) => {\n this._columns[id].hidden = column.hidden;\n });\n this.updatePage();\n }}\n @reorderColumns=${this.reorderColumnsFromFilter}\n ></ix-grid-column-filter>\n <ix-icon-button icon=\"download\"></ix-icon-button>\n <ix-grid-row-filter\n .columns=${this._columns}\n @rowFilter=${(e: CustomEvent) => {\n this.filters = e.detail.filters;\n this.updatePage();\n }}\n ></ix-grid-row-filter>\n </div>\n </div>\n `;\n\n private renderRowLimitControls = () => {\n if (this.rows.length <= this.rowLimit) return nothing;\n\n return html`\n <div class=\"row-limit\">\n <ix-button\n appearance=\"text\"\n @click=${() => {\n this.isExpanded = !this.isExpanded;\n }}\n has-icon\n >\n ${this.isExpanded ? copy.viewLess : copy.viewMore}\n <ix-icon slot=\"icon\">${this.isExpanded ? 'remove' : 'add'}</ix-icon>\n </ix-button>\n </div>\n `;\n };\n\n private renderPaginationControls = () => html`\n <ix-pagination\n .page=${this.page}\n .pageSize=${this.pageSize}\n .pageSizes=${this.pageSizes}\n .recordCount=${this.recordCount}\n @updatePagination=${(e: CustomEvent) => {\n this.page = e.detail.page;\n this.pageSize = e.detail.pageSize;\n this.updatePage();\n }}\n ></ix-pagination>\n `;\n\n render() {\n return html`\n <div class=${`grid-container ${this.isLoading ? 'loading' : ''}`}>\n ${this.hideHeader ? nothing : this.renderHeader()}\n ${!this.isLoading\n ? html`<vaadin-grid\n .items=${this.rowLimit > 0 && !this.isExpanded\n ? this.rows.slice(0, this.rowLimit)\n : this.rows}\n all-rows-visible\n column-reordering-allowed\n theme=\"no-border\"\n @mouseup=${this.reorderColumnsFromTable}\n >\n ${this._columns?.map((column: Column) =>\n column.name\n ? html`<vaadin-grid-column\n ${columnHeaderRenderer(\n () => this.renderColumnHeader(column),\n this.sortDirection\n )}\n ${columnBodyRenderer(column.bodyRenderer, [])}\n resizable\n width=${ifDefined(column.width)}\n ?hidden=${column.hidden}\n ?frozen-to-end=${column.frozenToEnd}\n ></vaadin-grid-column>`\n : nothing\n )}\n </vaadin-grid>`\n : nothing}\n ${this.rowLimit > 0\n ? this.renderRowLimitControls()\n : this.renderPaginationControls()}\n </div>\n `;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  import '@digital-realty/ix-icon-button/ix-icon-button.js';
3
- import '@digital-realty/ix-select/ix-select.js';
3
+ import '@digital-realty/ix-icon/ix-icon.js';
4
4
  import '@digital-realty/ix-switch/ix-switch.js';
5
5
  import type { Column } from '../IxGrid.js';
6
6
  export declare class IxGridColumnFilter extends LitElement {
@@ -9,6 +9,11 @@ export declare class IxGridColumnFilter extends LitElement {
9
9
  localStorageID: string | undefined;
10
10
  private isDropdownVisible;
11
11
  disabledColumns: string[];
12
+ dragEvent: {
13
+ sourceEl: HTMLElement | null;
14
+ startId: number;
15
+ targetId: number;
16
+ };
12
17
  connectedCallback(): void;
13
18
  disconnectedCallback(): void;
14
19
  outerInteraction: (e: Event) => void;
@@ -16,5 +21,8 @@ export declare class IxGridColumnFilter extends LitElement {
16
21
  toggleColumn(id: number): void;
17
22
  updateColumn(e: Event, id: number): void;
18
23
  dispatchUpdate(columns?: Column[]): void;
24
+ dragstart(e: DragEvent): void;
25
+ dragend(): void;
26
+ dragenter(e: DragEvent): void;
19
27
  render(): import("lit").TemplateResult<1>;
20
28
  }
@@ -1,8 +1,9 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { LitElement, html, nothing } from 'lit';
3
3
  import { customElement, property, state } from 'lit/decorators.js';
4
+ import { repeat } from 'lit/directives/repeat.js';
4
5
  import '@digital-realty/ix-icon-button/ix-icon-button.js';
5
- import '@digital-realty/ix-select/ix-select.js';
6
+ import '@digital-realty/ix-icon/ix-icon.js';
6
7
  import '@digital-realty/ix-switch/ix-switch.js';
7
8
  import { IxGridViewStyles } from '../grid-view-styles.js';
8
9
  import { IxGridColumnFilterStyles } from './grid-column-filter-styles.js';
@@ -14,6 +15,11 @@ let IxGridColumnFilter = class IxGridColumnFilter extends LitElement {
14
15
  this.localStorageID = undefined;
15
16
  this.isDropdownVisible = false;
16
17
  this.disabledColumns = [];
18
+ this.dragEvent = {
19
+ sourceEl: null,
20
+ startId: -1,
21
+ targetId: -1,
22
+ };
17
23
  this.outerInteraction = (e) => {
18
24
  if (!e.composedPath().includes(this)) {
19
25
  this.isDropdownVisible = false;
@@ -75,9 +81,43 @@ let IxGridColumnFilter = class IxGridColumnFilter extends LitElement {
75
81
  composed: true,
76
82
  }));
77
83
  }
78
- render() {
84
+ dragstart(e) {
85
+ const el = e.target;
86
+ this.dragEvent.sourceEl = el;
87
+ el.style.opacity = '0.3';
88
+ const id = Number(el.getAttribute('data-id'));
89
+ this.dragEvent.startId = id;
90
+ }
91
+ dragend() {
79
92
  var _a;
80
- return html ` <div class="grid-menu">
93
+ if (this.dragEvent.startId !== this.dragEvent.targetId) {
94
+ const reorderedColumns = [...this.columns];
95
+ const el = reorderedColumns.splice(this.dragEvent.startId, 1)[0];
96
+ reorderedColumns.splice(this.dragEvent.targetId, 0, el);
97
+ this.dispatchEvent(new CustomEvent('reorderColumns', {
98
+ detail: {
99
+ reorderedColumns,
100
+ },
101
+ bubbles: true,
102
+ composed: true,
103
+ }));
104
+ }
105
+ (_a = this.dragEvent.sourceEl) === null || _a === void 0 ? void 0 : _a.style.removeProperty('opacity');
106
+ this.dragEvent = {
107
+ sourceEl: null,
108
+ startId: -1,
109
+ targetId: -1,
110
+ };
111
+ }
112
+ dragenter(e) {
113
+ const el = e.target;
114
+ if (el.classList.contains('drag-target')) {
115
+ const target = Number(el.getAttribute('data-id'));
116
+ this.dragEvent.targetId = target;
117
+ }
118
+ }
119
+ render() {
120
+ return html `<div class="grid-menu">
81
121
  <span
82
122
  @click=${() => {
83
123
  this.isDropdownVisible = true;
@@ -94,17 +134,28 @@ let IxGridColumnFilter = class IxGridColumnFilter extends LitElement {
94
134
  ? html `<div class="active"></div>`
95
135
  : nothing}
96
136
  ${this.isDropdownVisible
97
- ? html ` <div class="dropdown-content">
98
- ${(_a = this.columns) === null || _a === void 0 ? void 0 : _a.map((col, id) => html `<div
137
+ ? html ` <div
138
+ class="dropdown-content"
139
+ @dragover=${(e) => e.preventDefault()}
140
+ @dragstart=${this.dragstart}
141
+ @dragend=${this.dragend}
142
+ @dragenter=${this.dragenter}
143
+ >
144
+ ${repeat(this.columns, (col) => col.name, (col, id) => html `<div
99
145
  class=${col.hidden ? 'disabled' : ''}
100
146
  >
101
- <label class="ix-switch-label">
147
+ <label
148
+ class=${`ix-switch-label drag-target ${this.dragEvent.startId === id ? 'dragOrigin' : ''}`}
149
+ draggable="true"
150
+ data-id=${id}
151
+ >
102
152
  <ix-switch
103
153
  .selected=${!col.hidden}
104
154
  @change=${(e) => this.updateColumn(e, id)}
105
155
  >
106
156
  </ix-switch>
107
157
  <p>${col.header}</p>
158
+ <ix-icon class="draggable">drag_handle</ix-icon>
108
159
  </label>
109
160
  </div>`)}
110
161
  </div>`
@@ -126,6 +177,9 @@ __decorate([
126
177
  __decorate([
127
178
  state()
128
179
  ], IxGridColumnFilter.prototype, "disabledColumns", void 0);
180
+ __decorate([
181
+ state()
182
+ ], IxGridColumnFilter.prototype, "dragEvent", void 0);
129
183
  IxGridColumnFilter = __decorate([
130
184
  customElement('ix-grid-column-filter')
131
185
  ], IxGridColumnFilter);
@@ -1 +1 @@
1
- {"version":3,"file":"IxGridColumnFilter.js","sourceRoot":"","sources":["../../src/components/IxGridColumnFilter.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport '@digital-realty/ix-select/ix-select.js';\nimport '@digital-realty/ix-switch/ix-switch.js';\nimport { IxGridViewStyles } from '../grid-view-styles.js';\nimport { IxGridColumnFilterStyles } from './grid-column-filter-styles.js';\nimport type { Column } from '../IxGrid.js';\n\nconst triggerKeys = [' ', 'Enter'];\n\n@customElement('ix-grid-column-filter')\nexport class IxGridColumnFilter extends LitElement {\n static readonly styles = [IxGridViewStyles, IxGridColumnFilterStyles];\n\n @property({ type: Array }) columns: Column[] = [];\n\n @property({ type: String }) localStorageID: string | undefined = undefined;\n\n @state() private isDropdownVisible: boolean = false;\n\n @state() disabledColumns: string[] = [];\n\n connectedCallback() {\n super.connectedCallback();\n document.addEventListener('click', this.outerInteraction);\n this.initializeLocalStorage();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('click', this.outerInteraction);\n }\n\n outerInteraction = (e: Event) => {\n if (!e.composedPath().includes(this)) {\n this.isDropdownVisible = false;\n }\n };\n\n initializeLocalStorage() {\n if (this.localStorageID) {\n const storedDisabledColumns = localStorage.getItem(this.localStorageID);\n\n if (storedDisabledColumns) {\n const disabledColumns = JSON.parse(storedDisabledColumns);\n this.columns.forEach((column, id) => {\n if (disabledColumns.includes(column.name)) {\n this.columns[id].hidden = true;\n }\n });\n }\n this.dispatchUpdate();\n }\n }\n\n toggleColumn(id: number) {\n this.columns[id].hidden = !this.columns[id].hidden;\n\n this.disabledColumns = this.columns\n .filter((column: Column) => column.hidden)\n .map((column: Column) => column.name);\n\n if (this.localStorageID !== undefined) {\n localStorage.setItem(\n this.localStorageID,\n JSON.stringify(this.disabledColumns)\n );\n }\n\n this.dispatchUpdate();\n }\n\n updateColumn(e: Event, id: number) {\n const input = e.target as HTMLElement;\n const el = input.shadowRoot?.querySelector('input');\n\n this.columns[id].hidden = !el?.checked;\n\n this.disabledColumns = this.columns\n .filter((column: Column) => column.hidden)\n .map((column: Column) => column.name);\n\n if (this.localStorageID !== undefined) {\n localStorage.setItem(\n this.localStorageID,\n JSON.stringify(this.disabledColumns)\n );\n }\n\n this.dispatchUpdate();\n }\n\n dispatchUpdate(columns = this.columns) {\n this.dispatchEvent(\n new CustomEvent('columnFilter', {\n detail: {\n columns,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n render() {\n return html` <div class=\"grid-menu\">\n <span\n @click=${() => {\n this.isDropdownVisible = true;\n }}\n @keyDown=${(e: KeyboardEvent) => {\n if (triggerKeys.includes(e.key)) {\n this.isDropdownVisible = true;\n }\n }}\n class=\"list list-dropdown\"\n >\n <ix-icon-button icon=\"list\"></ix-icon-button>\n ${this.disabledColumns.length > 0\n ? html`<div class=\"active\"></div>`\n : nothing}\n ${this.isDropdownVisible\n ? html` <div class=\"dropdown-content\">\n ${this.columns?.map(\n (col: Column, id: number) => html`<div\n class=${col.hidden ? 'disabled' : ''}\n >\n <label class=\"ix-switch-label\">\n <ix-switch\n .selected=${!col.hidden}\n @change=${(e: Event) => this.updateColumn(e, id)}\n >\n </ix-switch>\n <p>${col.header}</p>\n </label>\n </div>`\n )}\n </div>`\n : nothing}\n </span>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"IxGridColumnFilter.js","sourceRoot":"","sources":["../../src/components/IxGridColumnFilter.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport '@digital-realty/ix-icon/ix-icon.js';\nimport '@digital-realty/ix-switch/ix-switch.js';\nimport { IxGridViewStyles } from '../grid-view-styles.js';\nimport { IxGridColumnFilterStyles } from './grid-column-filter-styles.js';\nimport type { Column } from '../IxGrid.js';\n\nconst triggerKeys = [' ', 'Enter'];\n\n@customElement('ix-grid-column-filter')\nexport class IxGridColumnFilter extends LitElement {\n static readonly styles = [IxGridViewStyles, IxGridColumnFilterStyles];\n\n @property({ type: Array }) columns: Column[] = [];\n\n @property({ type: String }) localStorageID: string | undefined = undefined;\n\n @state() private isDropdownVisible: boolean = false;\n\n @state() disabledColumns: string[] = [];\n\n @state() dragEvent: {\n sourceEl: HTMLElement | null;\n startId: number;\n targetId: number;\n } = {\n sourceEl: null,\n startId: -1,\n targetId: -1,\n };\n\n connectedCallback() {\n super.connectedCallback();\n document.addEventListener('click', this.outerInteraction);\n this.initializeLocalStorage();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('click', this.outerInteraction);\n }\n\n outerInteraction = (e: Event) => {\n if (!e.composedPath().includes(this)) {\n this.isDropdownVisible = false;\n }\n };\n\n initializeLocalStorage() {\n if (this.localStorageID) {\n const storedDisabledColumns = localStorage.getItem(this.localStorageID);\n\n if (storedDisabledColumns) {\n const disabledColumns = JSON.parse(storedDisabledColumns);\n this.columns.forEach((column, id) => {\n if (disabledColumns.includes(column.name)) {\n this.columns[id].hidden = true;\n }\n });\n }\n this.dispatchUpdate();\n }\n }\n\n toggleColumn(id: number) {\n this.columns[id].hidden = !this.columns[id].hidden;\n\n this.disabledColumns = this.columns\n .filter((column: Column) => column.hidden)\n .map((column: Column) => column.name);\n\n if (this.localStorageID !== undefined) {\n localStorage.setItem(\n this.localStorageID,\n JSON.stringify(this.disabledColumns)\n );\n }\n\n this.dispatchUpdate();\n }\n\n updateColumn(e: Event, id: number) {\n const input = e.target as HTMLElement;\n const el = input.shadowRoot?.querySelector('input');\n\n this.columns[id].hidden = !el?.checked;\n\n this.disabledColumns = this.columns\n .filter((column: Column) => column.hidden)\n .map((column: Column) => column.name);\n\n if (this.localStorageID !== undefined) {\n localStorage.setItem(\n this.localStorageID,\n JSON.stringify(this.disabledColumns)\n );\n }\n\n this.dispatchUpdate();\n }\n\n dispatchUpdate(columns = this.columns) {\n this.dispatchEvent(\n new CustomEvent('columnFilter', {\n detail: {\n columns,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n dragstart(e: DragEvent) {\n const el = e.target as HTMLElement;\n this.dragEvent.sourceEl = el;\n el.style.opacity = '0.3';\n const id = Number(el.getAttribute('data-id') as string);\n this.dragEvent.startId = id;\n }\n\n dragend() {\n if (this.dragEvent.startId !== this.dragEvent.targetId) {\n const reorderedColumns = [...this.columns];\n const el = reorderedColumns.splice(this.dragEvent.startId, 1)[0];\n reorderedColumns.splice(this.dragEvent.targetId, 0, el);\n this.dispatchEvent(\n new CustomEvent('reorderColumns', {\n detail: {\n reorderedColumns,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n this.dragEvent.sourceEl?.style.removeProperty('opacity');\n this.dragEvent = {\n sourceEl: null,\n startId: -1,\n targetId: -1,\n };\n }\n\n dragenter(e: DragEvent) {\n const el = e.target as HTMLElement;\n if (el.classList.contains('drag-target')) {\n const target = Number(el.getAttribute('data-id') as string);\n this.dragEvent.targetId = target;\n }\n }\n\n render() {\n return html`<div class=\"grid-menu\">\n <span\n @click=${() => {\n this.isDropdownVisible = true;\n }}\n @keyDown=${(e: KeyboardEvent) => {\n if (triggerKeys.includes(e.key)) {\n this.isDropdownVisible = true;\n }\n }}\n class=\"list list-dropdown\"\n >\n <ix-icon-button icon=\"list\"></ix-icon-button>\n ${this.disabledColumns.length > 0\n ? html`<div class=\"active\"></div>`\n : nothing}\n ${this.isDropdownVisible\n ? html` <div\n class=\"dropdown-content\"\n @dragover=${(e: DragEvent) => e.preventDefault()}\n @dragstart=${this.dragstart}\n @dragend=${this.dragend}\n @dragenter=${this.dragenter}\n >\n ${repeat(\n this.columns,\n (col: Column) => col.name,\n (col: Column, id: number) => html`<div\n class=${col.hidden ? 'disabled' : ''}\n >\n <label\n class=${`ix-switch-label drag-target ${\n this.dragEvent.startId === id ? 'dragOrigin' : ''\n }`}\n draggable=\"true\"\n data-id=${id}\n >\n <ix-switch\n .selected=${!col.hidden}\n @change=${(e: Event) => this.updateColumn(e, id)}\n >\n </ix-switch>\n <p>${col.header}</p>\n <ix-icon class=\"draggable\">drag_handle</ix-icon>\n </label>\n </div>`\n )}\n </div>`\n : nothing}\n </span>\n </div>`;\n }\n}\n"]}
@@ -31,6 +31,26 @@ export const IxGridColumnFilterStyles = css `
31
31
  .dropdown-content label {
32
32
  display: flex;
33
33
  align-items: center;
34
+ background-color: rgb(249, 249, 249);
35
+ }
36
+ .dropdown-content label.dragOrigin {
37
+ background: #ff000017;
38
+ outline: 1px #ff9d9d dashed;
39
+ }
40
+ .dropdown-content label p {
41
+ flex: 2;
42
+ }
43
+ .dropdown-content label ix-icon.draggable {
44
+ font-size: 24px;
45
+ color: var(--md-sys-color-primary, #1456e0);
46
+ cursor: move; /* fallback if grab cursor is unsupported */
47
+ cursor: grab;
48
+ cursor: -moz-grab;
49
+ cursor: -webkit-grab;
50
+ opacity: 0;
51
+ }
52
+ .dropdown-content label:hover ix-icon.draggable {
53
+ opacity: 1;
34
54
  }
35
55
  .active {
36
56
  position: absolute;
@@ -1 +1 @@
1
- {"version":3,"file":"grid-column-filter-styles.js","sourceRoot":"","sources":["../../src/components/grid-column-filter-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoE1C,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const IxGridColumnFilterStyles = css`\n .dropdown-content {\n position: absolute;\n background-color: #f9f9f9;\n min-width: 160px;\n box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);\n z-index: 1;\n -webkit-box-align: center;\n align-items: center;\n cursor: pointer;\n vertical-align: middle;\n -webkit-tap-highlight-color: transparent;\n padding: 10px;\n }\n .dropdown-content > div {\n margin: 0px;\n font-family: 'Open Sans', sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 14px;\n line-height: 24px;\n letter-spacing: 0.25px;\n color: #092241;\n display: block;\n cursor: pointer;\n }\n .dropdown-content span:hover {\n background-color: #f1f1f1;\n }\n .dropdown-content label {\n display: flex;\n align-items: center;\n }\n .active {\n position: absolute;\n right: 0;\n top: 0;\n height: 8px;\n width: 8px;\n background-color: #db0028;\n border-radius: 50%;\n }\n ix-switch {\n padding: 2px 4px;\n --md-switch-track-height: 12px;\n --md-switch-track-width: 35px;\n --md-sys-color-primary: rgba(20, 86, 224, 0.68);\n --md-sys-color-on-primary: #1456e0;\n --md-sys-color-primary-container: #1456e0;\n --md-switch-handle-height: 19px;\n --md-switch-handle-width: 18px;\n --md-sys-color-surface-container-highest: #9e9e9e;\n --md-sys-color-outline: #9e9e9e;\n --md-switch-pressed-handle-height: 19px;\n --md-switch-pressed-handle-width: 18px;\n --md-switch-handle-color: #fff;\n --md-sys-color-on-surface-variant: white;\n --selected-handle-height: 19px;\n --selected-handle-width: 18px;\n --_pressed-handle-height: 19px;\n --_pressed-handle-width: 18px;\n --md-switch-selected-handle-height: 19px;\n --md-switch-selected-handle-width: 18px;\n margin: 11px 8px 1px 0px;\n }\n .list {\n position: relative;\n }\n`;\n"]}
1
+ {"version":3,"file":"grid-column-filter-styles.js","sourceRoot":"","sources":["../../src/components/grid-column-filter-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwF1C,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const IxGridColumnFilterStyles = css`\n .dropdown-content {\n position: absolute;\n background-color: #f9f9f9;\n min-width: 160px;\n box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);\n z-index: 1;\n -webkit-box-align: center;\n align-items: center;\n cursor: pointer;\n vertical-align: middle;\n -webkit-tap-highlight-color: transparent;\n padding: 10px;\n }\n .dropdown-content > div {\n margin: 0px;\n font-family: 'Open Sans', sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 14px;\n line-height: 24px;\n letter-spacing: 0.25px;\n color: #092241;\n display: block;\n cursor: pointer;\n }\n .dropdown-content span:hover {\n background-color: #f1f1f1;\n }\n .dropdown-content label {\n display: flex;\n align-items: center;\n background-color: rgb(249, 249, 249);\n }\n .dropdown-content label.dragOrigin {\n background: #ff000017;\n outline: 1px #ff9d9d dashed;\n }\n .dropdown-content label p {\n flex: 2;\n }\n .dropdown-content label ix-icon.draggable {\n font-size: 24px;\n color: var(--md-sys-color-primary, #1456e0);\n cursor: move; /* fallback if grab cursor is unsupported */\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n opacity: 0;\n }\n .dropdown-content label:hover ix-icon.draggable {\n opacity: 1;\n }\n .active {\n position: absolute;\n right: 0;\n top: 0;\n height: 8px;\n width: 8px;\n background-color: #db0028;\n border-radius: 50%;\n }\n ix-switch {\n padding: 2px 4px;\n --md-switch-track-height: 12px;\n --md-switch-track-width: 35px;\n --md-sys-color-primary: rgba(20, 86, 224, 0.68);\n --md-sys-color-on-primary: #1456e0;\n --md-sys-color-primary-container: #1456e0;\n --md-switch-handle-height: 19px;\n --md-switch-handle-width: 18px;\n --md-sys-color-surface-container-highest: #9e9e9e;\n --md-sys-color-outline: #9e9e9e;\n --md-switch-pressed-handle-height: 19px;\n --md-switch-pressed-handle-width: 18px;\n --md-switch-handle-color: #fff;\n --md-sys-color-on-surface-variant: white;\n --selected-handle-height: 19px;\n --selected-handle-width: 18px;\n --_pressed-handle-height: 19px;\n --_pressed-handle-width: 18px;\n --md-switch-selected-handle-height: 19px;\n --md-switch-selected-handle-width: 18px;\n margin: 11px 8px 1px 0px;\n }\n .list {\n position: relative;\n }\n`;\n"]}
package/package.json CHANGED
@@ -3,13 +3,13 @@
3
3
  "description": "Webcomponent ix-grid following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "Digital Realty",
6
- "version": "1.0.6",
6
+ "version": "1.0.11",
7
7
  "type": "module",
8
- "main": "dist/src/index.js",
9
- "module": "dist/src/index.js",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.js",
10
10
  "exports": {
11
- ".": "./dist/src/index.js",
12
- "./ix-grid.js": "./dist/src/ix-grid.js"
11
+ ".": "./dist/index.js",
12
+ "./ix-grid.js": "./dist/ix-grid.js"
13
13
  },
14
14
  "publishConfig": {
15
15
  "access": "public"
@@ -25,10 +25,10 @@
25
25
  "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\""
26
26
  },
27
27
  "dependencies": {
28
- "@digital-realty/ix-icon": "*",
29
- "@digital-realty/ix-icon-button": "^1.0.19",
30
- "@digital-realty/ix-select": "*",
31
- "@digital-realty/ix-switch": "*",
28
+ "@digital-realty/ix-icon": "^1.0.3",
29
+ "@digital-realty/ix-icon-button": "^1.0.21",
30
+ "@digital-realty/ix-select": "^1.0.21",
31
+ "@digital-realty/ix-switch": "^2.1.9",
32
32
  "@vaadin/grid": "^24.3.2",
33
33
  "lit": "^2.0.2"
34
34
  },
@@ -91,5 +91,5 @@
91
91
  "prettier --write"
92
92
  ]
93
93
  },
94
- "gitHead": "b9d0668d204a87407a723acbae1f4fd46c7e90b1"
94
+ "gitHead": "a93ad0076764dc26321faa51bc504ff6b534d836"
95
95
  }
package/src/IxGrid.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { html, LitElement, nothing } from 'lit';
2
- import { property, state } from 'lit/decorators.js';
2
+ import { property, state, query } from 'lit/decorators.js';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
4
  import '@vaadin/grid';
5
5
  import { columnBodyRenderer, columnHeaderRenderer } from '@vaadin/grid/lit.js';
@@ -30,6 +30,8 @@ export interface Column {
30
30
  export class IxGrid extends LitElement {
31
31
  static readonly styles = [IxGridViewStyles];
32
32
 
33
+ @query('vaadin-grid') grid!: HTMLElement;
34
+
33
35
  @property({ type: Array }) columns: Column[] = [];
34
36
 
35
37
  @property({ type: Array }) rows: Row[] = [];
@@ -56,12 +58,14 @@ export class IxGrid extends LitElement {
56
58
 
57
59
  @state() private filters: Filter[] = [];
58
60
 
61
+ @state() _columns: Column[] = [];
62
+
59
63
  @state() isLoading = false;
60
64
 
61
65
  @state() isExpanded = false;
62
66
 
63
67
  get columnNames() {
64
- return this.columns.map((column: Column) => column.name);
68
+ return this._columns.map((column: Column) => column.name);
65
69
  }
66
70
 
67
71
  private async updatePage() {
@@ -130,6 +134,44 @@ export class IxGrid extends LitElement {
130
134
  </div>
131
135
  `;
132
136
 
137
+ connectedCallback() {
138
+ super.connectedCallback();
139
+ this._columns = this.columns;
140
+ }
141
+
142
+ async reorderColumnsFromTable() {
143
+ // calulate column order from table header flex order
144
+ const headerNodes = Array.from(
145
+ this.grid?.shadowRoot?.querySelectorAll('th') || []
146
+ );
147
+ if (headerNodes.length) {
148
+ const columnOrder = headerNodes
149
+ .map((el, id) => ({ id, flexPosition: Number(el.style.order) }))
150
+ .sort((a, b) => a.flexPosition - b.flexPosition)
151
+ .map(el => el.id);
152
+ headerNodes.forEach((el, id) => {
153
+ this._columns[id].width = el.style.width;
154
+ });
155
+ const columnsCorrectlyOrdered = columnOrder.every(
156
+ (x, i) => i === 0 || x > columnOrder[i - 1]
157
+ );
158
+ if (!columnsCorrectlyOrdered) {
159
+ const reorderedColumns = columnOrder.map(id => this._columns[id]);
160
+ this._columns = [...reorderedColumns];
161
+ this.isLoading = true;
162
+ await this.updateComplete;
163
+ this.isLoading = false;
164
+ }
165
+ }
166
+ }
167
+
168
+ async reorderColumnsFromFilter(e: CustomEvent) {
169
+ this._columns = [...e.detail.reorderedColumns];
170
+ this.isLoading = true;
171
+ await this.updateComplete;
172
+ this.isLoading = false;
173
+ }
174
+
133
175
  private renderHeader = () => html`
134
176
  <div class="grid-header">
135
177
  <h2>
@@ -138,18 +180,19 @@ export class IxGrid extends LitElement {
138
180
  </h2>
139
181
  <div class="grid-menu">
140
182
  <ix-grid-column-filter
141
- .columns=${this.columns}
183
+ .columns=${this._columns}
142
184
  localStorageID=${ifDefined(this.localStorageID)}
143
185
  @columnFilter=${(e: CustomEvent) => {
144
186
  e.detail.columns.forEach((column: Column, id: number) => {
145
- this.columns[id].hidden = column.hidden;
187
+ this._columns[id].hidden = column.hidden;
146
188
  });
147
189
  this.updatePage();
148
190
  }}
191
+ @reorderColumns=${this.reorderColumnsFromFilter}
149
192
  ></ix-grid-column-filter>
150
193
  <ix-icon-button icon="download"></ix-icon-button>
151
194
  <ix-grid-row-filter
152
- .columns=${this.columns}
195
+ .columns=${this._columns}
153
196
  @rowFilter=${(e: CustomEvent) => {
154
197
  this.filters = e.detail.filters;
155
198
  this.updatePage();
@@ -196,30 +239,33 @@ export class IxGrid extends LitElement {
196
239
  return html`
197
240
  <div class=${`grid-container ${this.isLoading ? 'loading' : ''}`}>
198
241
  ${this.hideHeader ? nothing : this.renderHeader()}
199
- <vaadin-grid
200
- .items=${this.rowLimit > 0 && !this.isExpanded
201
- ? this.rows.slice(0, this.rowLimit)
202
- : this.rows}
203
- all-rows-visible
204
- column-reordering-allowed
205
- theme="no-border"
206
- >
207
- ${this.columns?.map((column: Column) =>
208
- column.name
209
- ? html`<vaadin-grid-column
210
- ${columnHeaderRenderer(
211
- () => this.renderColumnHeader(column),
212
- this.sortDirection
213
- )}
214
- ${columnBodyRenderer(column.bodyRenderer, [])}
215
- resizable
216
- width=${ifDefined(column.width)}
217
- ?hidden=${column.hidden}
218
- ?frozen-to-end=${column.frozenToEnd}
219
- ></vaadin-grid-column>`
220
- : nothing
221
- )}
222
- </vaadin-grid>
242
+ ${!this.isLoading
243
+ ? html`<vaadin-grid
244
+ .items=${this.rowLimit > 0 && !this.isExpanded
245
+ ? this.rows.slice(0, this.rowLimit)
246
+ : this.rows}
247
+ all-rows-visible
248
+ column-reordering-allowed
249
+ theme="no-border"
250
+ @mouseup=${this.reorderColumnsFromTable}
251
+ >
252
+ ${this._columns?.map((column: Column) =>
253
+ column.name
254
+ ? html`<vaadin-grid-column
255
+ ${columnHeaderRenderer(
256
+ () => this.renderColumnHeader(column),
257
+ this.sortDirection
258
+ )}
259
+ ${columnBodyRenderer(column.bodyRenderer, [])}
260
+ resizable
261
+ width=${ifDefined(column.width)}
262
+ ?hidden=${column.hidden}
263
+ ?frozen-to-end=${column.frozenToEnd}
264
+ ></vaadin-grid-column>`
265
+ : nothing
266
+ )}
267
+ </vaadin-grid>`
268
+ : nothing}
223
269
  ${this.rowLimit > 0
224
270
  ? this.renderRowLimitControls()
225
271
  : this.renderPaginationControls()}
@@ -1,7 +1,8 @@
1
1
  import { LitElement, html, nothing } from 'lit';
2
2
  import { customElement, property, state } from 'lit/decorators.js';
3
+ import { repeat } from 'lit/directives/repeat.js';
3
4
  import '@digital-realty/ix-icon-button/ix-icon-button.js';
4
- import '@digital-realty/ix-select/ix-select.js';
5
+ import '@digital-realty/ix-icon/ix-icon.js';
5
6
  import '@digital-realty/ix-switch/ix-switch.js';
6
7
  import { IxGridViewStyles } from '../grid-view-styles.js';
7
8
  import { IxGridColumnFilterStyles } from './grid-column-filter-styles.js';
@@ -21,6 +22,16 @@ export class IxGridColumnFilter extends LitElement {
21
22
 
22
23
  @state() disabledColumns: string[] = [];
23
24
 
25
+ @state() dragEvent: {
26
+ sourceEl: HTMLElement | null;
27
+ startId: number;
28
+ targetId: number;
29
+ } = {
30
+ sourceEl: null,
31
+ startId: -1,
32
+ targetId: -1,
33
+ };
34
+
24
35
  connectedCallback() {
25
36
  super.connectedCallback();
26
37
  document.addEventListener('click', this.outerInteraction);
@@ -103,8 +114,47 @@ export class IxGridColumnFilter extends LitElement {
103
114
  );
104
115
  }
105
116
 
117
+ dragstart(e: DragEvent) {
118
+ const el = e.target as HTMLElement;
119
+ this.dragEvent.sourceEl = el;
120
+ el.style.opacity = '0.3';
121
+ const id = Number(el.getAttribute('data-id') as string);
122
+ this.dragEvent.startId = id;
123
+ }
124
+
125
+ dragend() {
126
+ if (this.dragEvent.startId !== this.dragEvent.targetId) {
127
+ const reorderedColumns = [...this.columns];
128
+ const el = reorderedColumns.splice(this.dragEvent.startId, 1)[0];
129
+ reorderedColumns.splice(this.dragEvent.targetId, 0, el);
130
+ this.dispatchEvent(
131
+ new CustomEvent('reorderColumns', {
132
+ detail: {
133
+ reorderedColumns,
134
+ },
135
+ bubbles: true,
136
+ composed: true,
137
+ })
138
+ );
139
+ }
140
+ this.dragEvent.sourceEl?.style.removeProperty('opacity');
141
+ this.dragEvent = {
142
+ sourceEl: null,
143
+ startId: -1,
144
+ targetId: -1,
145
+ };
146
+ }
147
+
148
+ dragenter(e: DragEvent) {
149
+ const el = e.target as HTMLElement;
150
+ if (el.classList.contains('drag-target')) {
151
+ const target = Number(el.getAttribute('data-id') as string);
152
+ this.dragEvent.targetId = target;
153
+ }
154
+ }
155
+
106
156
  render() {
107
- return html` <div class="grid-menu">
157
+ return html`<div class="grid-menu">
108
158
  <span
109
159
  @click=${() => {
110
160
  this.isDropdownVisible = true;
@@ -121,18 +171,33 @@ export class IxGridColumnFilter extends LitElement {
121
171
  ? html`<div class="active"></div>`
122
172
  : nothing}
123
173
  ${this.isDropdownVisible
124
- ? html` <div class="dropdown-content">
125
- ${this.columns?.map(
174
+ ? html` <div
175
+ class="dropdown-content"
176
+ @dragover=${(e: DragEvent) => e.preventDefault()}
177
+ @dragstart=${this.dragstart}
178
+ @dragend=${this.dragend}
179
+ @dragenter=${this.dragenter}
180
+ >
181
+ ${repeat(
182
+ this.columns,
183
+ (col: Column) => col.name,
126
184
  (col: Column, id: number) => html`<div
127
185
  class=${col.hidden ? 'disabled' : ''}
128
186
  >
129
- <label class="ix-switch-label">
187
+ <label
188
+ class=${`ix-switch-label drag-target ${
189
+ this.dragEvent.startId === id ? 'dragOrigin' : ''
190
+ }`}
191
+ draggable="true"
192
+ data-id=${id}
193
+ >
130
194
  <ix-switch
131
195
  .selected=${!col.hidden}
132
196
  @change=${(e: Event) => this.updateColumn(e, id)}
133
197
  >
134
198
  </ix-switch>
135
199
  <p>${col.header}</p>
200
+ <ix-icon class="draggable">drag_handle</ix-icon>
136
201
  </label>
137
202
  </div>`
138
203
  )}
@@ -32,6 +32,26 @@ export const IxGridColumnFilterStyles = css`
32
32
  .dropdown-content label {
33
33
  display: flex;
34
34
  align-items: center;
35
+ background-color: rgb(249, 249, 249);
36
+ }
37
+ .dropdown-content label.dragOrigin {
38
+ background: #ff000017;
39
+ outline: 1px #ff9d9d dashed;
40
+ }
41
+ .dropdown-content label p {
42
+ flex: 2;
43
+ }
44
+ .dropdown-content label ix-icon.draggable {
45
+ font-size: 24px;
46
+ color: var(--md-sys-color-primary, #1456e0);
47
+ cursor: move; /* fallback if grab cursor is unsupported */
48
+ cursor: grab;
49
+ cursor: -moz-grab;
50
+ cursor: -webkit-grab;
51
+ opacity: 0;
52
+ }
53
+ .dropdown-content label:hover ix-icon.draggable {
54
+ opacity: 1;
35
55
  }
36
56
  .active {
37
57
  position: absolute;
package/tsconfig.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "skipLibCheck": true,
3
4
  "target": "es2018",
4
5
  "module": "esnext",
5
6
  "moduleResolution": "node",
@@ -11,7 +11,7 @@ export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
11
11
  exportConditions: ['browser', 'development'],
12
12
  },
13
13
 
14
- port: 8028,
14
+ port: 8030,
15
15
 
16
16
  /** Filter out lit dev mode logs */
17
17
  filterBrowserLogs(log) {