@parksw/sw-ui-components 0.0.2 → 0.0.5

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/index.js CHANGED
@@ -1,4 +1,801 @@
1
- export * from './my-element.js';
2
- export * from './my-button.js';
3
- export * from './my-calendar.js';
4
- export * from './my-grid.js';
1
+ import { LitElement, css, html } from "lit";
2
+ import { customElement, property, state } from "lit/decorators.js";
3
+ import { when } from "lit/directives/when.js";
4
+ import { classMap } from "lit/directives/class-map.js";
5
+ import { styleMap } from "lit/directives/style-map.js";
6
+ import { repeat } from "lit/directives/repeat.js";
7
+ function __decorate(e, c, l, u) {
8
+ var d = arguments.length, f = d < 3 ? c : u === null ? u = Object.getOwnPropertyDescriptor(c, l) : u, p;
9
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") f = Reflect.decorate(e, c, l, u);
10
+ else for (var m = e.length - 1; m >= 0; m--) (p = e[m]) && (f = (d < 3 ? p(f) : d > 3 ? p(c, l, f) : p(c, l)) || f);
11
+ return d > 3 && f && Object.defineProperty(c, l, f), f;
12
+ }
13
+ var MyElement = class extends LitElement {
14
+ constructor(...e) {
15
+ super(...e), this.name = "World";
16
+ }
17
+ render() {
18
+ return html`
19
+ <h1>Hello, ${this.name}!</h1>
20
+ `;
21
+ }
22
+ static #e = this.styles = css`
23
+ :host {
24
+ display: block;
25
+ border: solid 1px gray;
26
+ padding: 16px;
27
+ max-width: 800px;
28
+ }
29
+ `;
30
+ };
31
+ __decorate([property()], MyElement.prototype, "name", void 0), MyElement = __decorate([customElement("my-element")], MyElement);
32
+ var MyButton = class extends LitElement {
33
+ constructor(...e) {
34
+ super(...e), this.label = "Button", this.disabled = !1, this.variant = "primary";
35
+ }
36
+ render() {
37
+ return html`
38
+ <button
39
+ class="button ${this.variant}"
40
+ ?disabled=${this.disabled}
41
+ >
42
+ ${this.label}
43
+ </button>
44
+ `;
45
+ }
46
+ static #e = this.styles = css`
47
+ .button {
48
+ border: none;
49
+ color: white;
50
+ padding: 12px 24px;
51
+ text-align: center;
52
+ text-decoration: none;
53
+ display: inline-block;
54
+ font-size: 16px;
55
+ margin: 4px 2px;
56
+ cursor: pointer;
57
+ border-radius: 8px;
58
+ transition: background-color 0.3s ease;
59
+ }
60
+
61
+ .button:disabled {
62
+ cursor: not-allowed;
63
+ opacity: 0.6;
64
+ }
65
+
66
+ .primary {
67
+ background-color: #4CAF50; /* Green */
68
+ }
69
+
70
+ .primary:hover:not(:disabled) {
71
+ background-color: #45a049;
72
+ }
73
+
74
+ .secondary {
75
+ background-color: #008CBA; /* Blue */
76
+ }
77
+
78
+ .secondary:hover:not(:disabled) {
79
+ background-color: #007bb5;
80
+ }
81
+ `;
82
+ };
83
+ __decorate([property({ type: String })], MyButton.prototype, "label", void 0), __decorate([property({
84
+ type: Boolean,
85
+ reflect: !0
86
+ })], MyButton.prototype, "disabled", void 0), __decorate([property({ type: String })], MyButton.prototype, "variant", void 0), MyButton = __decorate([customElement("my-button")], MyButton);
87
+ var MyCalendar = class extends LitElement {
88
+ constructor(...e) {
89
+ super(...e), this.date = /* @__PURE__ */ new Date();
90
+ }
91
+ get year() {
92
+ return this.date.getFullYear();
93
+ }
94
+ get month() {
95
+ return this.date.getMonth();
96
+ }
97
+ _changeMonth(e) {
98
+ this.date = new Date(this.year, this.month + e, 1);
99
+ }
100
+ _renderHeader() {
101
+ return html`
102
+ <div class="header">
103
+ <button @click=${() => this._changeMonth(-1)}>‹</button>
104
+ <div class="month-year">${this.date.toLocaleString("default", { month: "long" })} ${this.year}</div>
105
+ <button @click=${() => this._changeMonth(1)}>›</button>
106
+ </div>
107
+ `;
108
+ }
109
+ _renderDaysOfWeek() {
110
+ return html`
111
+ <div class="days-of-week">
112
+ ${[
113
+ "Sun",
114
+ "Mon",
115
+ "Tue",
116
+ "Wed",
117
+ "Thu",
118
+ "Fri",
119
+ "Sat"
120
+ ].map((e) => html`<div>${e}</div>`)}
121
+ </div>
122
+ `;
123
+ }
124
+ _renderDates() {
125
+ let e = /* @__PURE__ */ new Date(), c = new Date(this.year, this.month, 1).getDay(), u = new Date(this.year, this.month + 1, 0).getDate(), d = [];
126
+ for (let e = 0; e < c; e++) d.push(html`<div class="date-cell empty"></div>`);
127
+ for (let c = 1; c <= u; c++) {
128
+ let u = this.year === e.getFullYear() && this.month === e.getMonth() && c === e.getDate();
129
+ d.push(html`<div class="date-cell ${u ? "today" : ""}">${c}</div>`);
130
+ }
131
+ return html`<div class="date-grid">${d}</div>`;
132
+ }
133
+ render() {
134
+ return html`
135
+ <div class="calendar-container">
136
+ ${this._renderHeader()}
137
+ ${this._renderDaysOfWeek()}
138
+ ${this._renderDates()}
139
+ </div>
140
+ `;
141
+ }
142
+ static #e = this.styles = css`
143
+ :host {
144
+ display: block;
145
+ max-width: 350px;
146
+ border: 1px solid #ccc;
147
+ border-radius: 8px;
148
+ padding: 16px;
149
+ font-family: sans-serif;
150
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
151
+ }
152
+
153
+ .header {
154
+ display: flex;
155
+ justify-content: space-between;
156
+ align-items: center;
157
+ margin-bottom: 16px;
158
+ }
159
+
160
+ .header button {
161
+ background: none;
162
+ border: 1px solid #ccc;
163
+ border-radius: 50%;
164
+ width: 32px;
165
+ height: 32px;
166
+ cursor: pointer;
167
+ font-size: 18px;
168
+ transition: background-color 0.2s;
169
+ }
170
+
171
+ .header button:hover {
172
+ background-color: #eee;
173
+ }
174
+
175
+ .month-year {
176
+ font-size: 1.2em;
177
+ font-weight: bold;
178
+ }
179
+
180
+ .days-of-week, .date-grid {
181
+ display: grid;
182
+ grid-template-columns: repeat(7, 1fr);
183
+ text-align: center;
184
+ }
185
+
186
+ .days-of-week > div {
187
+ font-weight: bold;
188
+ padding-bottom: 8px;
189
+ font-size: 0.9em;
190
+ color: #666;
191
+ }
192
+
193
+ .date-cell {
194
+ padding: 4px 0;
195
+ cursor: pointer;
196
+ border-radius: 50%;
197
+ width: 32px;
198
+ height: 32px;
199
+ display: flex;
200
+ justify-content: center;
201
+ align-items: center;
202
+ margin: 2px auto;
203
+ transition: background-color 0.2s;
204
+ }
205
+
206
+ .date-cell:not(.empty):hover {
207
+ background-color: #eee;
208
+ }
209
+
210
+ .date-cell.today {
211
+ background-color: #4CAF50;
212
+ color: white;
213
+ font-weight: bold;
214
+ }
215
+ `;
216
+ };
217
+ __decorate([state()], MyCalendar.prototype, "date", void 0), MyCalendar = __decorate([customElement("my-calendar")], MyCalendar);
218
+ var MyGrid = class extends LitElement {
219
+ constructor() {
220
+ super(), this.columns = [], this.data = [], this.itemsPerPage = 10, this.columnReordering = !0, this.height = "auto", this.enableColumnVisibility = !0, this.enableFilter = !0, this._sortKey = null, this._sortDirection = "asc", this._draggedColumnIndex = null, this._dragOverColumnIndex = null, this._selectedRowId = null, this._selectedColumnKey = null, this._filterValues = {}, this._activeFilterColumn = null, this._filterSearchTerm = "", this._currentPage = 1, this._hiddenColumns = /* @__PURE__ */ new Set(), this._showColumnMenu = !1, this._filterMenuSortDirection = "asc", this._resizingColumnIndex = null, this._startX = 0, this._startWidth = 0, this._handleDocumentClick = this._handleDocumentClick.bind(this), this._handleResizeMove = this._handleResizeMove.bind(this), this._handleResizeEnd = this._handleResizeEnd.bind(this);
221
+ }
222
+ connectedCallback() {
223
+ super.connectedCallback(), document.addEventListener("click", this._handleDocumentClick), document.addEventListener("mousemove", this._handleResizeMove), document.addEventListener("mouseup", this._handleResizeEnd);
224
+ }
225
+ disconnectedCallback() {
226
+ super.disconnectedCallback(), document.removeEventListener("click", this._handleDocumentClick), document.removeEventListener("mousemove", this._handleResizeMove), document.removeEventListener("mouseup", this._handleResizeEnd);
227
+ }
228
+ updated(e) {
229
+ super.updated(e), e.has("enableFilter") && (this._filterValues = {}, this._activeFilterColumn = null, this._filterSearchTerm = "", this._resetPage());
230
+ }
231
+ _handleDocumentClick(e) {
232
+ this._showColumnMenu &&= !1, this._activeFilterColumn && (this._activeFilterColumn = null, this._filterSearchTerm = "");
233
+ }
234
+ get _visibleColumns() {
235
+ return this.columns.filter((e) => !this._hiddenColumns.has(e.key));
236
+ }
237
+ get _gridColumnTemplate() {
238
+ let e = "";
239
+ return this.enableColumnVisibility && (e += "40px "), e += this._visibleColumns.map((e) => e.width || "minmax(150px, 1fr)").join(" "), e;
240
+ }
241
+ _resetPage() {
242
+ this._currentPage = 1;
243
+ }
244
+ _toggleColumnMenu(e) {
245
+ e.stopPropagation(), this._showColumnMenu = !this._showColumnMenu, this._activeFilterColumn = null;
246
+ }
247
+ _toggleColumnVisibility(e) {
248
+ let c = new Set(this._hiddenColumns);
249
+ c.has(e) ? c.delete(e) : c.add(e), this._hiddenColumns = c;
250
+ }
251
+ _handleItemsPerPageChange(e) {
252
+ let c = e.target;
253
+ this.itemsPerPage = Number(c.value), this._resetPage();
254
+ }
255
+ _handleHeaderClick(e) {
256
+ this._sortKey === e ? this._sortDirection = this._sortDirection === "asc" ? "desc" : "asc" : (this._sortKey = e, this._sortDirection = "asc"), this._resetPage();
257
+ }
258
+ _toggleFilterMenu(e, c) {
259
+ e.stopPropagation(), this._activeFilterColumn === c ? this._activeFilterColumn = null : (this._activeFilterColumn = c, this._showColumnMenu = !1, this._filterMenuSortDirection = "asc"), this._filterSearchTerm = "";
260
+ }
261
+ _toggleFilterMenuSort(e) {
262
+ e.stopPropagation(), this._filterMenuSortDirection = this._filterMenuSortDirection === "asc" ? "desc" : "asc";
263
+ }
264
+ _getUniqueValues(e) {
265
+ return Array.from(new Set(this.data.map((c) => c[e]))).sort((e, c) => {
266
+ if (e === c) return 0;
267
+ if (e == null) return 1;
268
+ if (c == null) return -1;
269
+ let l = 0;
270
+ if (typeof e == "number" && typeof c == "number") l = e - c;
271
+ else {
272
+ let u = Date.parse(String(e)), d = Date.parse(String(c));
273
+ l = !isNaN(u) && !isNaN(d) && String(e).includes("-") && String(c).includes("-") ? u - d : String(e).localeCompare(String(c));
274
+ }
275
+ return this._filterMenuSortDirection === "asc" ? l : -l;
276
+ });
277
+ }
278
+ _isFilterActive(e) {
279
+ return !!this._filterValues[e];
280
+ }
281
+ _handleFilterValueChange(e, c, l) {
282
+ let u = this._filterValues[e];
283
+ if (u) {
284
+ let d = new Set(u);
285
+ l ? d.add(c) : d.delete(c);
286
+ let f = this._getUniqueValues(e);
287
+ if (d.size === f.length) {
288
+ let c = { ...this._filterValues };
289
+ delete c[e], this._filterValues = c;
290
+ } else this._filterValues = {
291
+ ...this._filterValues,
292
+ [e]: d
293
+ };
294
+ } else if (!l) {
295
+ let l = this._getUniqueValues(e);
296
+ u = new Set(l), u.delete(c), this._filterValues = {
297
+ ...this._filterValues,
298
+ [e]: u
299
+ };
300
+ }
301
+ this._resetPage();
302
+ }
303
+ _handleSelectAll(e, c) {
304
+ if (c) {
305
+ let c = { ...this._filterValues };
306
+ delete c[e], this._filterValues = c;
307
+ } else this._filterValues = {
308
+ ...this._filterValues,
309
+ [e]: /* @__PURE__ */ new Set()
310
+ };
311
+ this._resetPage();
312
+ }
313
+ _handleFilterSearch(e) {
314
+ this._filterSearchTerm = e.target.value;
315
+ }
316
+ _handleResizeStart(e, c) {
317
+ e.preventDefault(), e.stopPropagation(), this._resizingColumnIndex = c, this._startX = e.pageX;
318
+ let l = this.shadowRoot?.querySelectorAll(".header-cell"), u = c + (this.enableColumnVisibility ? 1 : 0);
319
+ l && l[u] ? this._startWidth = l[u].getBoundingClientRect().width : this._startWidth = 150;
320
+ }
321
+ _handleResizeMove(e) {
322
+ if (this._resizingColumnIndex !== null) {
323
+ let c = e.pageX - this._startX, l = Math.max(50, this._startWidth + c), u = this._visibleColumns[this._resizingColumnIndex], d = this.columns.findIndex((e) => e.key === u.key);
324
+ if (d !== -1) {
325
+ let e = [...this.columns];
326
+ e[d] = {
327
+ ...e[d],
328
+ width: `${l}px`
329
+ }, this.columns = e;
330
+ }
331
+ }
332
+ }
333
+ _handleResizeEnd() {
334
+ this._resizingColumnIndex = null;
335
+ }
336
+ get _filteredData() {
337
+ if (!this.enableFilter) return this.data;
338
+ let e = this.data, c = Object.keys(this._filterValues);
339
+ return c.length > 0 && (e = e.filter((e) => c.every((c) => {
340
+ let l = this._filterValues[c];
341
+ return l ? l.size === 0 ? !1 : l.has(e[c]) : !0;
342
+ }))), e;
343
+ }
344
+ get _sortedData() {
345
+ let e = this._filteredData;
346
+ return this._sortKey ? [...e].sort((e, c) => {
347
+ let l = e[this._sortKey], u = c[this._sortKey];
348
+ if (l === u) return 0;
349
+ if (l == null) return 1;
350
+ if (u == null) return -1;
351
+ let d = 0;
352
+ return d = typeof l == "string" && typeof u == "string" ? l.localeCompare(u) : typeof l == "number" && typeof u == "number" ? l - u : String(l).localeCompare(String(u)), this._sortDirection === "asc" ? d : -d;
353
+ }) : e;
354
+ }
355
+ get _paginatedData() {
356
+ let e = (this._currentPage - 1) * this.itemsPerPage, c = e + this.itemsPerPage;
357
+ return this._sortedData.slice(e, c);
358
+ }
359
+ _handleCellClick(e, c) {
360
+ let l = e.id;
361
+ this._selectedRowId === l && this._selectedColumnKey === c ? (this._selectedRowId = null, this._selectedColumnKey = null) : (this._selectedRowId = l, this._selectedColumnKey = c);
362
+ }
363
+ _handleDragStart(e, c) {
364
+ if (this._resizingColumnIndex !== null) {
365
+ e.preventDefault();
366
+ return;
367
+ }
368
+ if (!this.columnReordering) {
369
+ e.preventDefault();
370
+ return;
371
+ }
372
+ if (this._draggedColumnIndex = c, e.dataTransfer) {
373
+ e.dataTransfer.effectAllowed = "move", e.dataTransfer.setData("text/plain", c.toString());
374
+ let l = e.target;
375
+ e.dataTransfer.setDragImage(l, e.offsetX, e.offsetY);
376
+ }
377
+ }
378
+ _handleDragOver(e, c) {
379
+ this.columnReordering && (e.preventDefault(), e.dataTransfer && (e.dataTransfer.dropEffect = "move"), this._draggedColumnIndex !== null && this._draggedColumnIndex !== c && (this._dragOverColumnIndex = c));
380
+ }
381
+ _handleDragLeave() {
382
+ this.columnReordering && (this._dragOverColumnIndex = null);
383
+ }
384
+ _handleDrop(e, c) {
385
+ if (this.columnReordering) {
386
+ if (e.preventDefault(), e.dataTransfer) {
387
+ let l = parseInt(e.dataTransfer.getData("text/plain"), 10);
388
+ if (this._draggedColumnIndex !== null && l !== c) {
389
+ let e = [...this._visibleColumns], [u] = e.splice(l, 1);
390
+ e.splice(c, 0, u);
391
+ let d = [], f = 0;
392
+ for (let c of this.columns) this._hiddenColumns.has(c.key) ? d.push(c) : d.push(e[f++]);
393
+ this.columns = d;
394
+ }
395
+ }
396
+ this._draggedColumnIndex = null, this._dragOverColumnIndex = null;
397
+ }
398
+ }
399
+ _handleDragEnd() {
400
+ this.columnReordering && (this._draggedColumnIndex = null, this._dragOverColumnIndex = null);
401
+ }
402
+ _formatLink(e, c) {
403
+ return e.replace(/{(\w+)}/g, (e, l) => c[l] === void 0 ? e : String(c[l]));
404
+ }
405
+ _renderCell(e, c) {
406
+ let u = e[c.key];
407
+ return c.linkTemplate ? html`<a href="${this._formatLink(c.linkTemplate, e)}">${u}</a>` : u;
408
+ }
409
+ _renderColumnMenu() {
410
+ return this._showColumnMenu ? html`
411
+ <div class="column-menu" @click=${(e) => e.stopPropagation()}>
412
+ ${this.columns.map((e) => html`
413
+ <label>
414
+ <input
415
+ type="checkbox"
416
+ .checked=${!this._hiddenColumns.has(e.key)}
417
+ @change=${() => this._toggleColumnVisibility(e.key)}
418
+ />
419
+ ${e.header}
420
+ </label>
421
+ `)}
422
+ </div>
423
+ ` : null;
424
+ }
425
+ _renderFilterMenu(e, c) {
426
+ if (this._activeFilterColumn !== e) return null;
427
+ let u = this._getUniqueValues(e).filter((e) => String(e).toLowerCase().includes(this._filterSearchTerm.toLowerCase())), d = this._filterValues[e], f = !d, p = f || !!d && u.every((e) => d.has(e));
428
+ return html`
429
+ <div class="${c > this._visibleColumns.length - 3 ? "filter-menu right-aligned" : "filter-menu"}" @click=${(e) => e.stopPropagation()}>
430
+ <div class="filter-search-container">
431
+ <input
432
+ type="text"
433
+ class="filter-search"
434
+ placeholder="Search..."
435
+ .value=${this._filterSearchTerm}
436
+ @input=${this._handleFilterSearch}
437
+ />
438
+ <button class="filter-sort-btn" @click=${this._toggleFilterMenuSort} title="Sort Values">
439
+ ${this._filterMenuSortDirection === "asc" ? "▲" : "▼"}
440
+ </button>
441
+ </div>
442
+ <div class="filter-list">
443
+ <label>
444
+ <input
445
+ type="checkbox"
446
+ .checked=${p}
447
+ @change=${(c) => this._handleSelectAll(e, c.target.checked)}
448
+ />
449
+ (Select All)
450
+ </label>
451
+ ${u.map((c) => html`
452
+ <label>
453
+ <input
454
+ type="checkbox"
455
+ .checked=${f || !!d && d.has(c)}
456
+ @change=${(l) => this._handleFilterValueChange(e, c, l.target.checked)}
457
+ />
458
+ ${String(c)}
459
+ </label>
460
+ `)}
461
+ </div>
462
+ </div>
463
+ `;
464
+ }
465
+ _renderHeader(e) {
466
+ return html`
467
+ <div class="grid-header">
468
+ <div class="grid-row" style=${styleMap(e)}>
469
+ ${when(this.enableColumnVisibility, () => html`
470
+ <div class="grid-cell header-cell settings-cell" @click=${this._toggleColumnMenu}>
471
+ ⚙️
472
+ ${this._renderColumnMenu()}
473
+ </div>
474
+ `)}
475
+ ${this._visibleColumns.map((e, c) => {
476
+ let u = {
477
+ "grid-cell": !0,
478
+ "header-cell": !0,
479
+ "drag-over": this._dragOverColumnIndex === c,
480
+ reorderable: this.columnReordering,
481
+ "align-center": e.align === "center",
482
+ "align-right": e.align === "right"
483
+ };
484
+ return html`
485
+ <div
486
+ .draggable=${this.columnReordering}
487
+ class=${classMap(u)}
488
+ @click=${() => this._handleHeaderClick(e.key)}
489
+ @dragstart=${(e) => this._handleDragStart(e, c)}
490
+ @dragover=${(e) => this._handleDragOver(e, c)}
491
+ @dragleave=${this._handleDragLeave}
492
+ @drop=${(e) => this._handleDrop(e, c)}
493
+ @dragend=${this._handleDragEnd}
494
+ >
495
+ <span class="header-text">${e.header}</span>
496
+ <div class="header-icons">
497
+ ${when(this.enableFilter, () => html`
498
+ <span class="filter-icon ${this._isFilterActive(e.key) ? "active" : ""}" @click=${(c) => this._toggleFilterMenu(c, e.key)}>
499
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
500
+ <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
501
+ </svg>
502
+ </span>
503
+ `)}
504
+ ${this._sortKey === e.key ? html`<span class="sort-indicator">${this._sortDirection === "asc" ? "▲" : "▼"}</span>` : ""}
505
+ </div>
506
+ ${this._renderFilterMenu(e.key, c)}
507
+ <div class="resize-handle" @mousedown=${(e) => this._handleResizeStart(e, c)} @click=${(e) => e.stopPropagation()}></div>
508
+ </div>
509
+ `;
510
+ })}
511
+ </div>
512
+ </div>
513
+ `;
514
+ }
515
+ _renderBody(e) {
516
+ return html`
517
+ <div class="grid-body">
518
+ ${repeat(this._paginatedData, (e) => e.id, (c) => html`
519
+ <div class="grid-row ${this.rowClass ? this.rowClass(c) : ""}" style=${styleMap(e)}>
520
+ ${when(this.enableColumnVisibility, () => html`<div class="grid-cell data-cell"></div>`)}
521
+ ${this._visibleColumns.map((e) => {
522
+ let u = {
523
+ "grid-cell": !0,
524
+ "data-cell": !0,
525
+ selected: this._selectedRowId === c.id && this._selectedColumnKey === e.key,
526
+ "align-center": e.align === "center",
527
+ "align-right": e.align === "right",
528
+ [`col-${e.key}`]: !0
529
+ };
530
+ return html`
531
+ <div
532
+ title="${String(c[e.key] ?? "")}"
533
+ class=${classMap(u)}
534
+ @click=${() => this._handleCellClick(c, e.key)}
535
+ >
536
+ ${this._renderCell(c, e)}
537
+ </div>
538
+ `;
539
+ })}
540
+ </div>
541
+ `)}
542
+ </div>
543
+ `;
544
+ }
545
+ _renderPaginationControls() {
546
+ let e = this._sortedData.length, c = Math.ceil(e / this.itemsPerPage);
547
+ return c <= 1 ? "" : html`
548
+ <div class="pagination">
549
+ <div class="pagination-group">
550
+ <button @click=${() => this._currentPage = 1} ?disabled=${this._currentPage === 1}>&lt;&lt; First</button>
551
+ <button @click=${() => this._currentPage--} ?disabled=${this._currentPage === 1}>&lt; Previous</button>
552
+ </div>
553
+ <div class="pagination-info">
554
+ <span>Page ${this._currentPage} of ${c}</span>
555
+ </div>
556
+ <div class="pagination-group">
557
+ <button @click=${() => this._currentPage++} ?disabled=${this._currentPage === c}>Next &gt;</button>
558
+ <button @click=${() => this._currentPage = c} ?disabled=${this._currentPage === c}>Last &gt;&gt;</button>
559
+ </div>
560
+ </div>
561
+ `;
562
+ }
563
+ render() {
564
+ let e = { height: this.height }, c = { "grid-template-columns": this._gridColumnTemplate };
565
+ return html`
566
+ <div class="toolbar">
567
+ <div class="items-per-page">
568
+ <span>Rows per page:</span>
569
+ <select @change=${this._handleItemsPerPageChange} .value=${this.itemsPerPage.toString()}>
570
+ <option value="10">10</option>
571
+ <option value="20">20</option>
572
+ <option value="50">50</option>
573
+ </select>
574
+ </div>
575
+ </div>
576
+ <div class="grid-wrapper" style=${styleMap(e)}>
577
+ <div class="grid-container">
578
+ ${this._renderHeader(c)}
579
+ ${this._renderBody(c)}
580
+ </div>
581
+ </div>
582
+ ${this._renderPaginationControls()}
583
+ `;
584
+ }
585
+ static #e = this.styles = css`
586
+ :host {
587
+ display: block;
588
+ font-family: sans-serif;
589
+ }
590
+ /* Default styles for all elements inside the component */
591
+ * {
592
+ box-sizing: border-box;
593
+ color: #000; /* Default text color black */
594
+ }
595
+ input, select, button {
596
+ background-color: #fff; /* Default background white */
597
+ color: #000; /* Default text color black */
598
+ border: 1px solid #ccc;
599
+ }
600
+
601
+ .toolbar {
602
+ margin-bottom: 8px;
603
+ display: flex;
604
+ justify-content: flex-end;
605
+ align-items: center;
606
+ }
607
+ .toolbar button { padding: 6px 12px; border-radius: 4px; background-color: #f8f8f8; cursor: pointer; }
608
+ .toolbar button:hover { background-color: #eee; }
609
+
610
+ .items-per-page {
611
+ display: flex;
612
+ align-items: center;
613
+ gap: 8px;
614
+ font-size: 0.9em;
615
+ }
616
+ .items-per-page select {
617
+ padding: 4px 8px;
618
+ border-radius: 4px;
619
+ cursor: pointer;
620
+ font-size: 1em;
621
+ color: #000;
622
+ }
623
+ .items-per-page select:hover {
624
+ border-color: #888;
625
+ }
626
+
627
+ .grid-wrapper {
628
+ overflow: auto;
629
+ border: 1px solid #ccc;
630
+ border-radius: 4px;
631
+ }
632
+ .grid-container {
633
+ display: inline-block;
634
+ min-width: 100%;
635
+ vertical-align: top;
636
+ }
637
+ .grid-header {
638
+ position: sticky;
639
+ top: 0;
640
+ z-index: 2;
641
+ background-color: #e8e8e8;
642
+ }
643
+ .grid-row {
644
+ display: grid;
645
+ border-bottom: 1px solid #ddd;
646
+ }
647
+ .grid-body .grid-row:last-of-type {
648
+ border-bottom: none;
649
+ }
650
+ .grid-cell {
651
+ padding: 12px 15px;
652
+ text-align: left;
653
+ color: #000;
654
+ overflow: hidden;
655
+ text-overflow: ellipsis;
656
+ white-space: nowrap;
657
+ border-right: 1px solid #ddd; /* Add right border */
658
+ }
659
+ .grid-cell:last-child {
660
+ border-right: none; /* Remove right border for last cell */
661
+ }
662
+ .grid-cell.align-center { justify-content: center; text-align: center; }
663
+ .grid-cell.align-right { justify-content: flex-end; text-align: right; }
664
+
665
+ .header-cell {
666
+ display: flex;
667
+ align-items: center;
668
+ justify-content: space-between;
669
+ font-weight: bold;
670
+ cursor: pointer;
671
+ user-select: none;
672
+ position: relative;
673
+ overflow: visible;
674
+ border-bottom: 1px solid #ccc; /* Add bottom border to header */
675
+ }
676
+ .header-text {
677
+ overflow: hidden;
678
+ text-overflow: ellipsis;
679
+ white-space: nowrap;
680
+ flex-grow: 1;
681
+ }
682
+ .header-icons {
683
+ display: flex;
684
+ align-items: center;
685
+ gap: 4px;
686
+ }
687
+ .sort-indicator {
688
+ flex-shrink: 0;
689
+ }
690
+ .filter-icon {
691
+ display: flex;
692
+ align-items: center;
693
+ justify-content: center;
694
+ width: 16px;
695
+ height: 16px;
696
+ color: #888; /* Default grey icon */
697
+ padding: 2px;
698
+ border-radius: 2px;
699
+ cursor: pointer;
700
+ }
701
+ .filter-icon:hover {
702
+ color: #000; /* Black icon on hover */
703
+ }
704
+ .filter-icon.active {
705
+ color: #007bff; /* Blue icon when active */
706
+ }
707
+
708
+ .settings-cell {
709
+ justify-content: center;
710
+ position: relative;
711
+ overflow: visible;
712
+ }
713
+
714
+ .column-menu, .filter-menu {
715
+ position: absolute;
716
+ top: 100%;
717
+ left: 0;
718
+ background-color: white;
719
+ border: 1px solid #ccc;
720
+ border-radius: 4px;
721
+ padding: 8px;
722
+ z-index: 100;
723
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
724
+ min-width: 150px;
725
+ display: flex;
726
+ flex-direction: column;
727
+ gap: 4px;
728
+ max-height: 250px;
729
+ overflow-y: auto;
730
+ text-align: left;
731
+ font-weight: normal;
732
+ }
733
+ .filter-menu.right-aligned {
734
+ left: auto;
735
+ right: 0;
736
+ }
737
+ .column-menu label, .filter-menu label {
738
+ display: flex;
739
+ align-items: center;
740
+ gap: 8px;
741
+ cursor: pointer;
742
+ font-weight: normal;
743
+ white-space: nowrap;
744
+ padding: 2px 0;
745
+ }
746
+ .filter-search-container {
747
+ display: flex;
748
+ gap: 4px;
749
+ margin-bottom: 4px;
750
+ }
751
+ .filter-search {
752
+ width: 100%;
753
+ padding: 4px;
754
+ border-radius: 4px;
755
+ flex-grow: 1;
756
+ }
757
+ .filter-sort-btn {
758
+ padding: 4px 8px;
759
+ cursor: pointer;
760
+ font-size: 0.8em;
761
+ }
762
+
763
+ .data-cell { cursor: pointer; }
764
+ .data-cell.selected { background-color: #aedcff; }
765
+ .data-cell a { color: #007bff; text-decoration: none; }
766
+ .data-cell a:hover { text-decoration: underline; }
767
+
768
+ .header-cell.reorderable { cursor: grab; }
769
+ .header-cell.drag-over { background-color: #cceeff; }
770
+
771
+ .grid-body .grid-row:nth-of-type(even) { background-color: #f2f2f2; }
772
+ .grid-body .grid-row:hover { background-color: #e0e0e0; }
773
+
774
+ .pagination {
775
+ display: flex;
776
+ justify-content: space-between;
777
+ align-items: center;
778
+ padding: 12px 0;
779
+ font-size: 0.9em;
780
+ color: #000;
781
+ }
782
+ .pagination-group { display: flex; gap: 8px; }
783
+ .pagination button { padding: 6px 12px; border-radius: 4px; background-color: #f8f8f8; cursor: pointer; }
784
+ .pagination button:disabled { cursor: not-allowed; opacity: 0.5; }
785
+
786
+ .resize-handle {
787
+ position: absolute;
788
+ top: 0;
789
+ right: 0;
790
+ width: 5px;
791
+ height: 100%;
792
+ cursor: col-resize;
793
+ z-index: 1;
794
+ }
795
+ .resize-handle:hover {
796
+ background-color: #007bff;
797
+ }
798
+ `;
799
+ };
800
+ __decorate([property({ type: Array })], MyGrid.prototype, "columns", void 0), __decorate([property({ type: Array })], MyGrid.prototype, "data", void 0), __decorate([property({ type: Number })], MyGrid.prototype, "itemsPerPage", void 0), __decorate([property({ type: Boolean })], MyGrid.prototype, "columnReordering", void 0), __decorate([property({ type: String })], MyGrid.prototype, "height", void 0), __decorate([property({ type: Boolean })], MyGrid.prototype, "enableColumnVisibility", void 0), __decorate([property({ type: Boolean })], MyGrid.prototype, "enableFilter", void 0), __decorate([property()], MyGrid.prototype, "rowClass", void 0), __decorate([state()], MyGrid.prototype, "_sortKey", void 0), __decorate([state()], MyGrid.prototype, "_sortDirection", void 0), __decorate([state()], MyGrid.prototype, "_draggedColumnIndex", void 0), __decorate([state()], MyGrid.prototype, "_dragOverColumnIndex", void 0), __decorate([state()], MyGrid.prototype, "_selectedRowId", void 0), __decorate([state()], MyGrid.prototype, "_selectedColumnKey", void 0), __decorate([state()], MyGrid.prototype, "_filterValues", void 0), __decorate([state()], MyGrid.prototype, "_activeFilterColumn", void 0), __decorate([state()], MyGrid.prototype, "_filterSearchTerm", void 0), __decorate([state()], MyGrid.prototype, "_currentPage", void 0), __decorate([state()], MyGrid.prototype, "_hiddenColumns", void 0), __decorate([state()], MyGrid.prototype, "_showColumnMenu", void 0), __decorate([state()], MyGrid.prototype, "_filterMenuSortDirection", void 0), __decorate([state()], MyGrid.prototype, "_resizingColumnIndex", void 0), MyGrid = __decorate([customElement("my-grid")], MyGrid);
801
+ export { MyButton, MyCalendar, MyElement, MyGrid };