@kubex/zinc 1.0.7 → 1.0.8
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/custom-elements.json +318 -10
- package/dist/vscode.html-custom-data.json +33 -5
- package/dist/web-types.json +80 -12
- package/dist/zn.d.ts +53 -3
- package/dist/zn.min.js +371 -311
- package/docs/data/products-table.json +203 -0
- package/docs/pages/components/button.md +25 -0
- package/docs/pages/components/data-table.md +21 -0
- package/docs/pages/components/header.md +7 -0
- package/docs/pages/components/order-table.md +82 -5
- package/package.json +1 -1
- package/src/components/button/button.component.ts +168 -10
- package/src/components/button/button.scss +115 -0
- package/src/components/content-block/content-block.component.ts +18 -7
- package/src/components/content-block/content-block.scss +4 -2
- package/src/components/data-select/data-select.component.ts +0 -1
- package/src/components/data-table/data-table.component.ts +112 -20
- package/src/components/data-table/data-table.scss +14 -3
- package/src/components/editor/editor.scss +1 -0
- package/src/components/expanding-action/expanding-action.component.ts +1 -1
- package/src/components/header/header.component.ts +8 -2
- package/src/components/header/header.scss +5 -1
- package/src/components/linked-select/linked-select.component.ts +1 -0
- package/src/components/menu/menu.component.ts +0 -1
- package/src/components/navbar/navbar.component.ts +1 -1
- package/src/components/note/note.component.ts +70 -2
- package/src/components/note/note.scss +26 -4
- package/src/components/order-table/order-table.component.ts +49 -28
- package/src/components/panel/panel.component.ts +3 -1
- package/src/components/rating/rating.component.ts +10 -9
- package/src/components/rating/rating.scss +15 -1
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
border-color: transparent;
|
|
24
24
|
height: 100%;
|
|
25
25
|
display: inline-flex;
|
|
26
|
+
position: relative;
|
|
26
27
|
|
|
27
28
|
&.button--info {
|
|
28
29
|
--btn-color: var(--zn-color-info);
|
|
@@ -39,6 +40,10 @@
|
|
|
39
40
|
&.button--success {
|
|
40
41
|
--btn-color: var(--zn-color-success);
|
|
41
42
|
}
|
|
43
|
+
|
|
44
|
+
&__label--hidden {
|
|
45
|
+
visibility: hidden;
|
|
46
|
+
}
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
.button.button--muted-notification {
|
|
@@ -306,6 +311,116 @@
|
|
|
306
311
|
}
|
|
307
312
|
}
|
|
308
313
|
|
|
314
|
+
.button--loading-bg {
|
|
315
|
+
background-color: #e0e0e0;
|
|
316
|
+
|
|
317
|
+
&-transparent {
|
|
318
|
+
background-color: transparent;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.button--loading {
|
|
323
|
+
&-fill {
|
|
324
|
+
pointer-events: none;
|
|
325
|
+
position: absolute;
|
|
326
|
+
z-index: 1;
|
|
327
|
+
background-color: rgba(var(--btn-color), .85);
|
|
328
|
+
border-radius: inherit;
|
|
329
|
+
transition: width 0s;
|
|
330
|
+
animation: loading-fill-grow var(--loading-duration, 2s) linear forwards;
|
|
331
|
+
inset: -1px;
|
|
332
|
+
|
|
333
|
+
&-transparent {
|
|
334
|
+
background-color: rgba(var(--zn-primary), 0.1);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
&-container {
|
|
339
|
+
position: absolute;
|
|
340
|
+
top: 0;
|
|
341
|
+
left: 0;
|
|
342
|
+
width: 100%;
|
|
343
|
+
height: 100%;
|
|
344
|
+
display: flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
justify-content: center;
|
|
347
|
+
pointer-events: none;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
&-text-bottom, &-text-top {
|
|
351
|
+
width: 100%;
|
|
352
|
+
height: 100%;
|
|
353
|
+
display: flex;
|
|
354
|
+
align-items: center;
|
|
355
|
+
justify-content: center;
|
|
356
|
+
font-size: inherit;
|
|
357
|
+
font-weight: inherit;
|
|
358
|
+
user-select: none;
|
|
359
|
+
position: absolute;
|
|
360
|
+
top: 0;
|
|
361
|
+
left: 0;
|
|
362
|
+
pointer-events: none;
|
|
363
|
+
|
|
364
|
+
.loading-countdown {
|
|
365
|
+
margin-left: 3px;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
&-left {
|
|
369
|
+
justify-content: flex-start;
|
|
370
|
+
padding-inline-start: 7px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
&-right {
|
|
374
|
+
justify-content: flex-end;
|
|
375
|
+
padding-inline-end: 7px;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
&-text-bottom {
|
|
380
|
+
z-index: 2;
|
|
381
|
+
color: rgba(var(--btn-color), .85);
|
|
382
|
+
|
|
383
|
+
&-transparent {
|
|
384
|
+
color: inherit;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
&-text-top {
|
|
389
|
+
z-index: 3;
|
|
390
|
+
color: inherit;
|
|
391
|
+
/* Animate the reveal from left to right using a mask */
|
|
392
|
+
mask-image: linear-gradient(90deg, #000 0%, #000 100%);
|
|
393
|
+
mask-size: 0 100%;
|
|
394
|
+
mask-repeat: no-repeat;
|
|
395
|
+
animation: loading-text-reveal var(--loading-duration, 2s) linear forwards;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.button--relative-wrapper {
|
|
400
|
+
position: relative;
|
|
401
|
+
display: inline-flex;
|
|
402
|
+
height: 100%;
|
|
403
|
+
width: 100%;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
@keyframes loading-fill-grow {
|
|
407
|
+
from {
|
|
408
|
+
width: 0;
|
|
409
|
+
}
|
|
410
|
+
to {
|
|
411
|
+
width: 100%;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
@keyframes loading-text-reveal {
|
|
416
|
+
from {
|
|
417
|
+
mask-size: 0 100%;
|
|
418
|
+
}
|
|
419
|
+
to {
|
|
420
|
+
mask-size: 100% 100%;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
309
424
|
:host([vertical-align="center"]) {
|
|
310
425
|
align-self: center;
|
|
311
426
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {classMap} from "lit/directives/class-map.js";
|
|
2
2
|
import {deepQuerySelectorAll} from "../../utilities/query";
|
|
3
3
|
import {HasSlotController} from "../../internal/slot";
|
|
4
|
+
import type {PropertyValues} from 'lit';
|
|
4
5
|
import {html, nothing, unsafeCSS} from 'lit';
|
|
5
6
|
import {property, queryAssignedNodes, queryAsync} from 'lit/decorators.js';
|
|
6
7
|
import {unsafeHTML} from 'lit-html/directives/unsafe-html.js';
|
|
7
8
|
import ZincElement from "../../internal/zinc-element";
|
|
8
|
-
import type {PropertyValues} from 'lit';
|
|
9
9
|
import type ZnTile from "../tile";
|
|
10
10
|
|
|
11
11
|
import styles from './content-block.scss';
|
|
@@ -29,7 +29,11 @@ export default class ContentBlock extends ZincElement {
|
|
|
29
29
|
@property() avatar = '';
|
|
30
30
|
|
|
31
31
|
@property({type: Boolean, reflect: true}) outbound = false;
|
|
32
|
+
|
|
33
|
+
@property({type: Boolean, attribute: "no-collapse"}) noCollapse = false;
|
|
34
|
+
|
|
32
35
|
@property({type: Boolean, reflect: true}) short = false;
|
|
36
|
+
|
|
33
37
|
@property({attribute: 'default-display', reflect: true}) defaultDisplay: 'text' | 'html' = 'text';
|
|
34
38
|
|
|
35
39
|
@queryAssignedNodes({slot: 'html', flatten: true}) htmlNodes!: Node[];
|
|
@@ -84,6 +88,9 @@ export default class ContentBlock extends ZincElement {
|
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
private _collapseContent(e: Event) {
|
|
91
|
+
if (this.noCollapse) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
87
94
|
const target = e.target as HTMLElement;
|
|
88
95
|
const headerClick = target.classList.contains('content-block-header') ||
|
|
89
96
|
target.parentElement?.classList.contains('content-block-header');
|
|
@@ -186,20 +193,24 @@ export default class ContentBlock extends ZincElement {
|
|
|
186
193
|
flush-footer="${hasFooter || nothing}"
|
|
187
194
|
class="${classMap({
|
|
188
195
|
'content-block--outbound': this.outbound,
|
|
189
|
-
'content-block--short': this.short
|
|
196
|
+
'content-block--short': this.short,
|
|
197
|
+
'content-block--collapsible': !this.noCollapse
|
|
190
198
|
})}">
|
|
191
199
|
|
|
192
200
|
<zn-header class="content-block-header"
|
|
193
|
-
caption="${this.sender}"
|
|
194
201
|
description="${this.truncateText()}"
|
|
195
202
|
@click="${this._collapseContent}">
|
|
196
203
|
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
204
|
+
<slot name="icon">
|
|
205
|
+
<zn-icon src="${this.avatar}"
|
|
206
|
+
library="avatar"
|
|
207
|
+
round></zn-icon>
|
|
208
|
+
</slot>
|
|
209
|
+
|
|
210
|
+
<slot name="caption" slot="caption">${this.sender}</slot>
|
|
200
211
|
|
|
201
212
|
<div slot="actions">
|
|
202
|
-
<small>${this.time}</small>
|
|
213
|
+
<slot name="actions"><small>${this.time}</small></slot>
|
|
203
214
|
${showActions ? html`
|
|
204
215
|
<zn-dropdown>
|
|
205
216
|
<zn-button slot="trigger" icon="more_vert" icon-size="24" color="transparent"
|
|
@@ -231,7 +231,6 @@ export default class ZnDataSelect extends ZincElement implements ZincFormControl
|
|
|
231
231
|
private _updatePrefix() {
|
|
232
232
|
// Set the prefix of the select to the selected values prefix
|
|
233
233
|
const selectedOption = this.select.selectedOptions[0];
|
|
234
|
-
console.log('selectedOption', selectedOption);
|
|
235
234
|
if (selectedOption && (this.iconPosition !== 'none' || this.iconOnly) && this.selectPrefix) {
|
|
236
235
|
if (this.iconPosition === 'none' && this.iconOnly) {
|
|
237
236
|
this.iconPosition = 'start';
|
|
@@ -2,7 +2,7 @@ import {classMap} from "lit/directives/class-map.js";
|
|
|
2
2
|
import {type CSSResultGroup, html, nothing, type TemplateResult, unsafeCSS} from 'lit';
|
|
3
3
|
import {HasSlotController} from "../../internal/slot";
|
|
4
4
|
import {ifDefined} from "lit/directives/if-defined.js";
|
|
5
|
-
import {property} from 'lit/decorators.js';
|
|
5
|
+
import {property, query} from 'lit/decorators.js';
|
|
6
6
|
import {ref} from "lit/directives/ref.js";
|
|
7
7
|
import {Task} from "@lit/task";
|
|
8
8
|
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
|
@@ -184,7 +184,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
184
184
|
@property({attribute: "empty-state-icon"}) emptyStateIcon: string = "data_alert";
|
|
185
185
|
|
|
186
186
|
// Hide the checkbox column
|
|
187
|
-
@property({attribute: 'hide-checkboxes', type: Boolean}) hideCheckboxes: boolean
|
|
187
|
+
@property({attribute: 'hide-checkboxes', type: Boolean}) hideCheckboxes: boolean;
|
|
188
188
|
|
|
189
189
|
@property() filters: [] = [];
|
|
190
190
|
|
|
@@ -192,6 +192,12 @@ export default class ZnDataTable extends ZincElement {
|
|
|
192
192
|
|
|
193
193
|
@property({attribute: "no-initial-load", type: Boolean}) noInitialLoad: boolean = false;
|
|
194
194
|
|
|
195
|
+
@property({attribute: 'group-by'}) groupBy = '';
|
|
196
|
+
|
|
197
|
+
@property() groups = '';
|
|
198
|
+
|
|
199
|
+
@query('#select-all-rows') selectAllButton: ZnButton;
|
|
200
|
+
|
|
195
201
|
// Data Table Properties
|
|
196
202
|
private _initialLoad = true;
|
|
197
203
|
private _lastTableContent: TemplateResult = html``;
|
|
@@ -226,6 +232,11 @@ export default class ZnDataTable extends ZincElement {
|
|
|
226
232
|
return {rows: [], page: 1, perPage: this.itemsPerPage, total: 0};
|
|
227
233
|
}
|
|
228
234
|
|
|
235
|
+
if (this.groupBy) {
|
|
236
|
+
// we want to load all the data possible so we can group and show multiple tables
|
|
237
|
+
this.itemsPerPage = 1000;
|
|
238
|
+
}
|
|
239
|
+
|
|
229
240
|
const requestData: DataRequest = {
|
|
230
241
|
page: this.page,
|
|
231
242
|
perPage: this.itemsPerPage,
|
|
@@ -390,13 +401,58 @@ export default class ZnDataTable extends ZincElement {
|
|
|
390
401
|
return this.emptyState();
|
|
391
402
|
}
|
|
392
403
|
|
|
404
|
+
this._rows = this.getRows(data);
|
|
405
|
+
|
|
406
|
+
if (this.groupBy) {
|
|
407
|
+
// we need to group the rows by the group column
|
|
408
|
+
const groupedRows: Record<string, Row[]> = {};
|
|
409
|
+
|
|
410
|
+
// add groups to the current rows
|
|
411
|
+
const toAdd = this.groups.split(',').map(g => g.trim()).filter(g => g.length > 0);
|
|
412
|
+
toAdd.forEach((group) => {
|
|
413
|
+
if (!groupedRows[this.humanize(group)]) {
|
|
414
|
+
groupedRows[this.humanize(group)] = [];
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
this._rows.forEach((row: Row) => {
|
|
419
|
+
const groupCell = row.cells.find((cell: Cell) => cell.column === this.groupBy);
|
|
420
|
+
const groupValue = groupCell ? groupCell.text : 'Ungrouped';
|
|
421
|
+
if (!groupedRows[this.humanize(groupValue)] && (!this.groups || groupValue === 'Ungrouped')) {
|
|
422
|
+
groupedRows[this.humanize(groupValue)] = [];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (groupedRows[this.humanize(groupValue)]) {
|
|
426
|
+
groupedRows[this.humanize(groupValue)].push(row);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// render a table for each group
|
|
431
|
+
return html`
|
|
432
|
+
<zn-sp flush>
|
|
433
|
+
${Object.keys(groupedRows).map((groupKey) => html`
|
|
434
|
+
<div class="table-group">
|
|
435
|
+
<h3 class="table-group__title">${groupKey === "Ungrouped" ? "" : groupKey}</h3>
|
|
436
|
+
${this.renderTableData(groupedRows[groupKey])}
|
|
437
|
+
</div>`
|
|
438
|
+
)}
|
|
439
|
+
</zn-sp>
|
|
440
|
+
`;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
return this.renderTableData(this._rows);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
public humanize(str: string) {
|
|
448
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
public renderTableData(data: any) {
|
|
393
452
|
const filteredHeaders = Object.values(this.headers).filter((header) => {
|
|
394
453
|
return !Object.values(this.hiddenColumns).includes(header.key);
|
|
395
454
|
});
|
|
396
455
|
|
|
397
|
-
this._rows = this.getRows(data);
|
|
398
|
-
|
|
399
|
-
const hasSelectedRows = this.selectedRows.length > 0;
|
|
400
456
|
this.rowHasActions = this._rows.some((row: Row) => row.actions && row.actions.length > 0);
|
|
401
457
|
|
|
402
458
|
// To make sure the cells are in the same order as the headers, we need to map them cell.col to heading.key
|
|
@@ -421,21 +477,17 @@ export default class ZnDataTable extends ZincElement {
|
|
|
421
477
|
<table class="${classMap({
|
|
422
478
|
'table': true,
|
|
423
479
|
'table--standalone': this.standalone,
|
|
424
|
-
'with-hover': !this.unsortable,
|
|
480
|
+
'with-hover': !this.unsortable && !this.hideCheckboxes,
|
|
425
481
|
})}">
|
|
426
482
|
<thead>
|
|
427
483
|
<tr>
|
|
428
|
-
${this.hideCheckboxes || !hasSelectedRows ? html`` : html`
|
|
429
|
-
<th>
|
|
430
|
-
<div><input type="checkbox" @change="${this.selectAll}"></div>
|
|
431
|
-
</th>`}
|
|
432
484
|
${filteredHeaders.map((header: HeaderConfig) => this.renderCellHeader(header))}
|
|
433
485
|
${this.rowHasActions ? html`
|
|
434
486
|
<th></th>` : html``}
|
|
435
487
|
</tr>
|
|
436
488
|
</thead>
|
|
437
489
|
<tbody>
|
|
438
|
-
${
|
|
490
|
+
${data.map((row: Row) => html`
|
|
439
491
|
<tr class="${classMap({'table__row--selected': this.isRowSelected(row)})}">
|
|
440
492
|
${row.cells.map((value: Cell, index: number) => this.renderCellBody(index, value))}
|
|
441
493
|
${this.rowHasActions ? this.renderActions(row) : null}
|
|
@@ -552,10 +604,37 @@ export default class ZnDataTable extends ZincElement {
|
|
|
552
604
|
getActions() {
|
|
553
605
|
const actions = [];
|
|
554
606
|
|
|
607
|
+
const hasSlots = this.hasSlotController.test(ActionSlots.delete.valueOf())
|
|
608
|
+
|| this.hasSlotController.test(ActionSlots.modify.valueOf())
|
|
609
|
+
|| this.hasSlotController.test(ActionSlots.create.valueOf());
|
|
610
|
+
|
|
611
|
+
if(!hasSlots) {
|
|
612
|
+
return [];
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
if (!this.hideCheckboxes && this._rows.length > 0) {
|
|
616
|
+
actions.push(html`
|
|
617
|
+
<zn-button @click="${this.selectAll}"
|
|
618
|
+
id="select-all-rows"
|
|
619
|
+
color="transparent"
|
|
620
|
+
size="x-small"
|
|
621
|
+
icon="indeterminate_check_box"
|
|
622
|
+
icon-size="22"
|
|
623
|
+
icon-color="primary"
|
|
624
|
+
tooltip="Select All"
|
|
625
|
+
slot="trigger">
|
|
626
|
+
</zn-button>`);
|
|
627
|
+
}
|
|
628
|
+
|
|
555
629
|
if (this.selectedRows.length > 0) {
|
|
556
630
|
actions.push(html`
|
|
557
|
-
<zn-button @click="${this.clearSelectedRows}"
|
|
558
|
-
|
|
631
|
+
<zn-button @click="${this.clearSelectedRows}"
|
|
632
|
+
color="transparent"
|
|
633
|
+
size="x-small"
|
|
634
|
+
icon="disabled_by_default"
|
|
635
|
+
icon-size="22"
|
|
636
|
+
tooltip="Clear Selection"
|
|
637
|
+
slot="trigger">
|
|
559
638
|
</zn-button>`);
|
|
560
639
|
|
|
561
640
|
if (this.hasSlotController.test(ActionSlots.delete.valueOf())) {
|
|
@@ -613,21 +692,25 @@ export default class ZnDataTable extends ZincElement {
|
|
|
613
692
|
}
|
|
614
693
|
|
|
615
694
|
selectAll(event: Event) {
|
|
616
|
-
const
|
|
617
|
-
|
|
695
|
+
const button = event.target as ZnButton;
|
|
696
|
+
if (button.disabled) return;
|
|
618
697
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
698
|
+
if (this.numberOfRowsSelected === this._rows.length) {
|
|
699
|
+
this.clearSelectedRows(event);
|
|
700
|
+
return;
|
|
622
701
|
}
|
|
623
702
|
|
|
624
|
-
this.selectedRows =
|
|
703
|
+
this.selectedRows = this._rows;
|
|
625
704
|
this.numberOfRowsSelected = this.selectedRows.length;
|
|
626
705
|
this.updateKeys();
|
|
627
706
|
this.requestUpdate();
|
|
628
707
|
}
|
|
629
708
|
|
|
630
709
|
selectRow(e: Event) {
|
|
710
|
+
if (this.hideCheckboxes) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
631
714
|
if (!(e.target && (e.target instanceof Element))) {
|
|
632
715
|
return;
|
|
633
716
|
}
|
|
@@ -833,7 +916,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
833
916
|
|
|
834
917
|
return html`
|
|
835
918
|
<td
|
|
836
|
-
@click="${this.selectRow}"
|
|
919
|
+
@click="${this.hideCheckboxes ? undefined : this.selectRow}"
|
|
837
920
|
class="${classMap({
|
|
838
921
|
'table__cell': true,
|
|
839
922
|
'table__cell--wide': headerKey === this.wideColumn,
|
|
@@ -889,10 +972,19 @@ export default class ZnDataTable extends ZincElement {
|
|
|
889
972
|
}
|
|
890
973
|
|
|
891
974
|
private updateKeys() {
|
|
975
|
+
this.updateSelectAll();
|
|
892
976
|
this.updateModifyKeys();
|
|
893
977
|
this.updateDeleteKeys();
|
|
894
978
|
}
|
|
895
979
|
|
|
980
|
+
private updateSelectAll() {
|
|
981
|
+
if (this.numberOfRowsSelected === this._rows.length) {
|
|
982
|
+
this.selectAllButton.icon = 'check_box';
|
|
983
|
+
} else {
|
|
984
|
+
this.selectAllButton.icon = 'indeterminate_check_box';
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
896
988
|
private updateModifyKeys() {
|
|
897
989
|
this.updateActionKeys('modify-action');
|
|
898
990
|
}
|
|
@@ -364,11 +364,9 @@ table tbody tr.table__row--selected {
|
|
|
364
364
|
border-bottom-right-radius: var(--zn-border-radius-large);
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
& + tr td {
|
|
367
|
+
& + tr.table__row--selected td {
|
|
368
368
|
border-top: 0 !important;
|
|
369
|
-
}
|
|
370
369
|
|
|
371
|
-
& + tr.table__row--selected td {
|
|
372
370
|
&:first-of-type {
|
|
373
371
|
border-top-left-radius: 0;
|
|
374
372
|
}
|
|
@@ -400,3 +398,16 @@ table tbody tr.table__row--selected {
|
|
|
400
398
|
table:has(tbody tr:first-of-type.table__row--selected) thead tr th {
|
|
401
399
|
border-bottom-color: var(--zn-color-purple-600) !important;
|
|
402
400
|
}
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
.table-group__title {
|
|
404
|
+
font-weight: var(--zn-font-weight-semibold);
|
|
405
|
+
font-size: var(--zn-font-size-large);
|
|
406
|
+
color: rgba(var(--zn-text-panel-title), 100%);
|
|
407
|
+
line-height: var(--zn-line-height-looser);
|
|
408
|
+
padding-left: var(--zn-spacing-medium);
|
|
409
|
+
margin: 0;
|
|
410
|
+
overflow: hidden;
|
|
411
|
+
white-space: nowrap;
|
|
412
|
+
text-overflow: ellipsis;
|
|
413
|
+
}
|
|
@@ -39,6 +39,7 @@ export default class ZnHeader extends ZincElement {
|
|
|
39
39
|
@property({type: Boolean}) transparent: boolean = false;
|
|
40
40
|
|
|
41
41
|
@property() caption: string;
|
|
42
|
+
@property() icon: string;
|
|
42
43
|
|
|
43
44
|
@property() description: string;
|
|
44
45
|
|
|
@@ -136,7 +137,8 @@ export default class ZnHeader extends ZincElement {
|
|
|
136
137
|
|
|
137
138
|
|
|
138
139
|
<div class="content" part="content">
|
|
139
|
-
${hasBreadcrumb ? html
|
|
140
|
+
${hasBreadcrumb ? html`
|
|
141
|
+
<slot name="breadcrumb" class="breadcrumb"></slot>` : null}
|
|
140
142
|
|
|
141
143
|
${hasPreviousPath ? html`
|
|
142
144
|
<a href="${this.previousPath}" class="caption__back"
|
|
@@ -151,7 +153,11 @@ export default class ZnHeader extends ZincElement {
|
|
|
151
153
|
|
|
152
154
|
<div class="caption">
|
|
153
155
|
<div part="header-left" class="header__left">
|
|
154
|
-
<span class="header__caption" part="header-caption"
|
|
156
|
+
<span class="header__caption" part="header-caption">
|
|
157
|
+
${this.icon ? html`
|
|
158
|
+
<zn-icon class="header__icon" src="${this.icon}"></zn-icon>` : null}
|
|
159
|
+
<slot name="caption">${this.caption}</slot>
|
|
160
|
+
</span>
|
|
155
161
|
${this.description ? html`
|
|
156
162
|
<span class="header__description"
|
|
157
163
|
part="header-description">${this.description}</span>`
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
overflow: hidden;
|
|
25
25
|
white-space: nowrap;
|
|
26
26
|
text-overflow: ellipsis;
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: var(--zn-spacing-x-small);
|
|
29
|
+
align-items: center;
|
|
30
|
+
text-wrap: auto;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
&--has-breadcrumb {
|
|
@@ -195,7 +199,7 @@
|
|
|
195
199
|
text-decoration: none;
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
zn-icon {
|
|
202
|
+
a zn-icon {
|
|
199
203
|
cursor: pointer;
|
|
200
204
|
|
|
201
205
|
&:hover {
|
|
@@ -169,7 +169,6 @@ export default class ZnMenu extends ZincElement {
|
|
|
169
169
|
// get the parent dropdown and close it
|
|
170
170
|
(closestMenu?.closest('zn-dropdown') as ZnDropdown | null)?.hide();
|
|
171
171
|
|
|
172
|
-
console.log('emitting select')
|
|
173
172
|
this.emit('zn-select', {detail: {item}});
|
|
174
173
|
}
|
|
175
174
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {classMap} from "lit/directives/class-map.js";
|
|
2
2
|
import {type colors} from "../data-select/providers/color-data-provider";
|
|
3
3
|
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
4
|
-
import {property} from "lit/decorators.js";
|
|
4
|
+
import {property, state} from "lit/decorators.js";
|
|
5
5
|
import ZincElement from '../../internal/zinc-element';
|
|
6
6
|
|
|
7
7
|
import styles from './note.scss';
|
|
@@ -32,6 +32,58 @@ export default class ZnNote extends ZincElement {
|
|
|
32
32
|
@property({reflect: true}) date: string = '';
|
|
33
33
|
@property({type: HTMLElement, reflect: true}) body: string = '';
|
|
34
34
|
|
|
35
|
+
// Number of lines at which the note body collapses; 0 disables collapsing
|
|
36
|
+
@property({type: Number, attribute: 'collapse-at-lines', reflect: true}) collapseAtLines: number = 3;
|
|
37
|
+
|
|
38
|
+
// Internal state: whether the body is currently expanded
|
|
39
|
+
@state() private expanded = false;
|
|
40
|
+
|
|
41
|
+
// Internal state: whether the content actually overflows the clamp
|
|
42
|
+
@state() private _isOverflowing = false;
|
|
43
|
+
|
|
44
|
+
private _toggleExpand = () => {
|
|
45
|
+
this.expanded = !this.expanded;
|
|
46
|
+
// re-evaluate overflow after toggle (in case of dynamic content)
|
|
47
|
+
this.updateComplete.then(() => this._measureOverflow());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private _measureOverflow() {
|
|
51
|
+
// Only relevant when collapseAtLines is set and not expanded
|
|
52
|
+
const container = this.shadowRoot?.querySelector('.note__body-container') as HTMLElement | null;
|
|
53
|
+
if (!container) {
|
|
54
|
+
this._isOverflowing = false;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (this.collapseAtLines <= 0) {
|
|
59
|
+
this._isOverflowing = false;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Temporarily ensure clamped styles are applied to measure
|
|
64
|
+
container.style.setProperty('--note-collapse-lines', String(this.collapseAtLines));
|
|
65
|
+
container.classList.toggle('note__body--clamped', !this.expanded);
|
|
66
|
+
|
|
67
|
+
// element starts hidden, cannot measure
|
|
68
|
+
if (container.clientHeight === 0) {
|
|
69
|
+
this._isOverflowing = false;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Measure overflow
|
|
74
|
+
this._isOverflowing = container.scrollHeight > container.clientHeight + 1; // +1 for rounding errors
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
protected firstUpdated() {
|
|
78
|
+
// Initial measurement of overflow
|
|
79
|
+
this._measureOverflow();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected updated() {
|
|
83
|
+
// Re-measure on any update to catch slot/content changes
|
|
84
|
+
this._measureOverflow();
|
|
85
|
+
}
|
|
86
|
+
|
|
35
87
|
protected render(): unknown {
|
|
36
88
|
return html`
|
|
37
89
|
<div class="${classMap({
|
|
@@ -52,7 +104,23 @@ export default class ZnNote extends ZincElement {
|
|
|
52
104
|
<small>${this.date}</small>
|
|
53
105
|
</slot>
|
|
54
106
|
</div>
|
|
55
|
-
<
|
|
107
|
+
<div class="${classMap({
|
|
108
|
+
'note__body-container': true,
|
|
109
|
+
'note__body--clamped': this.collapseAtLines > 0 && !this.expanded
|
|
110
|
+
})}" style="--note-collapse-lines: ${this.collapseAtLines}">
|
|
111
|
+
<slot class="note__body"></slot>
|
|
112
|
+
</div>
|
|
113
|
+
${this.collapseAtLines > 0 && this._isOverflowing ? html`
|
|
114
|
+
<div class="note__toggle">
|
|
115
|
+
<zn-button color="transparent"
|
|
116
|
+
size="content"
|
|
117
|
+
class="note__toggle__btn"
|
|
118
|
+
@click="${this._toggleExpand}"
|
|
119
|
+
aria-expanded="${String(this.expanded)}">
|
|
120
|
+
${this.expanded ? 'Show less' : 'Show more'}
|
|
121
|
+
</zn-button>
|
|
122
|
+
</div>
|
|
123
|
+
` : ''}
|
|
56
124
|
<slot name="footer" class="note__footer"></slot>
|
|
57
125
|
</div>
|
|
58
126
|
`;
|