@kubex/zinc 1.0.4 → 1.0.6

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 (158) hide show
  1. package/dist/custom-elements.json +1278 -191
  2. package/dist/vscode.html-custom-data.json +93 -16
  3. package/dist/web-types.json +235 -25
  4. package/dist/zn.d.ts +1313 -941
  5. package/dist/zn.min.css +1 -1
  6. package/dist/zn.min.js +2049 -931
  7. package/docs/_includes/default.njk +1 -0
  8. package/docs/assets/scripts/docs.js +4 -5
  9. package/docs/assets/scripts/search.js +0 -9
  10. package/docs/assets/styles/docs.css +3 -3
  11. package/docs/data/data-table.json +79 -0
  12. package/docs/data/products-table.json +36 -0
  13. package/docs/eleventy.config.cjs +3 -0
  14. package/docs/pages/components/data-select.md +10 -0
  15. package/docs/pages/components/data-table.md +84 -45
  16. package/docs/pages/components/dialog.md +1 -1
  17. package/docs/pages/components/editor.md +1 -3
  18. package/docs/pages/components/filter-wrapper.md +20 -0
  19. package/docs/pages/components/icon.md +2 -0
  20. package/docs/pages/components/item.md +2 -2
  21. package/docs/pages/components/menu-item.md +12 -3
  22. package/docs/pages/components/panel.md +17 -0
  23. package/docs/pages/components/progress-tile.md +17 -1
  24. package/docs/pages/components/settings-container.md +137 -0
  25. package/docs/pages/components/textarea.md +1 -1
  26. package/package.json +3 -1
  27. package/scss/_root.scss +26 -0
  28. package/scss/boot.scss +27 -1
  29. package/scss/mixins/index.scss +30 -1
  30. package/scss/shared/_base.scss +1 -1
  31. package/scss/shared/_button.scss +1 -1
  32. package/scss/shared/layout.scss +7 -0
  33. package/scss/themes/_dark.scss +5 -5
  34. package/scss/themes/_light.scss +6 -5
  35. package/scss/variables/index.scss +9 -0
  36. package/src/components/alert/alert.component.ts +1 -1
  37. package/src/components/alert/alert.scss +18 -4
  38. package/src/components/bulk-actions/bulk-actions.component.ts +152 -84
  39. package/src/components/bulk-actions/bulk-actions.scss +2 -0
  40. package/src/components/button/button.component.ts +6 -2
  41. package/src/components/button/button.scss +16 -1
  42. package/src/components/button-menu/button-menu.component.ts +23 -15
  43. package/src/components/button-menu/button-menu.scss +4 -4
  44. package/src/components/chart/chart.component.ts +14 -12
  45. package/src/components/checkbox/checkbox.component.ts +5 -1
  46. package/src/components/checkbox/checkbox.scss +1 -1
  47. package/src/components/chip/chip.component.ts +7 -3
  48. package/src/components/chip/chip.scss +9 -1
  49. package/src/components/collapsible/collapsible.component.ts +48 -2
  50. package/src/components/cols/cols.component.ts +7 -3
  51. package/src/components/cols/cols.scss +22 -14
  52. package/src/components/confirm/confirm.component.ts +1 -2
  53. package/src/components/content-block/content-block.component.ts +104 -14
  54. package/src/components/content-block/content-block.scss +8 -0
  55. package/src/components/data-select/data-select.component.ts +1 -1
  56. package/src/components/data-table/data-table.component.ts +394 -430
  57. package/src/components/data-table/data-table.scss +6 -1
  58. package/src/components/datepicker/datepicker.scss +1 -1
  59. package/src/components/dialog/dialog.component.ts +52 -33
  60. package/src/components/dialog/dialog.scss +15 -1
  61. package/src/components/dropdown/dropdown.component.ts +1 -1
  62. package/src/components/editor/editor.component.ts +196 -158
  63. package/src/components/editor/editor.scss +25 -5
  64. package/src/components/editor/modules/ai/index.ts +281 -0
  65. package/src/components/editor/modules/ai/panel/ai-panel.component.ts +102 -0
  66. package/src/components/editor/modules/ai/panel/ai-panel.scss +83 -0
  67. package/src/components/editor/modules/ai/tooltip/ai-tooltip.component.ts +30 -0
  68. package/src/components/editor/modules/ai/tooltip/ai-tooltip.scss +28 -0
  69. package/src/components/editor/modules/{attachment-module.ts → attachment/attachment.ts} +7 -7
  70. package/src/components/editor/modules/context-menu/context-menu-component.ts +115 -0
  71. package/src/components/editor/modules/context-menu/context-menu.scss +49 -0
  72. package/src/components/editor/modules/context-menu/context-menu.ts +296 -0
  73. package/src/components/editor/modules/context-menu/quick-action/index.ts +12 -0
  74. package/src/components/editor/modules/context-menu/quick-action/quick-action.component.ts +18 -0
  75. package/src/components/editor/modules/date-picker/date-picker.ts +77 -0
  76. package/src/components/editor/modules/dialog/dialog.component.ts +115 -0
  77. package/src/components/editor/modules/dialog/dialog.scss +43 -0
  78. package/src/components/editor/modules/dialog/dialog.ts +46 -0
  79. package/src/components/editor/modules/{drag-drop-module.ts → drag-drop/drag-drop.ts} +6 -6
  80. package/src/components/editor/modules/emoji/emoji.ts +106 -0
  81. package/src/components/editor/modules/emoji/headless/headless-emoji.component.ts +122 -0
  82. package/src/components/editor/modules/emoji/headless/headless-emoji.scss +52 -0
  83. package/src/components/editor/modules/emoji/headless/headless-emoji.ts +223 -0
  84. package/src/components/editor/modules/{image-resize-module/image-resize-module.ts → image-resize/image-resize.ts} +5 -5
  85. package/src/components/editor/modules/{time-tracking-module.ts → time-tracking/time-tracking.ts} +5 -5
  86. package/src/components/editor/modules/toolbar/tool/index.ts +12 -0
  87. package/src/components/editor/modules/toolbar/tool/tool.component.ts +30 -0
  88. package/src/components/editor/modules/toolbar/tool/tool.scss +5 -0
  89. package/src/components/editor/modules/toolbar/toolbar.component.ts +738 -0
  90. package/src/components/editor/modules/toolbar/toolbar.scss +98 -0
  91. package/src/components/editor/modules/toolbar/toolbar.ts +328 -0
  92. package/src/components/expanding-action/expanding-action.component.ts +2 -2
  93. package/src/components/expanding-action/expanding-action.scss +2 -2
  94. package/src/components/filter-wrapper/filter-wrapper.component.ts +91 -0
  95. package/src/components/filter-wrapper/filter-wrapper.scss +11 -0
  96. package/src/components/filter-wrapper/filter-wrapper.test.ts +10 -0
  97. package/src/components/filter-wrapper/index.ts +12 -0
  98. package/src/components/header/header.component.ts +1 -1
  99. package/src/components/header/header.scss +8 -1
  100. package/src/components/hover-container/hover-container.scss +39 -36
  101. package/src/components/icon/icon.component.ts +11 -5
  102. package/src/components/icon/icon.scss +15 -2
  103. package/src/components/inline-edit/inline-edit.component.ts +52 -6
  104. package/src/components/inline-edit/inline-edit.scss +15 -2
  105. package/src/components/input/input.scss +1 -1
  106. package/src/components/item/item.component.ts +30 -19
  107. package/src/components/item/item.scss +57 -23
  108. package/src/components/linked-select/linked-select.component.ts +5 -1
  109. package/src/components/menu/menu.component.ts +1 -0
  110. package/src/components/menu/menu.scss +1 -1
  111. package/src/components/menu-item/menu-item.component.ts +22 -4
  112. package/src/components/menu-item/menu-item.scss +54 -7
  113. package/src/components/navbar/navbar.component.ts +7 -1
  114. package/src/components/navbar/navbar.scss +26 -16
  115. package/src/components/option/option.component.ts +4 -1
  116. package/src/components/option/option.scss +9 -0
  117. package/src/components/page-nav/page-nav.component.ts +2 -2
  118. package/src/components/page-nav/page-nav.scss +4 -4
  119. package/src/components/panel/panel.component.ts +20 -9
  120. package/src/components/panel/panel.scss +5 -1
  121. package/src/components/popup/popup.component.ts +16 -2
  122. package/src/components/progress-tile/progress-tile.component.ts +10 -4
  123. package/src/components/progress-tile/progress-tile.scss +7 -4
  124. package/src/components/query-builder/query-builder.component.ts +1 -1
  125. package/src/components/radio/radio.scss +1 -1
  126. package/src/components/scroll-container/scroll-container.component.ts +56 -9
  127. package/src/components/scroll-container/scroll-container.scss +37 -2
  128. package/src/components/select/select.component.ts +3 -0
  129. package/src/components/select/select.scss +1 -1
  130. package/src/components/settings-container/index.ts +12 -0
  131. package/src/components/settings-container/settings-container.component.ts +226 -0
  132. package/src/components/settings-container/settings-container.scss +99 -0
  133. package/src/components/settings-container/settings-container.test.ts +10 -0
  134. package/src/components/skeleton/skeleton.scss +5 -4
  135. package/src/components/sp/sp.component.ts +2 -0
  136. package/src/components/sp/sp.scss +2 -0
  137. package/src/components/split-button/split-button.component.ts +24 -18
  138. package/src/components/split-pane/split-pane.component.ts +5 -5
  139. package/src/components/stat/stat.component.ts +5 -1
  140. package/src/components/stat/stat.scss +24 -1
  141. package/src/components/style/style.component.ts +25 -1
  142. package/src/components/tabs/tabs.component.ts +12 -1
  143. package/src/components/textarea/textarea.component.ts +3 -1
  144. package/src/components/textarea/textarea.scss +21 -2
  145. package/src/components/vertical-stepper/vertical-stepper.scss +1 -1
  146. package/src/internal/form.ts +3 -1
  147. package/src/internal/slot.ts +29 -3
  148. package/src/utilities/on.ts +7 -8
  149. package/src/utilities/query.ts +5 -1
  150. package/src/wc.scss +7 -0
  151. package/src/zinc.ts +5 -0
  152. package/src/components/editor/modules/dialog-module/dialog-module.component.ts +0 -289
  153. package/src/components/editor/modules/dialog-module/dialog-module.scss +0 -115
  154. package/src/components/editor/modules/dialog-module/dialog-module.ts +0 -99
  155. package/src/components/editor/modules/events/zn-show-canned-response-dialog.ts +0 -15
  156. package/src/components/editor/modules/menu-module/menu-module.component.ts +0 -149
  157. package/src/components/editor/modules/menu-module/menu-module.scss +0 -17
  158. package/src/components/editor/modules/menu-module/menu-module.ts +0 -203
@@ -1,10 +1,11 @@
1
1
  import {classMap} from "lit/directives/class-map.js";
2
2
  import {type CSSResultGroup, html, unsafeCSS} from 'lit';
3
- import {property} from 'lit/decorators.js';
3
+ import {property, state} from 'lit/decorators.js';
4
4
  import {Store} from "../../internal/storage";
5
5
  import ZincElement from '../../internal/zinc-element';
6
6
 
7
7
  import styles from './collapsible.scss';
8
+ import {HasSlotController} from "../../internal/slot";
8
9
 
9
10
  /**
10
11
  * @summary Toggles between showing and hiding content when clicked
@@ -26,6 +27,11 @@ export default class ZnCollapsible extends ZincElement {
26
27
 
27
28
  @property({reflect: true}) label = '';
28
29
 
30
+ @property({type: Boolean, attribute: 'show-number', reflect: true}) showNumber: boolean = false;
31
+
32
+ // what element name to count
33
+ @property({type: String, attribute: 'count-element'}) countElement: string = '*';
34
+
29
35
  @property({type: Boolean, reflect: true}) expanded: boolean = false;
30
36
 
31
37
  @property({attribute: 'default'}) defaultState: 'open' | 'closed';
@@ -38,8 +44,14 @@ export default class ZnCollapsible extends ZincElement {
38
44
 
39
45
  @property({attribute: 'flush', type: Boolean, reflect: true}) flush: boolean = false;
40
46
 
47
+ @state() numberOfItems: number = 0;
48
+
41
49
  protected _store: Store;
42
50
 
51
+ private readonly hasSlotController = new HasSlotController(this, '[default]', 'header', 'caption', 'label');
52
+
53
+ private observer: MutationObserver;
54
+
43
55
  connectedCallback() {
44
56
  super.connectedCallback();
45
57
  this._store = new Store(this.localStorage ? window.localStorage : window.sessionStorage, "zncla:", this.storeTtl);
@@ -51,6 +63,22 @@ export default class ZnCollapsible extends ZincElement {
51
63
  this.expanded = hasPref === "true";
52
64
  }
53
65
  }
66
+
67
+ if (this.showNumber) {
68
+ // add a mutation observer to the default slot to recalculate the number of items when it changes
69
+ const slot = this as HTMLElement;
70
+ this.observer = new MutationObserver(() => {
71
+ this.recalculateNumberOfItems();
72
+ });
73
+ this.observer.observe(slot, {childList: true, subtree: true});
74
+ }
75
+ }
76
+
77
+ disconnectedCallback() {
78
+ super.disconnectedCallback();
79
+ if (this.observer) {
80
+ this.observer.disconnect();
81
+ }
54
82
  }
55
83
 
56
84
  handleCollapse = (e: MouseEvent) => {
@@ -60,7 +88,23 @@ export default class ZnCollapsible extends ZincElement {
60
88
  }
61
89
  }
62
90
 
91
+ public recalculateNumberOfItems = () => {
92
+ const assignedElements = this.hasSlotController.getDefaultSlot()
93
+ .filter(node => node.nodeType === Node.ELEMENT_NODE) as HTMLElement[];
94
+
95
+ // query all direct children that match the countElement tag name
96
+ if (this.countElement === '*') {
97
+ this.numberOfItems = assignedElements.length;
98
+ return;
99
+ }
100
+
101
+ const children = assignedElements.flatMap(el => Array.from(el.querySelectorAll(this.countElement)));
102
+ this.numberOfItems = children.length;
103
+ }
104
+
63
105
  render() {
106
+ this.recalculateNumberOfItems();
107
+
64
108
  return html`
65
109
  <div @click="${() => (!this.expanded ? (this.expanded = true) : '')}">
66
110
  <slot name="header" class="header" @click="${this.handleCollapse}">
@@ -72,6 +116,8 @@ export default class ZnCollapsible extends ZincElement {
72
116
  </div>
73
117
  <div class="header__right">
74
118
  <slot name="label"><p class="label">${this.label}</p></slot>
119
+ ${this.showNumber && !this.expanded ? html`
120
+ <zn-chip size="small" type="primary">${this.numberOfItems}</zn-chip>` : ''}
75
121
  <zn-icon library="material-outlined" src="expand_more" class="expand"></zn-icon>
76
122
  </div>
77
123
  </slot>
@@ -79,7 +125,7 @@ export default class ZnCollapsible extends ZincElement {
79
125
  'content': true,
80
126
  'content--flush': this.flush,
81
127
  })}">
82
- <slot></slot>
128
+ <slot @slotchange="${this.requestUpdate}"></slot>
83
129
  </div>
84
130
  </div>`;
85
131
  }
@@ -25,7 +25,6 @@ import styles from './cols.scss';
25
25
  export default class ZnCols extends ZincElement {
26
26
  static styles: CSSResultGroup = unsafeCSS(styles);
27
27
 
28
-
29
28
  @property({reflect: true, attribute: 'layout'}) layout: string = '';
30
29
 
31
30
  @property({attribute: 'mc', type: Number, reflect: true}) maxColumns: number = 0;
@@ -35,7 +34,11 @@ export default class ZnCols extends ZincElement {
35
34
  @property({type: Boolean}) border: boolean = false;
36
35
 
37
36
  @property({type: Boolean}) pad: boolean;
37
+
38
+ @property({type: Boolean}) divide: boolean = false;
39
+
38
40
  @property({attribute: 'pad-x', type: Boolean}) padX: boolean;
41
+
39
42
  @property({attribute: 'pad-y', type: Boolean}) padY: boolean;
40
43
 
41
44
  render() {
@@ -47,7 +50,7 @@ export default class ZnCols extends ZincElement {
47
50
 
48
51
  this.layout = layout.join(',');
49
52
 
50
- this.maxColumns = Math.min(5, layout.reduce((a, b) => a + b, 0));
53
+ this.maxColumns = layout.reduce((a, b) => a + b, 0);
51
54
 
52
55
  const prefix = 'zn-col-';
53
56
  this.querySelectorAll(':scope > *').forEach((element: HTMLElement, index) => {
@@ -66,7 +69,8 @@ export default class ZnCols extends ZincElement {
66
69
  'cols--pad': this.pad,
67
70
  'cols--pad-x': this.padX,
68
71
  'cols--pad-y': this.padY,
69
- [`cols--layout-${this.layout.replace(',', '')}`]: !!this.layout,
72
+ 'cols--divide': this.divide,
73
+ [`cols--layout-${this.layout.replaceAll(',', '')}`]: !!this.layout,
70
74
  [`cols--mc-${this.maxColumns}`]: !!this.maxColumns,
71
75
  })}">
72
76
  <slot></slot>
@@ -26,20 +26,10 @@
26
26
  }
27
27
  }
28
28
 
29
- &--mc-2 {
30
- --col-width: 40%;
31
- }
32
-
33
- &--mc-3 {
34
- --col-width: 30%;
35
- }
36
-
37
- &--mc-4 {
38
- --col-width: 23%;
39
- }
40
-
41
- &--mc-5 {
42
- --col-width: 18%;
29
+ @for $i from 1 through 12 {
30
+ &--mc-#{$i} {
31
+ --col-width: calc(100% / #{$i + 1});
32
+ }
43
33
  }
44
34
 
45
35
  &--layout-121 {
@@ -54,6 +44,24 @@
54
44
  }
55
45
  }
56
46
 
47
+ &--divide {
48
+ ::slotted(*:not(:last-child)) {
49
+ position: relative;
50
+
51
+ &:after {
52
+ content: "";
53
+ position: absolute;
54
+ display: block;
55
+ width: 1px;
56
+ top: 0;
57
+ height: 100%;
58
+ max-height: 100%;
59
+ right: calc((var(--zn-spacing-small) / 2) * -1);
60
+ background-color: rgb(var(--zn-border-color));
61
+ }
62
+ }
63
+ }
64
+
57
65
  &--no-gap {
58
66
  gap: 0;
59
67
  }
@@ -1,5 +1,6 @@
1
1
  import {classMap} from "lit/directives/class-map.js";
2
2
  import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from 'lit';
3
+ import {deepQuerySelectorAll} from "../../utilities/query";
3
4
  import {HasSlotController} from "../../internal/slot";
4
5
  import {ifDefined} from "lit/directives/if-defined.js";
5
6
  import {property, query} from 'lit/decorators.js';
@@ -7,7 +8,6 @@ import ZincElement from "../../internal/zinc-element";
7
8
  import ZnDialog from "../dialog";
8
9
 
9
10
  import styles from './confirm.scss';
10
- import {deepQuerySelectorAll} from "../../utilities/query";
11
11
 
12
12
  /**
13
13
  * @summary Short summary of the component's intended use.
@@ -85,7 +85,6 @@ export default class ZnConfirm extends ZincElement {
85
85
  connectedCallback() {
86
86
  super.connectedCallback();
87
87
 
88
-
89
88
  if (this.hasSlotController.test('trigger')) {
90
89
  const trigger = this.hasSlotController.getSlot('trigger');
91
90
  trigger?.addEventListener('click', this.show);
@@ -28,6 +28,7 @@ export default class ContentBlock extends ZincElement {
28
28
 
29
29
  @property({type: Boolean, reflect: true}) outbound = false;
30
30
  @property({type: Boolean, reflect: true}) short = false;
31
+ @property({attribute: 'default-display', reflect: true}) defaultDisplay: 'text' | 'html' = 'text';
31
32
 
32
33
  @queryAssignedNodes({slot: 'html', flatten: true}) htmlNodes!: Node[];
33
34
 
@@ -37,25 +38,82 @@ export default class ContentBlock extends ZincElement {
37
38
 
38
39
  private _textRows: TextRow[] = [];
39
40
 
41
+ private _themeChangeObserver?: MutationObserver;
42
+
40
43
  connectedCallback() {
41
44
  super.connectedCallback();
42
45
  this.iframe.then((iframe) => {
43
- if (iframe.contentDocument) {
46
+ const rebuild = () => {
44
47
  const div = this.htmlNodes[0] as HTMLDivElement;
45
- if (div) {
46
- let convertedHtml = div?.innerHTML ?? '';
47
- convertedHtml = convertedHtml.replace(/&nbsp;/g, ' ');
48
- convertedHtml = convertedHtml.replace(/&lt;/g, '<');
49
- convertedHtml = convertedHtml.replace(/&gt;/g, '>');
50
- convertedHtml = convertedHtml.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
51
-
52
- const baseStyles = "<style>body,html{padding: 0; margin: 0; font-size: 13px; font-family: Arial;}</style>";
53
- iframe.srcdoc = baseStyles + convertedHtml;
54
- }
55
- }
48
+ if (!div) return;
49
+
50
+ let convertedHtml = div?.innerHTML ?? '';
51
+ convertedHtml = convertedHtml.replace(/&nbsp;/g, ' ');
52
+ convertedHtml = convertedHtml.replace(/&lt;/g, '<');
53
+ convertedHtml = convertedHtml.replace(/&gt;/g, '>');
54
+ convertedHtml = convertedHtml.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
55
+
56
+ const themeAttr = document.documentElement.getAttribute('t') || document.body.getAttribute('t') || '';
57
+
58
+ // Pull stylesheet links from host to inherit Zinc styles
59
+ const linkTags = Array.from(document.head.querySelectorAll('link[rel="stylesheet"]'))
60
+ .map((element: Element) => {
61
+ const href = (element as HTMLLinkElement).getAttribute('href') || (element as HTMLLinkElement).href || '';
62
+ return href ? `<link rel="stylesheet" href="${href}">` : '';
63
+ })
64
+ .join('');
65
+
66
+ const baseStyles = `<style>
67
+ html, body {
68
+ background-color: var(--zn-panel-background-color);
69
+ container-type: size;
70
+ margin: 0;
71
+ }
72
+
73
+ hr {
74
+ height: 0;
75
+ border: none;
76
+ border-top: 1px solid rgb(var(--zn-border-color));
77
+ }
78
+
79
+ code, kbd, samp, pre, .mono {
80
+ font-family: var(--zn-font-family-mono),sans-serif;
81
+ font-size: 1em;
82
+ }
83
+
84
+ small {
85
+ font-size: 80%;
86
+ }
87
+ </style>`;
88
+
89
+ const head = `${linkTags}${baseStyles}`;
90
+ const htmlAttrs = `${themeAttr ? ` t="${themeAttr}"` : ''}`;
91
+ const baseHref = document.baseURI || window.location.href;
92
+
93
+ iframe.srcdoc = `<!doctype html><html${htmlAttrs}><head><base href="${baseHref}" target="_blank">${head}</head><body>${convertedHtml}</body></html>`;
94
+ };
95
+
96
+ rebuild();
97
+
98
+ // Observe theme changes on both attribute and theme classes on html and body
99
+ this._themeChangeObserver = new MutationObserver(() => rebuild());
100
+ this._themeChangeObserver.observe(document.documentElement, {attributes: true, attributeFilter: ['t', 'class']});
101
+ this._themeChangeObserver.observe(document.body, {attributes: true, attributeFilter: ['t', 'class']});
102
+
103
+ const doc = iframe.contentDocument;
104
+ if (!doc) return;
105
+
106
+ iframe.style.height = (75 + doc.body.scrollHeight) + 'px';
107
+ iframe.style.width = '100%';
108
+ iframe.style.border = '0';
56
109
  });
57
110
  }
58
111
 
112
+ disconnectedCallback() {
113
+ super.disconnectedCallback();
114
+ this._themeChangeObserver?.disconnect();
115
+ }
116
+
59
117
  private _collapseContent(e: Event) {
60
118
  const target = e.target as HTMLElement;
61
119
  const headerClick = target.classList.contains('content-block-header') ||
@@ -106,6 +164,7 @@ export default class ContentBlock extends ZincElement {
106
164
  const hasTextSlot = this.hasSlotController.test('text');
107
165
  const hasHtmlSlot = this.hasSlotController.test('html');
108
166
  const showActions = hasTextSlot && hasHtmlSlot;
167
+ const initialShowHtml = hasHtmlSlot && (!hasTextSlot || this.defaultDisplay === 'html');
109
168
 
110
169
  return html`
111
170
  <zn-panel flush tabbed class="${classMap({
@@ -143,10 +202,10 @@ export default class ContentBlock extends ZincElement {
143
202
  </zn-header>
144
203
 
145
204
  <zn-sp no-gap>
146
- <iframe class="hidden" title="Content block HTML preview"></iframe>
205
+ <iframe class="${classMap({'hidden': !initialShowHtml})}" title="Content block HTML preview"></iframe>
147
206
  <slot class="html-content" name="html" style="display: none;"></slot>
148
207
  <slot name="text" style="display: none;"></slot>
149
- <div class="text-content">
208
+ <div class="${classMap({'text-content': true, 'hidden': initialShowHtml})}">
150
209
  ${text.map((section) => html`
151
210
  ${section.type === 'reply' ? html`
152
211
  <div class="toggle-reply" @click="${this.showReply}">...</div>` : ''}
@@ -196,6 +255,7 @@ export default class ContentBlock extends ZincElement {
196
255
  if (row.startsWith('Sent from')) type = 'reply';
197
256
  if (row.trim() === '' && previousType === 'reply') type = 'reply';
198
257
  if (type === 'reply' && row.startsWith('>')) row = row.substring(1).trim();
258
+ row = this.transformLineForImages(row);
199
259
 
200
260
  if (previousType === type) {
201
261
  if (textRows.length === 0) {
@@ -215,6 +275,36 @@ export default class ContentBlock extends ZincElement {
215
275
  return this._textRows;
216
276
  }
217
277
 
278
+ private transformLineForImages(line: string): string {
279
+ let out = line;
280
+
281
+ // Replace Markdown image syntax ![alt](url) for http(s)
282
+ const mdHttpImg = /!\[([^\]]*)\]\((https?:\/\/[^\s)]+?\.(?:png|jpe?g|gif|webp|bmp|svg))\)/gi;
283
+ out = out.replace(mdHttpImg, (_match, alt, url) => {
284
+ return `<img src="${url}" alt="${alt || 'image'}" loading="lazy" style="max-width:100%;max-height:500px;">`;
285
+ });
286
+
287
+ // Replace Markdown image syntax with data URI (base64)
288
+ const mdDataImg = /!\[([^\]]*)\]\((data:image\/[a-zA-Z0-9.+-]+;base64,[A-Za-z0-9+/=]+)\)/gi;
289
+ out = out.replace(mdDataImg, (_match, alt, url) => {
290
+ return `<img src="${url}" alt="${alt || 'image'}" loading="lazy" style="max-width:100%;max-height:500px;">`;
291
+ });
292
+
293
+ // Replace bare http(s) image URLs with <img>
294
+ const httpImg = /(https?:\/\/[^\s]+?\.(?:png|jpe?g|gif|webp|bmp|svg))(?!\S)/gi;
295
+ out = out.replace(httpImg, (_m, url) => {
296
+ return `<img src="${url}" alt="image" loading="lazy" style="max-width:100%;max-height:500px;">`;
297
+ });
298
+
299
+ // Replace bare data URI images with <img>
300
+ const dataImg = /(data:image\/[a-zA-Z0-9.+-]+;base64,[A-Za-z0-9+/=]+)(?!\S)/gi;
301
+ out = out.replace(dataImg, (_m, url) => {
302
+ return `<img src="${url}" alt="image" loading="lazy" style="max-width:100%;max-height:500px;">`;
303
+ });
304
+
305
+ return out;
306
+ }
307
+
218
308
  showReply(e: MouseEvent) {
219
309
  const target = e.target as HTMLElement;
220
310
  const nextElement = target.nextElementSibling;
@@ -1,3 +1,5 @@
1
+ @use "../../wc";
2
+
1
3
  :host {
2
4
  text-rendering: optimizeLegibility;
3
5
  -webkit-font-smoothing: antialiased;
@@ -45,6 +47,12 @@ zn-panel.content-block--short::part(mid) {
45
47
  display: none;
46
48
  }
47
49
 
50
+ zn-panel.content-block--short zn-header::part(header-description) {
51
+ @include wc.container-query(null, ph) {
52
+ display: none;
53
+ }
54
+ }
55
+
48
56
  zn-panel:not(.content-block--short) zn-header::part(header-description) {
49
57
  display: none;
50
58
  }
@@ -186,7 +186,7 @@ export default class ZnDataSelect extends ZincElement implements ZincFormControl
186
186
  @blur=${this.blur}
187
187
  value="${this.value}"
188
188
  placeholder="Choose a ${localProvider.getName}"
189
- exportparts="combobox,expand-icon,form-control-help-text,form-control-input">
189
+ exportparts="combobox,expand-icon,form-control-help-text,form-control-input,display-input">
190
190
  ${this.iconPosition !== 'none' ? html`
191
191
  <div id="select__prefix" slot="prefix" class="select__prefix"></div>` : ''}
192
192
  ${data.map((item: DataProviderOption) => html`