@kubex/zinc 1.0.8 → 1.0.9

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.
@@ -34,6 +34,20 @@ The `auto-click` attribute can be added to a button to make it automatically cli
34
34
  color="transparent"
35
35
  ></zn-button>
36
36
  </zn-button auto-click>
37
+
38
+ <br>
39
+ <br>
40
+
41
+ <zn-button color="success" auto-click auto-click-delay="10000" loading-text="Accepting">
42
+ Test Auto Button
43
+ <zn-style slot="cancel" margin="l">
44
+ <zn-button
45
+ icon="call_end"
46
+ icon-size="18"
47
+ type="button"
48
+ color="error"
49
+ ></zn-button></zn-style>
50
+ </zn-button>
37
51
  ```
38
52
 
39
53
  ### Variants
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubex/zinc",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "A collection of web components for building web applications based off of @shoelace-style/Shoelace",
5
5
  "keywords": [
6
6
  "web components",
@@ -537,5 +537,5 @@
537
537
  --zn-z-index-dropdown: 900;
538
538
  --zn-z-index-toast: 950;
539
539
  --zn-z-index-tooltip: 1000;
540
- --zn-z-index-editor-action: 100000;
540
+ --zn-z-index-editor-action: 1000000;
541
541
  }
@@ -361,26 +361,7 @@ export default class ZnButton extends ZincElement implements ZincFormControl {
361
361
  ${this.content}
362
362
  </slot>
363
363
  ${this.iconPosition === 'right' ? icon : ''}
364
- ${this.loading ? html`
365
- <div class="button--loading-container">
366
- <span
367
- class=${classMap({
368
- 'button--loading-text-bottom': true,
369
- 'button--loading-text-bottom-transparent': this.color === 'transparent',
370
- [`button--loading-text-bottom-${this.loadingTextPosition}`]: !!this.loadingTextPosition,
371
- })}>
372
- ${this.loadingText}<span class="loading-countdown"></span>
373
- </span>
374
- <span
375
- class=${classMap({
376
- 'button--loading-text-top': true,
377
- 'button--loading-text-top-transparent': this.color === 'transparent',
378
- [`button--loading-text-top-${this.loadingTextPosition}`]: !!this.loadingTextPosition,
379
- })}>
380
- ${this.loadingText}<span class="loading-countdown"></span>
381
- </span>
382
- </div>
383
- ` : null}
364
+ ${this._getLoadingContainer()}
384
365
  </${tag}>`;
385
366
 
386
367
  let content = this.autoClick ? html`
@@ -401,4 +382,15 @@ export default class ZnButton extends ZincElement implements ZincFormControl {
401
382
 
402
383
  return content;
403
384
  }
385
+
386
+ private _getLoadingContainer() {
387
+ return html`
388
+ ${this.loading ? html`
389
+ <div class="button--loading-container">
390
+ <span class="button--loading-text">
391
+ ${this.loadingText}<span class="loading-countdown"></span>
392
+ </span>
393
+ </div>
394
+ ` : null}`;
395
+ }
404
396
  }
@@ -312,8 +312,6 @@
312
312
  }
313
313
 
314
314
  .button--loading-bg {
315
- background-color: #e0e0e0;
316
-
317
315
  &-transparent {
318
316
  background-color: transparent;
319
317
  }
@@ -347,7 +345,8 @@
347
345
  pointer-events: none;
348
346
  }
349
347
 
350
- &-text-bottom, &-text-top {
348
+ &-text {
349
+ z-index: 5;
351
350
  width: 100%;
352
351
  height: 100%;
353
352
  display: flex;
@@ -357,9 +356,8 @@
357
356
  font-weight: inherit;
358
357
  user-select: none;
359
358
  position: absolute;
360
- top: 0;
361
- left: 0;
362
359
  pointer-events: none;
360
+ color: inherit;
363
361
 
364
362
  .loading-countdown {
365
363
  margin-left: 3px;
@@ -375,25 +373,6 @@
375
373
  padding-inline-end: 7px;
376
374
  }
377
375
  }
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
376
  }
398
377
 
399
378
  .button--relative-wrapper {
@@ -412,15 +391,6 @@
412
391
  }
413
392
  }
414
393
 
415
- @keyframes loading-text-reveal {
416
- from {
417
- mask-size: 0 100%;
418
- }
419
- to {
420
- mask-size: 100% 100%;
421
- }
422
- }
423
-
424
394
  :host([vertical-align="center"]) {
425
395
  align-self: center;
426
396
  }
@@ -72,3 +72,57 @@ zn-panel:not(.content-block--short) zn-header::part(header-description) {
72
72
  .hidden {
73
73
  display: none;
74
74
  }
75
+
76
+ li[data-list="ordered"] {
77
+ counter-increment: list-0 1;
78
+ }
79
+
80
+ @supports (counter-set:none) {
81
+ li[data-list] {
82
+ counter-set: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0;
83
+ }
84
+ }
85
+
86
+ li[data-list=bullet] > .ql-ui:before {
87
+ content: "•";
88
+ }
89
+
90
+ li[data-list=checked] > .ql-ui:before {
91
+ content: "☑";
92
+ }
93
+
94
+ li[data-list=unchecked] > .ql-ui:before {
95
+ content: "☐";
96
+ }
97
+
98
+ li[data-list="ordered"] > .ql-ui::before {
99
+ content: counter(list-0) ". ";
100
+ }
101
+
102
+ ol {
103
+ padding: 0;
104
+ margin: 0;
105
+ }
106
+
107
+ li[data-list=checked] > .ql-ui, li[data-list=unchecked] > .ql-ui {
108
+ color: #777;
109
+ }
110
+
111
+ .ql-ui {
112
+ position: absolute;
113
+ }
114
+
115
+ li {
116
+ list-style-type: none;
117
+ padding-left: 1em;
118
+ position: relative;
119
+ }
120
+
121
+ li > .ql-ui::before {
122
+ display: inline-block;
123
+ margin-left: -1.5em;
124
+ margin-right: 0.3em;
125
+ text-align: right;
126
+ white-space: nowrap;
127
+ width: 1.2em;
128
+ }
@@ -90,6 +90,8 @@ interface HeaderConfig {
90
90
  default?: boolean;
91
91
  sortable?: boolean;
92
92
  filterable?: boolean;
93
+ hideHeader?: boolean;
94
+ hideColumn?: boolean;
93
95
  }
94
96
 
95
97
  interface DataRequest {
@@ -427,6 +429,13 @@ export default class ZnDataTable extends ZincElement {
427
429
  }
428
430
  });
429
431
 
432
+ // remove empty groups
433
+ Object.keys(groupedRows).forEach((groupKey) => {
434
+ if (groupedRows[groupKey].length === 0) {
435
+ delete groupedRows[groupKey];
436
+ }
437
+ });
438
+
430
439
  // render a table for each group
431
440
  return html`
432
441
  <zn-sp flush>
@@ -449,7 +458,10 @@ export default class ZnDataTable extends ZincElement {
449
458
  }
450
459
 
451
460
  public renderTableData(data: any) {
452
- const filteredHeaders = Object.values(this.headers).filter((header) => {
461
+ const filteredHeaders = Object.values(this.headers).filter((header: HeaderConfig) => {
462
+ if (header.hideHeader || header.hideColumn) {
463
+ return false;
464
+ }
453
465
  return !Object.values(this.hiddenColumns).includes(header.key);
454
466
  });
455
467
 
@@ -608,7 +620,7 @@ export default class ZnDataTable extends ZincElement {
608
620
  || this.hasSlotController.test(ActionSlots.modify.valueOf())
609
621
  || this.hasSlotController.test(ActionSlots.create.valueOf());
610
622
 
611
- if(!hasSlots) {
623
+ if (!hasSlots) {
612
624
  return [];
613
625
  }
614
626
 
@@ -909,6 +921,13 @@ export default class ZnDataTable extends ZincElement {
909
921
  }
910
922
 
911
923
  private renderCellBody(index: number, value: Cell) {
924
+ const filteredHeaders = Object.values(this.headers).filter((header: HeaderConfig) => {
925
+ if (header.hideHeader || header.hideColumn) {
926
+ return false;
927
+ }
928
+ return !Object.values(this.hiddenColumns).includes(header.key);
929
+ });
930
+
912
931
  const headerKeys: string[] = Object.keys(this.headers).filter(
913
932
  (key) => !Object.values(this.hiddenColumns).includes(key)
914
933
  );
@@ -920,7 +939,7 @@ export default class ZnDataTable extends ZincElement {
920
939
  class="${classMap({
921
940
  'table__cell': true,
922
941
  'table__cell--wide': headerKey === this.wideColumn,
923
- 'table__cell--last': headerKey === headerKeys[headerKeys.length - 1],
942
+ 'table__cell--last': index === filteredHeaders.length - 1,
924
943
  })}">
925
944
  <div>${this.renderCell(value)}</div>
926
945
  </td>`;
@@ -65,7 +65,6 @@
65
65
  padding: 0 var(--zn-spacing-medium);
66
66
 
67
67
  img {
68
- max-width: 40%;
69
68
  height: auto;
70
69
  }
71
70
  }
@@ -31,6 +31,7 @@ export default class ZnPanel extends ZincElement {
31
31
  @property() icon: string;
32
32
  @property() description: string;
33
33
  @property({type: Boolean}) tabbed: boolean;
34
+ @property({attribute: 'header-underline', type: Boolean}) underlineHeader: boolean;
34
35
  @property({type: Boolean}) cosmic: boolean;
35
36
  @property({type: Boolean}) flush: boolean;
36
37
  @property({attribute: 'flush-x', type: Boolean}) flushX: boolean;
@@ -94,7 +95,10 @@ export default class ZnPanel extends ZincElement {
94
95
 
95
96
  <div class="panel__inner">
96
97
  ${hasHeader ? html`
97
- <zn-header class="panel__header"
98
+ <zn-header class="${classMap({
99
+ "panel__header": true,
100
+ "panel__header--underline": this.underlineHeader,
101
+ })}"
98
102
  icon="${this.icon}"
99
103
  caption="${this.caption}"
100
104
  description="${ifDefined(this.description)}"
@@ -40,6 +40,10 @@
40
40
  border-bottom: 0;
41
41
  }
42
42
 
43
+ &--underline {
44
+ border-bottom: 1px solid rgb(var(--zn-border-color));
45
+ }
46
+
43
47
  &::part(content) {
44
48
  padding: 0;
45
49
  }
@@ -1,5 +1,6 @@
1
1
  import {classMap} from "lit/directives/class-map.js";
2
2
  import {type CSSResultGroup, html, unsafeCSS} from 'lit';
3
+ import {deepQuerySelectorAll} from "../../utilities/query";
3
4
  import {property, state} from "lit/decorators.js";
4
5
  import {Store} from "../../internal/storage";
5
6
  import {type ZnChangeEvent} from "../../events/zn-change";
@@ -7,7 +8,6 @@ import ZincElement from '../../internal/zinc-element';
7
8
  import type ZnCheckbox from "../checkbox";
8
9
 
9
10
  import styles from './settings-container.scss';
10
- import {deepQuerySelectorAll} from "../../utilities/query";
11
11
 
12
12
  interface SettingsContainerFilter {
13
13
  attribute: string;
@@ -295,7 +295,6 @@ export default class ZnTabs extends ZincElement {
295
295
  let hasActive = false;
296
296
  this._tabs.forEach(tab => {
297
297
 
298
-
299
298
  if (tab.hasAttribute('tab-uri') && this._knownUri.has(tab.getAttribute('tab-uri')!)) {
300
299
  tab.setAttribute('tab', this._knownUri.get(tab.getAttribute('tab-uri')!)!);
301
300
  }
@@ -407,19 +406,38 @@ export default class ZnTabs extends ZincElement {
407
406
  }
408
407
 
409
408
  removeTabAndPanel(tabId: string) {
410
- if (this._panels.has(tabId)) {
411
- this._panels.delete(tabId);
409
+ if (this._current === tabId) {
410
+ this.setActiveTab('', true, false);
412
411
  }
413
412
 
414
413
  for (const tab of this._tabs) {
415
414
  if (tab.getAttribute('tab') === tabId) {
416
- tab.remove();
415
+
416
+ if (tab.hasAttribute('tab-uri')) {
417
+ const tabUri = tab.getAttribute('tab-uri')!;
418
+ if (this._knownUri.has(tabUri)) {
419
+ this._knownUri.delete(tabUri);
420
+ }
421
+ }
422
+
423
+ //tab.remove();
424
+ tab.parentElement?.removeChild(tab)
417
425
  this._tabs.splice(this._tabs.indexOf(tab), 1);
418
426
  }
419
427
  }
420
428
 
421
- if (this._current === tabId) {
422
- this.setActiveTab('', true, false);
429
+ if (this._panels.has(tabId)) {
430
+ const panel = this._panels.get(tabId);
431
+ if (panel instanceof HTMLElement) {
432
+ panel.remove();
433
+ } else if (panel instanceof Array) {
434
+ panel.forEach((item) => {
435
+ if (item instanceof HTMLElement) {
436
+ item.remove();
437
+ }
438
+ })
439
+ }
440
+ this._panels.delete(tabId);
423
441
  }
424
442
  }
425
443
 
@@ -235,12 +235,50 @@ export class FormControlController implements ReactiveController {
235
235
  name.length > 0 &&
236
236
  typeof value !== 'undefined'
237
237
  ) {
238
- if (Array.isArray(value)) {
238
+ const appendPrimitive = (val: string | number | boolean) => {
239
+ event.formData.append(name, val.toString());
240
+ };
241
+ const appendFile = (file: Blob, filename?: string) => {
242
+ // If a filename is provided or it's a File (has name), FormData will use it properly
243
+ const maybeFile = file as unknown as File;
244
+ const fname = filename ?? (typeof maybeFile.name === 'string' ? maybeFile.name : undefined);
245
+ // Overloads: append(name, blob, filename?)
246
+ if (typeof fname === 'string') {
247
+ event.formData.append(name, file, fname);
248
+ } else {
249
+ event.formData.append(name, file);
250
+ }
251
+ };
252
+
253
+ const isFileList = (val: unknown): val is FileList => typeof FileList !== 'undefined' && val instanceof FileList;
254
+ const isBlob = (val: unknown): val is Blob => typeof Blob !== 'undefined' && val instanceof Blob;
255
+
256
+ if (isFileList(value)) {
257
+ // Match native input[type=file] behavior: append each File; if empty, append nothing
258
+ if (value.length > 0) {
259
+ for (let i = 0; i < value.length; i++) {
260
+ const f = value.item(i);
261
+ if (f) appendFile(f, f.name);
262
+ }
263
+ }
264
+ } else if (isBlob(value)) {
265
+ appendFile(value, (value as unknown as File).name);
266
+ } else if (Array.isArray(value)) {
239
267
  (value as unknown[]).forEach(val => {
240
- event.formData.append(name, (val as string | number | boolean).toString());
268
+ if (isBlob(val)) {
269
+ appendFile(val as Blob, (val as unknown as File).name);
270
+ } else if (isFileList(val)) {
271
+ const fl = val as FileList;
272
+ for (let i = 0; i < fl.length; i++) {
273
+ const f = fl.item(i);
274
+ if (f) appendFile(f, f.name);
275
+ }
276
+ } else {
277
+ appendPrimitive(val as string | number | boolean);
278
+ }
241
279
  });
242
280
  } else {
243
- event.formData.append(name, (value as string | number | boolean).toString());
281
+ appendPrimitive(value as string | number | boolean);
244
282
  }
245
283
 
246
284
  this.host.dispatchEvent(new CustomEvent('zn-formdata', {bubbles: true, composed: true}));