@kubex/zinc 1.1.13 → 1.1.14

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.
Files changed (31) hide show
  1. package/dist/custom-elements.json +198 -7
  2. package/dist/vscode.html-custom-data.json +39 -2
  3. package/dist/web-types.json +77 -4
  4. package/dist/zn.d.ts +61 -4
  5. package/dist/zn.min.css +1 -1
  6. package/dist/zn.min.js +318 -306
  7. package/docs/pages/components/channel-tile.md +3 -3
  8. package/docs/pages/components/chat-message-attachment.md +54 -0
  9. package/docs/pages/components/chat-message.md +18 -1
  10. package/docs/pages/components/data-table.md +1 -3
  11. package/package.json +1 -1
  12. package/scss/shared/_table.scss +9 -23
  13. package/scss/themes/_dark.scss +3 -0
  14. package/scss/themes/_light.scss +4 -0
  15. package/src/components/channel-tile/channel-tile.component.ts +6 -6
  16. package/src/components/chat-message/chat-message.component.ts +14 -5
  17. package/src/components/chat-message/chat-message.scss +37 -12
  18. package/src/components/chat-message-attachment/chat-message-attachment.component.ts +78 -0
  19. package/src/components/chat-message-attachment/chat-message-attachment.scss +32 -0
  20. package/src/components/chat-message-attachment/chat-message-attachment.test.ts +36 -0
  21. package/src/components/chat-message-attachment/index.ts +12 -0
  22. package/src/components/data-table/data-table.component.ts +65 -46
  23. package/src/components/data-table/data-table.scss +32 -58
  24. package/src/components/icon/icon.component.ts +1 -1
  25. package/src/components/icon/icon.scss +2 -1
  26. package/src/components/page/page.component.ts +32 -1
  27. package/src/components/page/page.scss +5 -4
  28. package/src/components/tooltip/tooltip.scss +1 -1
  29. package/src/events/zn-accept.ts +1 -1
  30. package/src/events/zn-reject.ts +1 -1
  31. package/src/zinc.ts +1 -0
@@ -610,12 +610,10 @@ export default class ZnDataTable extends ZincElement {
610
610
  </tr>
611
611
  </thead>
612
612
  <tbody>
613
- ${(data as Row[]).map((row: Row, rowIndex: number) => html`
613
+ ${(data as Row[]).map((row: Row) => html`
614
614
  <tr class="${classMap({
615
615
  'table__row--selected': this.isRowSelected(row),
616
616
  'table__row--data': true,
617
- 'table__row--even': (rowIndex % 2) === 0,
618
- 'table__row--odd': (rowIndex % 2) === 1,
619
617
  })}" data-row-id="${row.id}">
620
618
  ${anyHidden ? this.renderExpanderCell(row) : nothing}
621
619
  ${(visibleRowCells.get(row.id) || row.cells).map((value: Cell, index: number) => this.renderCellBody(index, value))}
@@ -650,15 +648,17 @@ export default class ZnDataTable extends ZincElement {
650
648
  getTableFooter() {
651
649
  const rowSelected = this.getRowsSelected();
652
650
  const pagination = this.getPagination();
651
+ const rowsPerPage = this.getRowsPerPage();
653
652
 
654
- if (rowSelected !== null || pagination !== null) {
653
+ if (rowSelected !== null || pagination !== null || rowsPerPage !== null) {
655
654
  return html`
656
655
  <div class="table__footer">
657
656
  <div class="table__footer__left">
657
+ ${pagination}
658
658
  ${rowSelected}
659
659
  </div>
660
660
  <div class="table__footer__right">
661
- ${pagination}
661
+ ${rowsPerPage}
662
662
  </div>
663
663
  </div>`;
664
664
  }
@@ -673,7 +673,7 @@ export default class ZnDataTable extends ZincElement {
673
673
  <p>${this.numberOfRowsSelected} of ${this._rows.length} rows selected</p>`
674
674
  }
675
675
 
676
- getPagination() {
676
+ getRowsPerPage() {
677
677
  if (this.hidePagination || (this.totalPages <= 1 && this._rows.length <= this.itemsPerPage)) return null;
678
678
 
679
679
  const optionsRowsPerPage = [10, 20, 30, 40, 50];
@@ -692,41 +692,60 @@ export default class ZnDataTable extends ZincElement {
692
692
  </zn-option>`
693
693
  )}
694
694
  </zn-select>
695
- </div>
695
+ </div>`;
696
+ }
696
697
 
697
- ${this.totalPages <= 1
698
- ? html``
699
- : html`
700
- <div class="table__footer__pagination-count">
701
- <p>Page ${this.page} of ${this.totalPages}</p>
702
- </div>
698
+ private getPageRange(): (number | 'ellipsis')[] {
699
+ const total = this.totalPages;
700
+ const current = this.page;
701
+
702
+ if (total <= 7) {
703
+ return Array.from({length: total}, (_, i) => i + 1);
704
+ }
705
+
706
+ const showLeftEllipsis = current > 4;
707
+ const showRightEllipsis = current < total - 3;
708
+
709
+ if (!showLeftEllipsis && showRightEllipsis) {
710
+ return [1, 2, 3, 4, 5, 'ellipsis', total];
711
+ }
703
712
 
704
- <div class="table__footer__pagination-buttons">
705
- <zn-button @click="${this.page !== 1 ? this.goToFirstPage : undefined}"
706
- ?disabled="${this.page === 1}"
707
- icon-size="16"
708
- icon="keyboard_double_arrow_left"
709
- outline>
710
- </zn-button>
711
- <zn-button @click="${this.page !== 1 ? this.goToPreviousPage : undefined}"
712
- ?disabled="${this.page === 1}"
713
- icon-size="16"
714
- icon="chevron_left"
715
- outline>
716
- </zn-button>
717
- <zn-button @click="${this.page !== this.totalPages ? this.goToNextPage : undefined}"
718
- ?disabled="${this.page === this.totalPages}"
719
- icon-size="16"
720
- icon="chevron_right"
721
- outline>
722
- </zn-button>
723
- <zn-button @click="${this.page !== this.totalPages ? this.goToLastPage : undefined}"
724
- ?disabled="${this.page === this.totalPages}"
725
- icon-size="16"
726
- icon="keyboard_double_arrow_right"
727
- outline>
728
- </zn-button>
729
- </div>`}`;
713
+ if (showLeftEllipsis && !showRightEllipsis) {
714
+ return [1, 'ellipsis', total - 4, total - 3, total - 2, total - 1, total];
715
+ }
716
+
717
+ return [1, 'ellipsis', current - 1, current, current + 1, 'ellipsis', total];
718
+ }
719
+
720
+ getPagination() {
721
+ if (this.hidePagination || this.totalPages <= 1) return null;
722
+
723
+ return html`
724
+ <div class="table__footer__pagination-buttons">
725
+ <zn-button @click="${this.page !== 1 ? this.goToFirstPage : undefined}"
726
+ ?disabled="${this.page === 1}"
727
+ icon="arrow_left@lu">First
728
+ </zn-button>
729
+ <zn-button @click="${this.page !== 1 ? this.goToPreviousPage : undefined}"
730
+ ?disabled="${this.page === 1}">Back
731
+ </zn-button>
732
+ ${this.getPageRange().map((p) => p === 'ellipsis'
733
+ ? html`<span class="table__footer__pagination-ellipsis">…</span>`
734
+ : html`
735
+ <zn-button @click="${p !== this.page ? () => this.goToPage(p) : undefined}"
736
+ icon-button="small"
737
+ class="${p === this.page ? 'table__footer__pagination-page--active' : ''}">${p}
738
+ </zn-button>`
739
+ )}
740
+ <zn-button @click="${this.page !== this.totalPages ? this.goToNextPage : undefined}"
741
+ ?disabled="${this.page === this.totalPages}">Next
742
+ </zn-button>
743
+ <zn-button @click="${this.page !== this.totalPages ? this.goToLastPage : undefined}"
744
+ ?disabled="${this.page === this.totalPages}"
745
+ icon="arrow_right@lu"
746
+ icon-position="right">Last
747
+ </zn-button>
748
+ </div>`;
730
749
  }
731
750
 
732
751
  getActions() {
@@ -1005,20 +1024,20 @@ export default class ZnDataTable extends ZincElement {
1005
1024
  if (this.sortColumn !== key) {
1006
1025
  return html`
1007
1026
  <div class="table__head__sort">
1008
- <zn-icon src="unfold_more" size="14"></zn-icon>
1027
+ <zn-icon src="chevrons_up_down@lu" size="14"></zn-icon>
1009
1028
  </div>`;
1010
1029
  }
1011
1030
 
1012
1031
  if (this.sortDirection === 'asc') {
1013
1032
  return html`
1014
1033
  <div class="table__head__sort table__head__sort--active">
1015
- <zn-icon src="arrow_downward_alt" size="16"></zn-icon>
1034
+ <zn-icon src="chevron_down@lu" size="16"></zn-icon>
1016
1035
  </div>`;
1017
1036
  }
1018
1037
 
1019
1038
  return html`
1020
1039
  <div class="table__head__sort table__head__sort--active">
1021
- <zn-icon src="arrow_upward_alt" size="16"></zn-icon>
1040
+ <zn-icon src="chevron_up@lu" size="16"></zn-icon>
1022
1041
  </div>`;
1023
1042
  }
1024
1043
 
@@ -1085,7 +1104,7 @@ export default class ZnDataTable extends ZincElement {
1085
1104
  <td class="table__cell table__cell--expander"></td>`;
1086
1105
 
1087
1106
  const expanded = this._expandedRows.has(row.id);
1088
- const icon = expanded ? 'expand_more' : 'chevron_right';
1107
+ const icon = expanded ? 'chevron_down@lu' : 'chevron_right';
1089
1108
 
1090
1109
  return html`
1091
1110
  <td class="table__cell table__cell--expander">
@@ -1320,9 +1339,9 @@ export default class ZnDataTable extends ZincElement {
1320
1339
  <td class="table__cell table__cell--actions">
1321
1340
  <zn-dropdown placement="bottom-end">
1322
1341
  <zn-button slot="trigger"
1323
- icon="more_vert"
1324
- color="transparent"
1325
- icon-size="24"
1342
+ icon-button
1343
+ plain
1344
+ icon="ellipsis@lu"
1326
1345
  aria-label="Row actions">
1327
1346
  </zn-button>
1328
1347
  <zn-menu>
@@ -17,16 +17,12 @@ table {
17
17
  max-width: 100%;
18
18
  table-layout: auto;
19
19
  text-align: left;
20
- font-size: var(--zn-text-table-content-font-size);
21
- line-height: var(--zn-text-table-content-line-height);
22
- font-weight: var(--zn-text-table-content-font-weight);
20
+ @include wc.text-style(table-content);
23
21
 
24
- tbody tr:nth-of-type(even) {
25
- background-color: unset;
26
- }
27
-
28
- tbody tr.table__row--data.table__row--odd:not(.table__row--selected) td {
29
- background-color: rgba(var(--zn-body));
22
+ tbody tr.table__row--data td {
23
+ height: 48px;
24
+ padding-block: 0;
25
+ overflow: hidden;
30
26
  }
31
27
 
32
28
  tbody tr.table__row--details td {
@@ -38,6 +34,10 @@ table {
38
34
  border-radius: var(--zn-border-radius);
39
35
  border: 1px solid rgb(var(--zn-border-color));
40
36
  overflow: hidden;
37
+
38
+ thead tr th {
39
+ border-top: 0;
40
+ }
41
41
  }
42
42
 
43
43
  thead {
@@ -46,6 +46,7 @@ table {
46
46
  }
47
47
 
48
48
  thead tr th {
49
+ background-color: rgb(var(--zn-table-header-background-color));
49
50
  border-bottom: 1px solid rgb(var(--zn-border-color)) !important;
50
51
  }
51
52
 
@@ -67,32 +68,19 @@ table {
67
68
  border-top: 0 !important;
68
69
  }
69
70
 
70
- thead tr th:first-of-type,
71
- tbody tr td:first-of-type {
72
- padding-left: var(--zn-base-gap, 14px);
73
- }
74
-
75
- thead tr th:last-of-type,
76
- tbody tr td:last-of-type {
77
- padding-right: var(--zn-base-gap, 14px);
78
- }
79
-
80
71
  th, td {
81
- padding: var(--zn-spacing-medium);
72
+ padding: var(--zn-spacing-small) var(--zn-spacing-medium);
82
73
  min-width: 90px;
83
74
  white-space: nowrap;
84
75
 
85
76
  span {
86
77
  white-space: normal;
87
78
  }
88
-
89
- &:first-child {
90
- padding-left: 0;
91
- }
92
79
  }
93
80
 
94
81
  th {
95
- padding-bottom: 0;
82
+ @include wc.text-style(button-label);
83
+ border-top: 1px solid rgb(var(--zn-border-color));
96
84
  border-bottom: 1px solid rgb(var(--zn-border-color));
97
85
  }
98
86
  }
@@ -104,11 +92,6 @@ table {
104
92
 
105
93
  .table { // The container element that holds the table and the filters
106
94
 
107
- tr th {
108
- padding-top: var(--zn-spacing-large);
109
- padding-bottom: var(--zn-spacing-large);
110
- }
111
-
112
95
  tr th, tr td {
113
96
  min-width: 50px;
114
97
 
@@ -140,34 +123,23 @@ table {
140
123
  }
141
124
 
142
125
  &__head {
143
- &:hover {
144
- .table__head__sort {
145
- opacity: 1;
146
- }
147
- }
126
+ text-transform: capitalize;
148
127
 
149
128
  &__sort {
150
- margin-left: var(--zn-spacing-small);
151
- opacity: 0;
129
+ margin: 0;
130
+ padding: 0;
131
+ opacity: 1;
152
132
  display: flex;
153
133
  flex-direction: column;
154
134
  justify-content: center;
155
135
  align-items: center;
156
136
  cursor: pointer;
157
-
158
- &--active {
159
- opacity: 1 !important;
160
- }
161
137
  }
162
138
 
163
139
  &--wide {
164
140
  width: 100%;
165
141
  }
166
142
 
167
- &--last div {
168
- flex-direction: row-reverse !important;
169
- }
170
-
171
143
  &--left div {
172
144
  justify-content: flex-start;
173
145
  }
@@ -198,10 +170,6 @@ table {
198
170
  width: 100%;
199
171
  }
200
172
 
201
- &--last div {
202
- justify-content: flex-end;
203
- }
204
-
205
173
  &--left div {
206
174
  justify-content: flex-start;
207
175
  }
@@ -217,6 +185,7 @@ table {
217
185
  &--actions {
218
186
  width: 25px;
219
187
  min-width: 25px;
188
+ text-align: right;
220
189
  }
221
190
 
222
191
  .caption {
@@ -290,7 +259,7 @@ table {
290
259
  display: flex;
291
260
  flex-direction: row;
292
261
  justify-content: space-between;
293
- padding: var(--zn-spacing-medium) var(--zn-spacing-medium);
262
+ padding: var(--zn-spacing-medium) 0;
294
263
 
295
264
  &__right, &__left {
296
265
  display: flex;
@@ -311,10 +280,6 @@ table {
311
280
  }
312
281
  }
313
282
 
314
- &__pagination-count {
315
-
316
- }
317
-
318
283
  &__pagination-buttons {
319
284
  display: flex;
320
285
  flex-direction: row;
@@ -332,6 +297,19 @@ table {
332
297
  }
333
298
  }
334
299
  }
300
+
301
+ &__pagination-page--active::part(base) {
302
+ background-color: rgb(var(--zn-primary));
303
+ border-color: rgb(var(--zn-primary));
304
+ color: rgb(var(--zn-text-on-primary, 255 255 255));
305
+ }
306
+
307
+ &__pagination-ellipsis {
308
+ display: flex;
309
+ align-items: center;
310
+ padding: 0 var(--zn-spacing-x-small);
311
+ color: rgb(var(--zn-text));
312
+ }
335
313
  }
336
314
 
337
315
  &__details {
@@ -438,10 +416,6 @@ table tbody tr.table__row--selected {
438
416
  border-bottom-right-radius: 0;
439
417
  }
440
418
  }
441
-
442
- &.table__row--odd {
443
- background-color: hsla(from var(--zn-color-purple-200) h s l / 0.8);
444
- }
445
419
  }
446
420
 
447
421
  table:has(tbody tr:first-of-type.table__row--selected) thead tr th {
@@ -354,7 +354,7 @@ export default class ZnIcon extends ZincElement {
354
354
  viewBox="0 0 24 24"
355
355
  fill="none"
356
356
  stroke="currentColor"
357
- stroke-width="2"
357
+ stroke-width="2.1"
358
358
  stroke-linecap="round"
359
359
  stroke-linejoin="round"
360
360
  aria-hidden="true"
@@ -141,7 +141,8 @@ $icon-colors: (
141
141
  }
142
142
 
143
143
  @each $name, $token in $icon-colors {
144
- &--fill-#{$name} {
144
+ $display-name: "" + $name;
145
+ &--fill-#{$display-name} {
145
146
  --icon-fill: rgb(var(#{$token}));
146
147
  }
147
148
  }
@@ -103,6 +103,35 @@ export default class ZnPage extends ZnTabs {
103
103
  this.classList.toggle('alt-pressed', false);
104
104
  };
105
105
 
106
+ // Inject a real chevron icon between breadcrumb links (idempotent: only mutates when needed)
107
+ private handleBreadcrumbSlotChange = (e: Event) => {
108
+ const slot = e.target as HTMLSlotElement;
109
+ const assigned = slot.assignedElements();
110
+ const anchors = assigned.filter(el => el.tagName === 'A');
111
+
112
+ // Remove separators that are no longer between two links
113
+ assigned.forEach(el => {
114
+ if (!el.hasAttribute('data-breadcrumb-separator')) return;
115
+ const prev = el.previousElementSibling;
116
+ const valid = prev?.tagName === 'A' && anchors.indexOf(prev) < anchors.length - 1;
117
+ if (!valid) el.remove();
118
+ });
119
+
120
+ // Ensure each link except the last is followed by a separator icon
121
+ anchors.forEach((anchor, index) => {
122
+ if (index === anchors.length - 1) return;
123
+ const next = anchor.nextElementSibling;
124
+ if (next?.hasAttribute('data-breadcrumb-separator')) return;
125
+
126
+ const icon = document.createElement('zn-icon');
127
+ icon.setAttribute('src', 'arrow-right@lu');
128
+ icon.setAttribute('size', '16');
129
+ icon.setAttribute('slot', 'breadcrumb');
130
+ icon.setAttribute('data-breadcrumb-separator', '');
131
+ anchor.after(icon);
132
+ });
133
+ };
134
+
106
135
  _registerTabs = () => {
107
136
  this.registerPageNavigationTabs();
108
137
  };
@@ -393,7 +422,9 @@ export default class ZnPage extends ZnTabs {
393
422
  <div class="header__left">
394
423
  <span class="header__caption">
395
424
  ${hasBreadcrumb ? html`
396
- <slot name="breadcrumb" class="breadcrumb"></slot>` : null}
425
+ <slot name="breadcrumb" class="breadcrumb"
426
+ @slotchange="${this.handleBreadcrumbSlotChange}"></slot>
427
+ <zn-icon class="breadcrumb__separator" src="arrow-right@lu" size="16"></zn-icon>` : null}
397
428
  <slot name="caption">${this.caption}</slot>
398
429
  </span>
399
430
  <span class="header__description"><slot name="description">${this.summary}</slot></span>
@@ -149,14 +149,15 @@
149
149
  color: rgb(var(--zn-primary));
150
150
  }
151
151
 
152
- &::slotted(a)::after {
153
- content: '>';
154
- margin-left: var(--zn-spacing-2x-small);
152
+ &::slotted([data-breadcrumb-separator]) {
155
153
  color: rgb(var(--zn-text-muted));
156
- font-weight: var(--zn-font-weight-normal);
157
154
  }
158
155
  }
159
156
 
157
+ .breadcrumb__separator {
158
+ color: rgb(var(--zn-text-muted));
159
+ }
160
+
160
161
  slot {
161
162
  display: flex;
162
163
  align-items: center;
@@ -26,7 +26,7 @@
26
26
  }
27
27
 
28
28
  .tooltip__body {
29
- @include wc.text-style("paragraph");
29
+ @include wc.text-style(paragraph);
30
30
 
31
31
  display: block;
32
32
  width: max-content;
@@ -1,4 +1,4 @@
1
- export type ZnAcceptEvent = CustomEvent<{ fid: string; acceptUri: string }>;
1
+ export type ZnAcceptEvent = CustomEvent<{ itemId: string; acceptUri: string }>;
2
2
 
3
3
  declare global {
4
4
  interface GlobalEventHandlersEventMap {
@@ -1,4 +1,4 @@
1
- export type ZnRejectEvent = CustomEvent<{ fid: string; variant: string }>;
1
+ export type ZnRejectEvent = CustomEvent<{ itemId: string; variant: string }>;
2
2
 
3
3
  declare global {
4
4
  interface GlobalEventHandlersEventMap {
package/src/zinc.ts CHANGED
@@ -8,6 +8,7 @@ export { default as Collapsible } from './components/collapsible';
8
8
  export { default as Alert } from './components/alert';
9
9
  export { default as ButtonGroup } from './components/button-group';
10
10
  export { default as ChatMessage } from './components/chat-message';
11
+ export { default as ChatMessageAttachment } from './components/chat-message-attachment';
11
12
  export { default as Chip } from './components/chip';
12
13
  export { default as Well } from './components/well';
13
14
  export { default as CopyButton } from './components/copy-button';