@kubex/zinc 1.1.174 → 1.1.176
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 +239 -239
- package/dist/vscode.html-custom-data.json +48 -48
- package/dist/web-types.json +92 -92
- package/dist/zn.d.ts +2 -0
- package/dist/zn.min.js +250 -250
- package/docs/pages/components/vertical-stepper.md +1 -1
- package/package.json +1 -1
- package/src/components/content-block/content-block.component.ts +2 -2
- package/src/components/content-block/content-block.test.ts +14 -0
- package/src/components/content-block/sanitize-html.ts +11 -0
- package/src/components/vertical-stepper/vertical-stepper.scss +4 -0
|
@@ -35,7 +35,7 @@ Use the `active` attribute to highlight the current step in the process. The act
|
|
|
35
35
|
|
|
36
36
|
### With Custom Icons
|
|
37
37
|
|
|
38
|
-
Use the `icon` slot to add custom icons or indicators for each step.
|
|
38
|
+
Use the `icon` slot to add custom icons or indicators for each step. The icon is centred in the step's 32px circle, so keep it at the default 24px size or smaller.
|
|
39
39
|
|
|
40
40
|
```html:preview
|
|
41
41
|
<zn-vertical-stepper caption="Personal Details" description="Enter your name and contact information" first active>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import {classMap} from "lit/directives/class-map.js";
|
|
|
2
2
|
import {deepQuerySelectorAll} from "../../utilities/query";
|
|
3
3
|
import {HasSlotController} from "../../internal/slot";
|
|
4
4
|
import {html, unsafeCSS} from 'lit';
|
|
5
|
-
import {looksLikeHtml, sanitizeHtml} from './sanitize-html';
|
|
5
|
+
import {htmlToText, looksLikeHtml, sanitizeHtml} from './sanitize-html';
|
|
6
6
|
import {MutationController} from '@lit-labs/observers/mutation-controller.js';
|
|
7
7
|
import {property, queryAssignedNodes, queryAsync, state} from 'lit/decorators.js';
|
|
8
8
|
import {unsafeHTML} from 'lit/directives/unsafe-html.js';
|
|
@@ -292,7 +292,7 @@ export default class ContentBlock extends ZincElement {
|
|
|
292
292
|
protected truncateText() {
|
|
293
293
|
const textContent = this.querySelector('[slot="text"]') as HTMLDivElement | null;
|
|
294
294
|
if (!textContent) return '';
|
|
295
|
-
const trimmed = textContent.innerText
|
|
295
|
+
const trimmed = htmlToText(textContent.innerText);
|
|
296
296
|
return trimmed.length > 32 ? trimmed.substring(0, 32) + '...' : trimmed;
|
|
297
297
|
}
|
|
298
298
|
|
|
@@ -63,4 +63,18 @@ describe('<zn-content-block>', () => {
|
|
|
63
63
|
expect(content.textContent).to.not.contain('<br');
|
|
64
64
|
expect(content.querySelectorAll('br').length).to.be.greaterThan(1);
|
|
65
65
|
});
|
|
66
|
+
|
|
67
|
+
it('should decode entities and strip markup in the header preview', async () => {
|
|
68
|
+
const preview = async (body: string) => {
|
|
69
|
+
const el = await fixture<LitElement>(
|
|
70
|
+
`<zn-content-block><div slot="text">${body}</div></zn-content-block>`
|
|
71
|
+
);
|
|
72
|
+
await el.updateComplete;
|
|
73
|
+
return el.shadowRoot!.querySelector('.content-block-header__description')!.textContent;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
expect(await preview('test&nbsp;send')).to.equal('test send');
|
|
77
|
+
expect(await preview('<p>Hello</p><p>there</p>')).to.equal('Hello there');
|
|
78
|
+
expect(await preview('From: Bob <bob@example.com>')).to.equal('From: Bob <bob@example.com>');
|
|
79
|
+
});
|
|
66
80
|
});
|
|
@@ -83,3 +83,14 @@ export function sanitizeHtml(source: string): string {
|
|
|
83
83
|
copyChildren(parsed.body, root, out);
|
|
84
84
|
return root.innerHTML;
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
/** Plain text of a body that may be HTML source or text holding encoded entities like ` `. */
|
|
88
|
+
export function htmlToText(source: string): string {
|
|
89
|
+
// Plain text is escaped so an address like `<bob@example.com>` isn't parsed as a tag
|
|
90
|
+
const markup = looksLikeHtml(source)
|
|
91
|
+
? sanitizeHtml(source)
|
|
92
|
+
: source.replace(/<br\s*\/?>/gi, ' ').replace(/</g, '<');
|
|
93
|
+
const parsed = new DOMParser().parseFromString(markup, 'text/html');
|
|
94
|
+
parsed.body.querySelectorAll('br, p, li').forEach((el) => el.after(' '));
|
|
95
|
+
return (parsed.body.textContent ?? '').replace(/\s+/g, ' ').trim();
|
|
96
|
+
}
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
&__icon {
|
|
19
19
|
width: var(--zn-spacing-large);
|
|
20
20
|
height: var(--zn-spacing-large);
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-shrink: 0;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
21
25
|
background-color: rgb(var(--zn-input-bg));
|
|
22
26
|
border-width: 1px;
|
|
23
27
|
border-radius: 100%;
|