@kubex/zinc 1.0.115 → 1.0.117

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 (102) hide show
  1. package/dist/custom-elements.json +476 -287
  2. package/dist/vscode.html-custom-data.json +52 -52
  3. package/dist/web-types.json +116 -86
  4. package/dist/zn.d.ts +63 -11
  5. package/dist/zn.min.css +1 -1
  6. package/dist/zn.min.js +1096 -1087
  7. package/docs/_includes/default.njk +3 -4
  8. package/docs/assets/styles/docs.css +13 -13
  9. package/docs/pages/components/absolute-container.md +2 -2
  10. package/docs/pages/components/alert.md +5 -5
  11. package/docs/pages/components/audio-select.md +4 -4
  12. package/docs/pages/components/button-group.md +1 -31
  13. package/docs/pages/components/button.md +13 -12
  14. package/docs/pages/components/checkbox.md +4 -4
  15. package/docs/pages/components/chip.md +14 -14
  16. package/docs/pages/components/data-table.md +4 -4
  17. package/docs/pages/components/datepicker.md +5 -5
  18. package/docs/pages/components/dialog.md +2 -2
  19. package/docs/pages/components/file.md +81 -9
  20. package/docs/pages/components/header.md +4 -6
  21. package/docs/pages/components/hover-container.md +1 -1
  22. package/docs/pages/components/icon.md +14 -0
  23. package/docs/pages/components/inline-edit.md +4 -4
  24. package/docs/pages/components/item.md +2 -2
  25. package/docs/pages/components/menu.md +2 -2
  26. package/docs/pages/components/note.md +12 -12
  27. package/docs/pages/components/page.md +3 -3
  28. package/docs/pages/components/pagination.md +6 -6
  29. package/docs/pages/components/pane.md +3 -6
  30. package/docs/pages/components/panel.md +10 -12
  31. package/docs/pages/components/priority-list.md +3 -3
  32. package/docs/pages/components/radio-group.md +4 -4
  33. package/docs/pages/components/radio.md +4 -4
  34. package/docs/pages/components/scroll-container.md +10 -10
  35. package/docs/pages/components/select.md +5 -5
  36. package/docs/pages/components/split-button.md +4 -4
  37. package/docs/pages/components/tabs.md +3 -3
  38. package/docs/pages/components/tile.md +13 -13
  39. package/docs/pages/components/toggle.md +4 -4
  40. package/docs/pages/components/translations.md +5 -5
  41. package/docs/pages/components/vertical-stepper.md +3 -3
  42. package/docs/pages/components/well.md +19 -19
  43. package/docs/pages/getting-started/example-layout.md +16 -16
  44. package/docs/pages/getting-started/example-page.md +1 -3
  45. package/package.json +2 -1
  46. package/scss/_root.scss +87 -60
  47. package/scss/shared/_button.scss +6 -1
  48. package/scss/shared/_form-elements.scss +1 -0
  49. package/scss/shared/_table.scss +1 -1
  50. package/scss/shared/layout.scss +5 -4
  51. package/scss/themes/_dark.scss +4 -4
  52. package/scss/themes/_light.scss +70 -287
  53. package/src/components/bulk-actions/bulk-actions.component.ts +0 -1
  54. package/src/components/button/button.component.ts +40 -10
  55. package/src/components/button/button.scss +67 -103
  56. package/src/components/button-menu/button-menu.component.ts +2 -6
  57. package/src/components/collapsible/collapsible.scss +1 -1
  58. package/src/components/cols/cols.scss +1 -1
  59. package/src/components/content-block/content-block.component.ts +1 -2
  60. package/src/components/data-table/data-table.component.ts +4 -8
  61. package/src/components/data-table/data-table.test.ts +7 -0
  62. package/src/components/data-table-filter/data-table-filter.component.ts +1 -1
  63. package/src/components/data-table-sort/data-table-sort.component.ts +2 -2
  64. package/src/components/dialog/dialog.component.ts +0 -1
  65. package/src/components/editor/modules/dialog/dialog.component.ts +0 -1
  66. package/src/components/editor/modules/dialog/dialog.scss +1 -1
  67. package/src/components/editor/modules/toolbar/toolbar.component.ts +0 -1
  68. package/src/components/expanding-action/expanding-action.component.ts +0 -3
  69. package/src/components/expanding-action/expanding-action.scss +0 -5
  70. package/src/components/file/file.component.ts +158 -17
  71. package/src/components/file/file.scss +122 -29
  72. package/src/components/header/header.component.ts +2 -8
  73. package/src/components/header/header.scss +4 -25
  74. package/src/components/icon/icon.component.ts +80 -1
  75. package/src/components/icon/icon.scss +8 -0
  76. package/src/components/icon/icon.test.ts +24 -0
  77. package/src/components/icon-picker/icon-picker.component.ts +0 -1
  78. package/src/components/inline-edit/inline-edit.component.ts +3 -4
  79. package/src/components/input/input.scss +21 -6
  80. package/src/components/input-group/input-group.scss +2 -1
  81. package/src/components/markdown-editor/markdown-editor.component.ts +1 -5
  82. package/src/components/menu/menu.scss +1 -1
  83. package/src/components/menu-item/menu-item.scss +4 -4
  84. package/src/components/navbar/navbar.component.ts +20 -0
  85. package/src/components/navbar/navbar.scss +31 -17
  86. package/src/components/navbar/navbar.test.ts +72 -0
  87. package/src/components/note/note.component.ts +0 -1
  88. package/src/components/page/page.component.ts +43 -12
  89. package/src/components/page/page.scss +21 -17
  90. package/src/components/page/page.test.ts +18 -1
  91. package/src/components/page-nav/page-nav.scss +6 -6
  92. package/src/components/panel/panel.component.ts +3 -5
  93. package/src/components/panel/panel.scss +3 -3
  94. package/src/components/panel/panel.test.ts +14 -0
  95. package/src/components/query-builder/query-builder.component.ts +0 -1
  96. package/src/components/slideout/slideout.component.ts +0 -1
  97. package/src/components/sp/sp.scss +2 -2
  98. package/src/components/tab/tab.component.ts +2 -0
  99. package/src/components/tabs/tabs.component.ts +1 -1
  100. package/src/components/tile/tile.scss +1 -1
  101. package/src/components/translation-group/translation-group.component.ts +0 -3
  102. package/src/components/translations/translations.component.ts +0 -3
@@ -11,6 +11,7 @@ import {property, query, state} from 'lit/decorators.js';
11
11
  import {repeat} from 'lit/directives/repeat.js';
12
12
  import {watch} from "../../internal/watch";
13
13
  import ZincElement, {type ZincFormControl} from '../../internal/zinc-element';
14
+ import ZnDialog from "../dialog";
14
15
  import type ZnButton from "../button";
15
16
 
16
17
  import styles from './file.scss';
@@ -23,12 +24,11 @@ import styles from './file.scss';
23
24
  *
24
25
  * @dependency zn-button
25
26
  * @dependency zn-icon
27
+ * @dependency zn-dialog
26
28
  *
27
29
  * @slot label - The file control's label. Alternatively, you can use the `label` attribute.
28
30
  * @slot help-text - Text that describes how to use the file control.
29
31
  * Alternatively, you can use the `help-text` attribute.
30
- * @slot droparea-icon - Optional droparea icon to use instead of the default.
31
- * Works best with `<zn-icon>`.
32
32
  * @slot trigger - Optional content to be used as trigger instead of the default content.
33
33
  * Opening the file dialog on click and as well as drag and drop will work for this content.
34
34
  * Following attributes will no longer work: *label*, *droparea*, *help-text*, *size*,
@@ -37,6 +37,7 @@ import styles from './file.scss';
37
37
  *
38
38
  * @event zn-blur - Emitted when the control loses focus.
39
39
  * @event zn-change - Emitted when an alteration to the control's value is committed by the user.
40
+ * @event zn-clear - Emitted when the user confirms clearing the selected file or `src`.
40
41
  * @event zn-error - Emitted when multiple files are selected via drag and drop, without
41
42
  * the `multiple` property being set.
42
43
  * @event zn-focus - Emitted when the control gains focus.
@@ -52,8 +53,12 @@ import styles from './file.scss';
52
53
  * @csspart value - The chosen files or placeholder text for the file input.
53
54
  * @csspart droparea - The element wrapping the drop zone.
54
55
  * @csspart droparea-background - The background of the drop zone.
55
- * @csspart droparea-icon - The container that wraps the icon for the drop zone.
56
- * @csspart droparea-value - The text for the drop zone.
56
+ * @csspart upload - The upload button shown in the droparea when no file is selected.
57
+ * @csspart preview - The image preview rendered in the droparea for previewable files.
58
+ * @csspart filename - The filename label rendered in the droparea for non-previewable files.
59
+ * @csspart clear - The clear button rendered in the droparea when a file is present.
60
+ * @csspart clear-confirm - The confirmation dialog shown before clearing the file.
61
+ * @csspart link - The current link anchor rendered when `show-link` is enabled.
57
62
  * @csspart trigger - The container that wraps the trigger.
58
63
  *
59
64
  * @animation file.iconDrop - The animation to use for the file icon
@@ -65,6 +70,9 @@ import styles from './file.scss';
65
70
  */
66
71
  export default class ZnFile extends ZincElement implements ZincFormControl {
67
72
  static styles: CSSResultGroup = unsafeCSS(styles);
73
+ static dependencies = {
74
+ 'zn-dialog': ZnDialog
75
+ };
68
76
 
69
77
  private readonly formControlController = new FormControlController(this, {
70
78
  assumeInteractionOn: ['zn-change'],
@@ -76,6 +84,7 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
76
84
  private readonly localize = new LocalizeController(this);
77
85
 
78
86
  @state() private userIsDragging = false;
87
+ @state() private fileObjectUrl: string | null = null;
79
88
 
80
89
  @query('.input__control') input: HTMLInputElement;
81
90
 
@@ -87,6 +96,8 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
87
96
 
88
97
  @query('.input__value') inputChosen: HTMLSpanElement;
89
98
 
99
+ @query('.clear-confirm') clearConfirmDialog: HTMLElement & { show: () => void; hide: () => void };
100
+
90
101
  /**
91
102
  * The selected files as a FileList object containing a list of File objects.
92
103
  * The FileList behaves like an array, so you can get the number of selected files
@@ -99,6 +110,7 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
99
110
  set files(v: FileList | null) {
100
111
  if (this.input) {
101
112
  this.input.files = v;
113
+ this.updatePreview();
102
114
  }
103
115
  }
104
116
 
@@ -211,6 +223,26 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
211
223
  /** Suppress the value from being displayed in the file control */
212
224
  @property({attribute: 'hide-value', type: Boolean}) hideValue = false;
213
225
 
226
+ /**
227
+ * URL of an already-uploaded file (e.g., from a CDN) to display as the current value
228
+ * when no file has been selected locally. If the URL points to an image, it is rendered
229
+ * as a preview inside the droparea. Otherwise the URL is shown as a filename.
230
+ */
231
+ @property() src = '';
232
+
233
+ /**
234
+ * When enabled, automatically submit the surrounding form whenever the value changes
235
+ * (file selected, dropped, or cleared). Useful for forms that only contain this control
236
+ * and a CSRF token.
237
+ */
238
+ @property({type: Boolean, attribute: 'trigger-submit'}) triggerSubmit = false;
239
+
240
+ /**
241
+ * When enabled, render the current link (`previewSrc`) as a clickable URL below the control.
242
+ * Useful for showing the existing CDN link alongside the preview.
243
+ */
244
+ @property({type: Boolean, attribute: 'show-link'}) showLink = false;
245
+
214
246
  /** Gets the validity state object */
215
247
  get validity() {
216
248
  return this.input?.validity;
@@ -343,8 +375,13 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
343
375
  e.preventDefault();
344
376
  e.stopPropagation();
345
377
 
378
+ this.updatePreview();
346
379
  this.emit('zn-input');
347
380
  this.emit('zn-change');
381
+
382
+ if (this.triggerSubmit) {
383
+ this.formControlController.submit();
384
+ }
348
385
  }
349
386
 
350
387
  private handleDragOver = (e: DragEvent) => {
@@ -439,6 +476,57 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
439
476
  this.input.dispatchEvent(new Event('change'));
440
477
  }
441
478
 
479
+ /** Open the confirm dialog before clearing. */
480
+ private handleClearClick = (e: Event) => {
481
+ e.preventDefault();
482
+ e.stopPropagation();
483
+ this.clearConfirmDialog?.show();
484
+ }
485
+
486
+ /** Clear the current value after the user confirms. */
487
+ private confirmClear = () => {
488
+ const hadLocalFile = (this.files?.length ?? 0) > 0;
489
+ this.input.value = '';
490
+ this.files = null;
491
+ // If only an external `src` was present, clear it. If a local file was selected on top of
492
+ // an external src, leave the src so the droparea reverts to the originally-supplied preview.
493
+ if (!hadLocalFile) {
494
+ this.src = '';
495
+ }
496
+ this.clearConfirmDialog?.hide();
497
+ this.input.dispatchEvent(new Event('change'));
498
+ this.emit('zn-clear');
499
+ }
500
+
501
+ private updatePreview() {
502
+ if (this.fileObjectUrl) {
503
+ URL.revokeObjectURL(this.fileObjectUrl);
504
+ this.fileObjectUrl = null;
505
+ }
506
+
507
+ const file = this.files?.[0];
508
+ if (file && file.type.startsWith('image/')) {
509
+ this.fileObjectUrl = URL.createObjectURL(file);
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Returns the URL currently shown in the droparea — the locally-selected file's object URL
515
+ * if a file is selected, otherwise the externally supplied `src`. Useful for getting the
516
+ * current CDN link to submit alongside form data.
517
+ */
518
+ get previewSrc(): string {
519
+ return this.fileObjectUrl ?? this.src ?? '';
520
+ }
521
+
522
+ disconnectedCallback() {
523
+ super.disconnectedCallback();
524
+ if (this.fileObjectUrl) {
525
+ URL.revokeObjectURL(this.fileObjectUrl);
526
+ this.fileObjectUrl = null;
527
+ }
528
+ }
529
+
442
530
  private renderFileValueWithDelete(): HTMLTemplateResult {
443
531
  // files as an array
444
532
  const files = Array.from(this.files || []);
@@ -464,7 +552,6 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
464
552
  class="input__delete"
465
553
  color="transparent"
466
554
  icon="close"
467
- size="content"
468
555
  icon-size="18"
469
556
  @click="${this.removeFile}"
470
557
  part="delete"></zn-button>` : ''}
@@ -474,30 +561,75 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
474
561
  }
475
562
 
476
563
  private renderDroparea(): HTMLTemplateResult {
564
+ const files = Array.from(this.files || []);
565
+ const firstFile = files[0];
566
+
567
+ const hasLocalFile = files.length > 0;
568
+ const hasExternalSrc = !hasLocalFile && !!this.src;
569
+ const hasValue = hasLocalFile || hasExternalSrc;
570
+
571
+ const imageSrc = hasLocalFile ? this.fileObjectUrl : (hasExternalSrc ? this.src : null);
572
+ const showImagePreview = !!imageSrc;
573
+ const displayName = hasLocalFile ? firstFile.name : (hasExternalSrc ? this.src : '');
574
+
575
+ let buttonText = this.localize.term('fileButtonText');
576
+ if (this.multiple) buttonText = this.localize.term('fileButtonTextMultiple');
577
+ if (this.webkitdirectory) buttonText = this.localize.term('folderButtonText');
578
+
477
579
  return html`
478
580
  <div
479
- class="droparea"
581
+ class=${classMap({
582
+ 'droparea': true,
583
+ 'droparea--has-preview': showImagePreview,
584
+ })}
480
585
  @click="${this.handleClick}"
481
586
  @keypress="${this.handleClick}"
482
587
  @focus="${this.handleFocus}"
483
588
  @blur="${this.handleBlur}"
484
589
  tabindex="${this.disabled ? '-1' : '0'}"
485
590
  part="droparea">
591
+ ${hasValue ? html`
592
+ <zn-button
593
+ class="droparea__clear"
594
+ icon="close"
595
+ icon-size="18"
596
+ color="default"
597
+ outline
598
+ ?disabled=${this.disabled}
599
+ @click=${this.handleClearClick}
600
+ part="clear"
601
+ style="z-index: 1000;"
602
+ aria-label="${this.localize.term('clearEntry')}"></zn-button>
603
+ ` : ''}
486
604
  <div
487
605
  class="droparea__background"
488
606
  part="droparea-background">
489
- <span part="droparea-icon" class="droparea__icon">
490
- <slot name="droparea-icon">
491
- <zn-icon src="upload_file"></zn-icon>
492
- </slot>
493
- </span>
494
- <p class="droparea__text"
495
- part="droparea-value">
496
- <strong>${this.localize.term(this.webkitdirectory ? 'folderDragDrop' : 'fileDragDrop')}</strong>
497
- ${this.renderFileValueWithDelete()}
498
- </p>
607
+ ${showImagePreview
608
+ ? html`<img
609
+ class="droparea__preview"
610
+ src=${imageSrc!}
611
+ alt=${displayName}
612
+ part="preview">`
613
+ : (hasValue
614
+ ? html`<span class="droparea__filename" part="filename">${displayName}</span>`
615
+ : html`
616
+ <zn-button
617
+ class="droparea__upload"
618
+ icon="cloud_upload"
619
+ icon-size="20"
620
+ color="default"
621
+ outline
622
+ ?disabled=${this.disabled}
623
+ part="upload">
624
+ ${buttonText}
625
+ </zn-button>`)}
499
626
  </div>
500
627
  </div>
628
+ <zn-dialog class="clear-confirm" label="${this.localize.term('clearEntry')}" part="clear-confirm">
629
+ <p class="clear-confirm__text">Are you sure you want to remove this file?</p>
630
+ <zn-button slot="footer" outline dialog-closer>Cancel</zn-button>
631
+ <zn-button slot="footer" color="error" @click=${this.confirmClear}>Remove</zn-button>
632
+ </zn-dialog>
501
633
  `;
502
634
  }
503
635
 
@@ -520,7 +652,6 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
520
652
  ?disabled=${this.disabled}
521
653
  exportparts="base:button__base"
522
654
  part="button"
523
- size="small"
524
655
  outline>
525
656
  ${buttonText}
526
657
  </zn-button>
@@ -567,6 +698,16 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
567
698
  ${this.droparea ? this.renderDroparea() : this.renderButton()}
568
699
  </div>
569
700
 
701
+ ${this.showLink && this.previewSrc ? html`
702
+ <a
703
+ class="form-control__link"
704
+ part="link"
705
+ href=${this.previewSrc}
706
+ target="_blank"
707
+ rel="noopener noreferrer"
708
+ title=${this.previewSrc}>${this.previewSrc}</a>
709
+ ` : ''}
710
+
570
711
  <div
571
712
  aria-hidden="${hasHelpText ? 'false' : 'true'}"
572
713
  class="form-control__help-text"
@@ -99,15 +99,17 @@
99
99
  .droparea {
100
100
  --highlight-color: var(--zn-color-primary-600);
101
101
 
102
- border: 2px dashed var(--zn-input-border-color);
102
+ position: relative;
103
+ border: 1px solid var(--zn-input-border-color);
104
+ border-radius: var(--zn-border-radius-medium);
103
105
  font: var(--zn-font-size-medium);
104
- padding: var(--zn-spacing-x-large) var(--zn-spacing-large);
106
+ min-height: 180px;
105
107
  transition: var(--zn-transition-medium) background,
106
108
  var(--zn-transition-medium) border-color;
107
109
  }
108
110
 
109
111
  .droparea:focus-visible {
110
- border: 2px dashed var(--zn-color-primary-600);
112
+ border-color: var(--zn-color-primary-600);
111
113
  outline: var(--zn-focus-ring);
112
114
  outline-offset: var(--zn-focus-ring-offset);
113
115
  }
@@ -124,52 +126,105 @@
124
126
  .droparea__background {
125
127
  align-items: center;
126
128
  display: flex;
129
+ justify-content: center;
127
130
  gap: var(--zn-spacing-x-small);
128
- padding: var(--zn-spacing-x-small) var(--zn-spacing-medium);
131
+ padding: var(--zn-spacing-large) var(--zn-spacing-medium);
132
+ width: 100%;
133
+ height: 100%;
134
+ min-height: inherit;
135
+ box-sizing: border-box;
129
136
  }
130
137
 
131
- .droparea__icon {
132
- align-items: center;
133
- color: var(--highlight-color);
134
- display: flex;
135
- font-size: var(--zn-spacing-3x-large);
138
+ .droparea__clear {
139
+ position: absolute;
140
+ top: var(--zn-spacing-small);
141
+ right: var(--zn-spacing-small);
142
+ z-index: 1;
136
143
  }
137
144
 
138
- .file-wrapper {
139
- display: flex;
140
- flex-direction: row;
141
- flex-wrap: wrap;
145
+ .droparea__upload {
146
+ text-transform: uppercase;
147
+ letter-spacing: 0.02em;
142
148
  }
143
149
 
144
- .droparea__text {
145
- display: flex;
146
- flex-direction: column;
147
- gap: var(--zn-spacing-3x-small);
148
- margin: 0;
150
+ .droparea--has-preview .droparea__background {
151
+ --zn-droparea-checker-size: 12px;
152
+ --zn-droparea-checker-a: var(--zn-color-neutral-50);
153
+ --zn-droparea-checker-b: var(--zn-color-neutral-100);
154
+
155
+ background-color: var(--zn-droparea-checker-a);
156
+ background-image:
157
+ linear-gradient(45deg, var(--zn-droparea-checker-b) 25%, transparent 25%),
158
+ linear-gradient(-45deg, var(--zn-droparea-checker-b) 25%, transparent 25%),
159
+ linear-gradient(45deg, transparent 75%, var(--zn-droparea-checker-b) 75%),
160
+ linear-gradient(-45deg, transparent 75%, var(--zn-droparea-checker-b) 75%);
161
+ background-size: var(--zn-droparea-checker-size) var(--zn-droparea-checker-size);
162
+ background-position:
163
+ 0 0,
164
+ 0 calc(var(--zn-droparea-checker-size) / 2),
165
+ calc(var(--zn-droparea-checker-size) / 2) calc(var(--zn-droparea-checker-size) / -2),
166
+ calc(var(--zn-droparea-checker-size) / -2) 0;
167
+ border-radius: calc(var(--zn-border-radius-medium) - 1px);
168
+ }
169
+
170
+ .droparea__preview {
171
+ /**
172
+ * SVGs without intrinsic dimensions fall back to a 300x150 default in <img>, which
173
+ * makes them look cramped or invisible at small container widths. Force an explicit
174
+ * box (full container width, fixed height) and use object-fit so loaded images stay
175
+ * inside the box. The text properties below also wrap alt text inside the same box
176
+ * when the image fails to load (e.g. a broken CDN URL), instead of letting it push
177
+ * the container out.
178
+ */
179
+ display: block;
180
+ position: relative;
181
+ z-index: 1;
182
+ width: 100%;
183
+ height: 150px;
184
+ max-width: 100%;
185
+ object-fit: contain;
186
+ overflow: hidden;
187
+ overflow-wrap: anywhere;
188
+ word-break: break-word;
189
+ text-align: center;
190
+ font-size: var(--zn-input-help-text-font-size-medium);
191
+ color: var(--zn-input-color);
192
+ }
193
+
194
+ .droparea__filename {
195
+ color: var(--zn-input-color);
196
+ font-size: var(--zn-input-label-font-size-medium);
197
+ font-weight: var(--zn-font-weight-medium);
198
+ word-break: break-all;
199
+ text-align: center;
200
+ padding: 0 var(--zn-spacing-3x-large);
149
201
  }
150
202
 
151
- .droparea__text strong {
152
- color: var(--highlight-color);
153
- font-weight: var(--zn-font-weight-bold);
203
+ .file-wrapper {
204
+ display: flex;
205
+ flex-direction: row;
206
+ flex-wrap: wrap;
154
207
  }
155
208
 
156
209
  /* Sizes */
157
210
  /* stylelint-disable-next-line no-descending-specificity */
158
211
  .form-control--small .droparea {
159
212
  font: var(--zn-font-size-small);
213
+ min-height: 140px;
160
214
  }
161
215
 
162
- .form-control--small .droparea__icon {
163
- font-size: var(--zn-spacing-2x-large)
216
+ .form-control--small .droparea__preview {
217
+ height: 110px;
164
218
  }
165
219
 
166
220
  /* stylelint-disable-next-line no-descending-specificity */
167
221
  .form-control--large .droparea {
168
222
  font: var(--zn-font-size-large);
223
+ min-height: 220px;
169
224
  }
170
225
 
171
- .form-control--large .droparea__icon {
172
- font-size: var(--zn-spacing-4x-large)
226
+ .form-control--large .droparea__preview {
227
+ height: 190px;
173
228
  }
174
229
 
175
230
  /* Disabled Styles */
@@ -181,20 +236,58 @@
181
236
 
182
237
  :host(:not([disabled])) .form-control--user-dragging .droparea {
183
238
  background: var(--zn-color-primary-50);
184
- border: 2px solid var(--zn-color-primary-600);
239
+ border-color: var(--zn-color-primary-600);
185
240
  cursor: pointer;
186
241
  }
187
242
 
188
243
  :host(:not([disabled])) .droparea:not(:focus-visible):hover {
189
244
  --highlight-color: var(--zn-color-primary-800);
190
245
 
191
- border: 2px dashed var(--zn-color-primary-700);
192
- background-color: var(--zn-color-primary-50);
246
+ border-color: var(--zn-color-primary-700);
193
247
  cursor: pointer;
194
248
  }
195
249
 
250
+ :host(:not([disabled])) .droparea:hover .droparea__upload::part(base),
251
+ :host(:not([disabled])) .droparea__upload:hover::part(base),
252
+ :host(:not([disabled])) .form-control--user-dragging .droparea__upload::part(base) {
253
+ background: var(--zn-color-primary-50);
254
+ border-color: var(--zn-color-primary-700);
255
+ color: var(--zn-color-primary-800);
256
+ }
257
+
258
+ /**
259
+ * Make the icon inside the upload button transparent to pointer events so the cursor is
260
+ * treated as being over the button itself. Without this, hovering the small icon area
261
+ * sometimes fails to trigger the button's :hover state, leaving it un-highlighted.
262
+ */
263
+ .droparea__upload::part(icon) {
264
+ pointer-events: none;
265
+ }
266
+
196
267
  /* Validation */
197
268
  /* stylelint-disable-next-line no-descending-specificity */
198
269
  :host([data-user-invalid]:not([disabled])) .droparea {
199
- border: 2px dashed var(--zn-color-error);
270
+ border-color: var(--zn-color-error);
271
+ }
272
+
273
+ /* Confirm dialog content spacing */
274
+ .clear-confirm__text {
275
+ margin: 0;
276
+ color: var(--zn-input-color);
277
+ }
278
+
279
+ /* Current link display */
280
+ .form-control__link {
281
+ display: inline-block;
282
+ margin-top: var(--zn-spacing-x-small);
283
+ font-size: var(--zn-input-help-text-font-size-medium);
284
+ color: var(--zn-color-primary-700);
285
+ word-break: break-all;
286
+ text-decoration: none;
287
+ max-width: 100%;
288
+ }
289
+
290
+ .form-control__link:hover {
291
+ color: var(--zn-color-primary-800);
292
+ text-decoration: underline;
200
293
  }
@@ -41,8 +41,6 @@ export default class ZnHeader extends ZincElement {
41
41
  @property() caption: string;
42
42
  @property() icon: string;
43
43
 
44
- @property() description: string;
45
-
46
44
  @property({type: Array}) navigation = [];
47
45
 
48
46
  @property({attribute: 'full-width', type: Boolean}) fullWidth: boolean;
@@ -142,7 +140,7 @@ export default class ZnHeader extends ZincElement {
142
140
  ${hasPreviousPath ? html`
143
141
  <a href="${this.previousPath}" class="caption__back"
144
142
  data-target="${this.previousTarget ? this.previousTarget : ''}">
145
- <zn-button size="content" icon="arrow_back" icon-size="24" color="transparent"></zn-button>
143
+ <zn-button icon="arrow_back" icon-size="20" color="transparent"></zn-button>
146
144
  </a>` : null}
147
145
 
148
146
  ${hasDefaultSlot ? html`
@@ -154,15 +152,11 @@ export default class ZnHeader extends ZincElement {
154
152
  <div part="header-left" class="header__left">
155
153
  <span class="header__caption" part="header-caption">
156
154
  ${this.icon ? html`
157
- <zn-icon class="header__icon" src="${this.icon}"></zn-icon>` : null}
155
+ <zn-icon class="header__icon" size=20 src="${this.icon}"></zn-icon>` : null}
158
156
  ${hasBreadcrumb ? html`
159
157
  <slot name="breadcrumb" class="breadcrumb"></slot>` : null}
160
158
  <slot name="caption">${this.caption}</slot>
161
159
  </span>
162
- ${this.description ? html`
163
- <span class="header__description"
164
- part="header-description">${this.description}</span>`
165
- : ''}
166
160
  </div>
167
161
 
168
162
  <div class="header__right">
@@ -8,20 +8,17 @@
8
8
  .header {
9
9
  flex-grow: 1;
10
10
 
11
- // This isn't correct fix this also
12
11
  .caption {
13
- //padding: var(--zn-spacing-small) 0;
14
12
  justify-content: space-between;
15
- gap: var(--zn-spacing-2x-small);
13
+ gap: var(--zn-base-gap);
16
14
  max-width: 100%;
17
- min-height: 58px;
18
15
  }
19
16
 
20
17
  &__caption {
21
18
  font-weight: var(--zn-font-weight-medium);
22
19
  font-size: var(--zn-font-size-large);
23
20
  color: rgba(var(--zn-text-panel-title), 100%);
24
- line-height: 28px;
21
+ line-height: var(--zn-icon-size, 20px);
25
22
  margin: 0;
26
23
  overflow: hidden;
27
24
  white-space: nowrap;
@@ -31,17 +28,6 @@
31
28
  align-items: center;
32
29
  text-wrap: auto;
33
30
  }
34
-
35
- // remove the padding on the nav
36
- &--has-nav {
37
- .caption {
38
- padding-bottom: 0;
39
- }
40
-
41
- .content {
42
- padding-bottom: var(--zn-spacing-x-small);
43
- }
44
- }
45
31
  }
46
32
 
47
33
  .caption__back {
@@ -126,8 +112,7 @@
126
112
  height: fit-content;
127
113
  gap: 10px;
128
114
  margin: 0 auto;
129
- padding-left: var(--zn-spacing-medium);
130
- padding-right: var(--zn-spacing-medium);
115
+ padding: var(--zn-base-gap);
131
116
  }
132
117
 
133
118
  &__left {
@@ -135,7 +120,6 @@
135
120
  justify-content: center;
136
121
  flex-direction: column;
137
122
  gap: 1px;
138
- min-height: 24px;
139
123
  flex-shrink: 1;
140
124
  max-width: 100%;
141
125
  }
@@ -147,12 +131,6 @@
147
131
  min-width: 20px;
148
132
  }
149
133
 
150
- &__description {
151
- display: contents;
152
- font-size: var(--zn-font-size-medium);
153
- line-height: 28px;
154
- }
155
-
156
134
  .navless {
157
135
  min-height: 10px;
158
136
  }
@@ -194,6 +172,7 @@
194
172
  align-items: center;
195
173
  gap: 10px;
196
174
  max-width: 100%;
175
+ line-height: var(--zn-icon-size, 20px);
197
176
 
198
177
  a {
199
178
  display: flex;