@momentum-design/components 0.140.0 → 0.141.0
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/browser/index.js +424 -424
- package/dist/browser/index.js.map +4 -4
- package/dist/components/brandvisual/brandvisual.component.d.ts +49 -1
- package/dist/components/brandvisual/brandvisual.component.js +154 -19
- package/dist/components/brandvisualprovider/brandvisualprovider.component.d.ts +97 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.component.js +105 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.constants.d.ts +7 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.constants.js +10 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.context.d.ts +12 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.context.js +7 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.types.d.ts +3 -0
- package/dist/components/brandvisualprovider/brandvisualprovider.types.js +1 -0
- package/dist/components/brandvisualprovider/index.d.ts +7 -0
- package/dist/components/brandvisualprovider/index.js +4 -0
- package/dist/components/icon/icon.component.js +3 -2
- package/dist/components/illustration/illustration.component.js +3 -2
- package/dist/custom-elements.json +252 -7
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/react/brandvisualprovider/index.d.ts +24 -0
- package/dist/react/brandvisualprovider/index.js +17 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/utils/asset-fetch/index.d.ts +42 -0
- package/dist/utils/asset-fetch/index.js +101 -0
- package/package.json +1 -1
- package/dist/components/icon/icon.utils.d.ts +0 -32
- package/dist/components/icon/icon.utils.js +0 -91
- package/dist/components/illustration/illustration.utils.d.ts +0 -32
- package/dist/components/illustration/illustration.utils.js +0 -91
|
@@ -34,14 +34,62 @@ declare class Brandvisual extends Component {
|
|
|
34
34
|
* This will only be set if the brandvisual is an image (png).
|
|
35
35
|
*/
|
|
36
36
|
altText?: string;
|
|
37
|
+
private readonly brandVisualProviderContext;
|
|
38
|
+
private abortController?;
|
|
39
|
+
constructor();
|
|
40
|
+
/**
|
|
41
|
+
* Resolves the brandvisual, either over HTTP through a `BrandVisualProvider` or through a
|
|
42
|
+
* dynamic import of the lit template shipped in the `@momentum-design/brand-visuals` package.
|
|
43
|
+
*
|
|
44
|
+
* The dynamic import is the fallback for every case that is not a fully configured custom set:
|
|
45
|
+
* no provider at all, the momentum set, or a custom set that is missing a url or file extension.
|
|
46
|
+
* Keeping it reachable without a provider is what makes this backwards compatible - a bare
|
|
47
|
+
* `<mdc-brandvisual name="…">` behaves exactly as it did before the provider existed.
|
|
48
|
+
*/
|
|
37
49
|
private getBrandVisualData;
|
|
50
|
+
/**
|
|
51
|
+
* Fetches a vector brandvisual over HTTP and inlines it.
|
|
52
|
+
*
|
|
53
|
+
* This method uses abortController.signal to cancel the fetch request when the component is
|
|
54
|
+
* disconnected or updated. If the request is aborted after the fetch() call has been fulfilled
|
|
55
|
+
* but before the response body has been read, then attempting to read the response body will
|
|
56
|
+
* reject with an AbortError exception.
|
|
57
|
+
*/
|
|
58
|
+
private fetchBrandVisual;
|
|
59
|
+
/**
|
|
60
|
+
* Points an `img` at the raster brandvisual and resolves once the browser has loaded it.
|
|
61
|
+
*
|
|
62
|
+
* There is nothing to fetch here - assigning `src` starts the load even while the element is
|
|
63
|
+
* detached - but we still wait for it so that `load` and `error` keep meaning the same thing
|
|
64
|
+
* they do on the other two branches.
|
|
65
|
+
*/
|
|
66
|
+
private loadBrandVisualImage;
|
|
67
|
+
/**
|
|
68
|
+
* Parse the fetched brandvisual string to an html element and set the attributes the
|
|
69
|
+
* packaged lit templates would otherwise carry.
|
|
70
|
+
*
|
|
71
|
+
* @param brandVisualData - The brandvisual string to be parsed
|
|
72
|
+
* @returns brandVisualElement
|
|
73
|
+
*/
|
|
74
|
+
private prepareBrandVisualElement;
|
|
38
75
|
updated(changedProperties: Map<string, any>): void;
|
|
76
|
+
disconnectedCallback(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Labels the brandvisual with the alt text, if it has anything to label.
|
|
79
|
+
*
|
|
80
|
+
* The dynamic import hands back a lit `TemplateResult`, whose markup has to be parsed before an
|
|
81
|
+
* `img` can be found in it, while both provider branches already produce an `Element` - so the
|
|
82
|
+
* two need different treatment. Only raster visuals have an `img` to label; vector ones are
|
|
83
|
+
* `aria-hidden` by design and are returned untouched.
|
|
84
|
+
*/
|
|
85
|
+
private applyAltText;
|
|
39
86
|
private injectTemplateAttributes;
|
|
40
87
|
private injectHtmlAttributes;
|
|
41
88
|
/**
|
|
42
89
|
* Sets the brandVisualData state to the fetched brandvisual.
|
|
43
90
|
* Dispatches a 'load' event on the component once the brandvisual has been successfully loaded.
|
|
44
|
-
* @param brandVisualHtml - The brandvisual
|
|
91
|
+
* @param brandVisualHtml - The brandvisual which has been resolved, either as the lit template
|
|
92
|
+
* from the dynamic import or as an element built from the provider url.
|
|
45
93
|
*/
|
|
46
94
|
private handleBrandVisualLoadedSuccess;
|
|
47
95
|
/**
|
|
@@ -10,6 +10,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { html } from 'lit';
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
12
12
|
import { Component } from '../../models';
|
|
13
|
+
import providerUtils from '../../utils/provider';
|
|
14
|
+
import { assetFetch } from '../../utils/asset-fetch';
|
|
15
|
+
import BrandVisualProvider from '../brandvisualprovider/brandvisualprovider.component';
|
|
13
16
|
import styles from './brandvisual.styles';
|
|
14
17
|
/**
|
|
15
18
|
* @tagname mdc-brandvisual
|
|
@@ -21,61 +24,189 @@ import styles from './brandvisual.styles';
|
|
|
21
24
|
* @csspart brandvisualImage - Set styles for the brandvisual image container
|
|
22
25
|
*/
|
|
23
26
|
class Brandvisual extends Component {
|
|
27
|
+
constructor() {
|
|
28
|
+
super();
|
|
29
|
+
this.brandVisualProviderContext = providerUtils.consume({
|
|
30
|
+
host: this,
|
|
31
|
+
context: BrandVisualProvider.Context,
|
|
32
|
+
});
|
|
33
|
+
this.abortController = new AbortController(); // Initialize AbortController
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolves the brandvisual, either over HTTP through a `BrandVisualProvider` or through a
|
|
37
|
+
* dynamic import of the lit template shipped in the `@momentum-design/brand-visuals` package.
|
|
38
|
+
*
|
|
39
|
+
* The dynamic import is the fallback for every case that is not a fully configured custom set:
|
|
40
|
+
* no provider at all, the momentum set, or a custom set that is missing a url or file extension.
|
|
41
|
+
* Keeping it reachable without a provider is what makes this backwards compatible - a bare
|
|
42
|
+
* `<mdc-brandvisual name="…">` behaves exactly as it did before the provider existed.
|
|
43
|
+
*/
|
|
24
44
|
async getBrandVisualData() {
|
|
45
|
+
if (!this.name) {
|
|
46
|
+
const nameError = new Error('No brandvisual name provided.');
|
|
47
|
+
this.handleBrandVisualLoadedFailure(nameError);
|
|
48
|
+
return Promise.reject(nameError);
|
|
49
|
+
}
|
|
50
|
+
const providerContext = this.brandVisualProviderContext.value;
|
|
51
|
+
if ((providerContext === null || providerContext === void 0 ? void 0 : providerContext.brandVisualSet) === 'custom-brand-visuals') {
|
|
52
|
+
const { url, fileExtension, cacheName, cacheStrategy } = providerContext;
|
|
53
|
+
if (url && fileExtension) {
|
|
54
|
+
// raster visuals are handed to the browser as an <img src>, vector ones are fetched
|
|
55
|
+
// and inlined so they can be styled through ::part(brandvisual)
|
|
56
|
+
return fileExtension === 'png'
|
|
57
|
+
? this.loadBrandVisualImage(url, fileExtension)
|
|
58
|
+
: this.fetchBrandVisual({ url, fileExtension, cacheName, cacheStrategy });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// dynamic import of the lit template from the momentum brand-visuals package
|
|
62
|
+
return import(`@momentum-design/brand-visuals/dist/ts/${this.name}.ts`)
|
|
63
|
+
.then(module => {
|
|
64
|
+
this.handleBrandVisualLoadedSuccess(module.default());
|
|
65
|
+
})
|
|
66
|
+
.catch(error => {
|
|
67
|
+
this.handleBrandVisualLoadedFailure(error);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetches a vector brandvisual over HTTP and inlines it.
|
|
72
|
+
*
|
|
73
|
+
* This method uses abortController.signal to cancel the fetch request when the component is
|
|
74
|
+
* disconnected or updated. If the request is aborted after the fetch() call has been fulfilled
|
|
75
|
+
* but before the response body has been read, then attempting to read the response body will
|
|
76
|
+
* reject with an AbortError exception.
|
|
77
|
+
*/
|
|
78
|
+
async fetchBrandVisual({ url, fileExtension, cacheName, cacheStrategy, }) {
|
|
79
|
+
// function to abort the fetch request and create a new signal
|
|
80
|
+
// (directly passing the abortcontroller to the fetch request per reference
|
|
81
|
+
// will not work due to JS call-by-sharing behavior)
|
|
82
|
+
const renewSignal = () => {
|
|
83
|
+
var _a;
|
|
84
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
85
|
+
this.abortController = new AbortController();
|
|
86
|
+
return this.abortController.signal;
|
|
87
|
+
};
|
|
88
|
+
return assetFetch({
|
|
89
|
+
url,
|
|
90
|
+
name: this.name,
|
|
91
|
+
fileExtension,
|
|
92
|
+
cacheName,
|
|
93
|
+
cacheStrategy,
|
|
94
|
+
renewSignal,
|
|
95
|
+
assetType: 'brand visual',
|
|
96
|
+
})
|
|
97
|
+
.then(brandVisualData => {
|
|
98
|
+
this.handleBrandVisualLoadedSuccess(this.prepareBrandVisualElement(brandVisualData));
|
|
99
|
+
})
|
|
100
|
+
.catch(error => {
|
|
101
|
+
this.handleBrandVisualLoadedFailure(error);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Points an `img` at the raster brandvisual and resolves once the browser has loaded it.
|
|
106
|
+
*
|
|
107
|
+
* There is nothing to fetch here - assigning `src` starts the load even while the element is
|
|
108
|
+
* detached - but we still wait for it so that `load` and `error` keep meaning the same thing
|
|
109
|
+
* they do on the other two branches.
|
|
110
|
+
*/
|
|
111
|
+
async loadBrandVisualImage(url, fileExtension) {
|
|
112
|
+
const image = document.createElement('img');
|
|
113
|
+
image.setAttribute('part', 'brandvisualImage');
|
|
114
|
+
image.setAttribute('data-name', this.name);
|
|
115
|
+
return new Promise(resolve => {
|
|
116
|
+
image.onload = () => {
|
|
117
|
+
this.handleBrandVisualLoadedSuccess(image);
|
|
118
|
+
resolve();
|
|
119
|
+
};
|
|
120
|
+
image.onerror = () => {
|
|
121
|
+
this.handleBrandVisualLoadedFailure(new Error('There was a problem while fetching the brand visual!'));
|
|
122
|
+
resolve();
|
|
123
|
+
};
|
|
124
|
+
image.src = `${url}/${this.name}.${fileExtension}`;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parse the fetched brandvisual string to an html element and set the attributes the
|
|
129
|
+
* packaged lit templates would otherwise carry.
|
|
130
|
+
*
|
|
131
|
+
* @param brandVisualData - The brandvisual string to be parsed
|
|
132
|
+
* @returns brandVisualElement
|
|
133
|
+
*/
|
|
134
|
+
prepareBrandVisualElement(brandVisualData) {
|
|
135
|
+
const brandVisualElement = new DOMParser().parseFromString(brandVisualData, 'text/html').body.children[0];
|
|
25
136
|
if (this.name) {
|
|
26
|
-
|
|
27
|
-
return import(`@momentum-design/brand-visuals/dist/ts/${this.name}.ts`)
|
|
28
|
-
.then(module => {
|
|
29
|
-
this.handleBrandVisualLoadedSuccess(module.default());
|
|
30
|
-
})
|
|
31
|
-
.catch(error => {
|
|
32
|
-
this.handleBrandVisualLoadedFailure(error);
|
|
33
|
-
});
|
|
137
|
+
brandVisualElement.setAttribute('data-name', this.name);
|
|
34
138
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
139
|
+
brandVisualElement.setAttribute('part', 'brandvisual');
|
|
140
|
+
// set aria-hidden=true for SVG to avoid screen readers
|
|
141
|
+
brandVisualElement.setAttribute('aria-hidden', 'true');
|
|
142
|
+
return brandVisualElement;
|
|
38
143
|
}
|
|
39
144
|
updated(changedProperties) {
|
|
40
145
|
super.updated(changedProperties);
|
|
41
146
|
if (changedProperties.has('name')) {
|
|
42
147
|
// import brandVisual data if name changes:
|
|
43
148
|
this.getBrandVisualData().catch(err => {
|
|
44
|
-
if (this.onerror) {
|
|
149
|
+
if (err.name !== 'AbortError' && this.onerror) {
|
|
45
150
|
this.onerror(err);
|
|
46
151
|
}
|
|
47
152
|
});
|
|
48
153
|
}
|
|
49
154
|
if (changedProperties.has('altText')) {
|
|
50
155
|
if (this.brandVisualData) {
|
|
51
|
-
this.brandVisualData = this.
|
|
156
|
+
this.brandVisualData = this.applyAltText(this.brandVisualData);
|
|
52
157
|
}
|
|
53
158
|
}
|
|
54
159
|
}
|
|
160
|
+
disconnectedCallback() {
|
|
161
|
+
var _a;
|
|
162
|
+
super.disconnectedCallback();
|
|
163
|
+
// abort the fetch request when the component is disconnected
|
|
164
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
165
|
+
this.abortController = undefined; // reset the abort controller
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Labels the brandvisual with the alt text, if it has anything to label.
|
|
169
|
+
*
|
|
170
|
+
* The dynamic import hands back a lit `TemplateResult`, whose markup has to be parsed before an
|
|
171
|
+
* `img` can be found in it, while both provider branches already produce an `Element` - so the
|
|
172
|
+
* two need different treatment. Only raster visuals have an `img` to label; vector ones are
|
|
173
|
+
* `aria-hidden` by design and are returned untouched.
|
|
174
|
+
*/
|
|
175
|
+
applyAltText(brandVisual) {
|
|
176
|
+
if (brandVisual instanceof Element) {
|
|
177
|
+
return brandVisual.tagName === 'IMG' ? this.injectHtmlAttributes(brandVisual, { alt: this.altText }) : brandVisual;
|
|
178
|
+
}
|
|
179
|
+
return this.injectTemplateAttributes(brandVisual, 'img', { alt: this.altText });
|
|
180
|
+
}
|
|
55
181
|
injectTemplateAttributes(litTemplate, tag, props) {
|
|
56
182
|
const parser = new DOMParser();
|
|
57
183
|
const doc = parser.parseFromString(litTemplate.strings[0], 'text/html');
|
|
58
184
|
const element = doc.querySelector(tag);
|
|
59
185
|
if (element) {
|
|
60
|
-
|
|
61
|
-
element.setAttribute(key, value);
|
|
62
|
-
});
|
|
186
|
+
this.injectHtmlAttributes(element, props);
|
|
63
187
|
}
|
|
64
188
|
return element || litTemplate;
|
|
65
189
|
}
|
|
66
190
|
injectHtmlAttributes(html, props) {
|
|
67
191
|
Object.entries(props).forEach(([key, value]) => {
|
|
68
|
-
|
|
192
|
+
// an unset alt-text must not end up rendered as alt="undefined"
|
|
193
|
+
if (value === undefined) {
|
|
194
|
+
html.removeAttribute(key);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
html.setAttribute(key, value);
|
|
198
|
+
}
|
|
69
199
|
});
|
|
70
200
|
return html;
|
|
71
201
|
}
|
|
72
202
|
/**
|
|
73
203
|
* Sets the brandVisualData state to the fetched brandvisual.
|
|
74
204
|
* Dispatches a 'load' event on the component once the brandvisual has been successfully loaded.
|
|
75
|
-
* @param brandVisualHtml - The brandvisual
|
|
205
|
+
* @param brandVisualHtml - The brandvisual which has been resolved, either as the lit template
|
|
206
|
+
* from the dynamic import or as an element built from the provider url.
|
|
76
207
|
*/
|
|
77
208
|
handleBrandVisualLoadedSuccess(brandVisualHtml) {
|
|
78
|
-
this.brandVisualData = this.
|
|
209
|
+
this.brandVisualData = this.applyAltText(brandVisualHtml);
|
|
79
210
|
// when brandvisual is imported successfully, trigger brandvisual load event.
|
|
80
211
|
const loadEvent = new Event('load', {
|
|
81
212
|
bubbles: true,
|
|
@@ -113,4 +244,8 @@ __decorate([
|
|
|
113
244
|
property({ type: String, reflect: true, attribute: 'alt-text' }),
|
|
114
245
|
__metadata("design:type", String)
|
|
115
246
|
], Brandvisual.prototype, "altText", void 0);
|
|
247
|
+
__decorate([
|
|
248
|
+
state(),
|
|
249
|
+
__metadata("design:type", AbortController)
|
|
250
|
+
], Brandvisual.prototype, "abortController", void 0);
|
|
116
251
|
export default Brandvisual;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Provider } from '../../models';
|
|
2
|
+
import BrandVisualProviderContext from './brandvisualprovider.context';
|
|
3
|
+
import type { BrandVisualSet, CacheStrategy } from './brandvisualprovider.types';
|
|
4
|
+
/**
|
|
5
|
+
* The brandvisualprovider is the context provider for `mdc-brandvisual`. It lets an application configure where brand visuals come from and how they are cached in one place, so every nested brand visual stays consistent without repeating that setup at each usage.
|
|
6
|
+
*
|
|
7
|
+
* Without a provider, `mdc-brandvisual` resolves its asset through a dynamic import of the lit template shipped in `@momentum-design/brand-visuals`. That import is not statically analysable, so bundlers have to account for every asset in the package. Pointing the provider at a URL replaces that import with an HTTP fetch, which lets an application serve the brand visual set itself and keep it out of the bundle entirely.
|
|
8
|
+
*
|
|
9
|
+
* **When to use**
|
|
10
|
+
*
|
|
11
|
+
* - Use `mdc-brandvisualprovider` to configure the brand visual source once for every nested `mdc-brandvisual` in a subtree.
|
|
12
|
+
* - Use `mdc-brandvisualprovider` with `brand-visual-set="custom-brand-visuals"` when brand visuals should be served over HTTP rather than bundled — for example in a host framework that cannot afford to bundle the full asset set.
|
|
13
|
+
* - Use `mdc-brandvisualprovider` when brand visuals should be cached across re-renders or navigations to avoid repeated network fetches.
|
|
14
|
+
*
|
|
15
|
+
* **When not to use**
|
|
16
|
+
*
|
|
17
|
+
* - Do not expect one provider to cover every brand visual when fetching over HTTP. The set is split across an `svg` and a `png` folder and a provider points at one of them, so a page using artwork from both needs one provider for each — see **Content guidance** below. Outside that case, prefer a single provider near the root and nest only when a subtree genuinely needs a different source.
|
|
18
|
+
* - Do not reach for `mdc-brandvisualprovider` to render a logo — it has no visible UI. Use `mdc-brandvisual` for the visual itself.
|
|
19
|
+
* - Do not add a provider purely to keep the existing behaviour. `mdc-brandvisual` works without one.
|
|
20
|
+
*
|
|
21
|
+
* @tagname mdc-brandvisualprovider
|
|
22
|
+
*
|
|
23
|
+
* @slot - children
|
|
24
|
+
*/
|
|
25
|
+
declare class BrandVisualProvider extends Provider<BrandVisualProviderContext> {
|
|
26
|
+
constructor();
|
|
27
|
+
/**
|
|
28
|
+
* Context object of the BrandVisualProviderContext, to be consumed by child components
|
|
29
|
+
*/
|
|
30
|
+
static get Context(): {
|
|
31
|
+
__context__: BrandVisualProviderContext;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Brand visual set to be used
|
|
35
|
+
*
|
|
36
|
+
* If `momentum-brand-visuals` is selected, the brand visuals will be fetched from the
|
|
37
|
+
* Momentum Design System brand visual set per a dynamic JS Import (no need to provide a URL).
|
|
38
|
+
* This requires the consumer to have the `@momentum-design/brand-visuals` package installed and the
|
|
39
|
+
* build tooling needs to support dynamic imports.
|
|
40
|
+
*
|
|
41
|
+
* If `custom-brand-visuals` is selected, the brand visuals will be fetched from the provided URL.
|
|
42
|
+
* This requires the consumer to provide a URL from which the brand visuals will be fetched and
|
|
43
|
+
* the consumer needs to make sure to bundle the brand visuals in the application.
|
|
44
|
+
*
|
|
45
|
+
* @default momentum-brand-visuals
|
|
46
|
+
*/
|
|
47
|
+
brandVisualSet?: BrandVisualSet;
|
|
48
|
+
/**
|
|
49
|
+
* Url of where brand visuals will be fetched from
|
|
50
|
+
* (if Brand visual set is `custom-brand-visuals`, this will be the base url)
|
|
51
|
+
*/
|
|
52
|
+
url?: string;
|
|
53
|
+
/**
|
|
54
|
+
* File extension of brand visuals
|
|
55
|
+
* (if Brand visual set is `custom-brand-visuals`, this will be the file extension for brand visuals)
|
|
56
|
+
*
|
|
57
|
+
* `svg` visuals are fetched and inlined, `png` visuals are set as the `src` of an `img` element.
|
|
58
|
+
* Note that the two sets are not interchangeable: the device visuals only ship as `png`,
|
|
59
|
+
* every other visual only ships as `svg`.
|
|
60
|
+
*
|
|
61
|
+
* @default svg
|
|
62
|
+
*/
|
|
63
|
+
fileExtension?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Brand visuals Cache Strategy to use
|
|
66
|
+
*
|
|
67
|
+
* **Can only be used if Brand visual set is `custom-brand-visuals` and the file extension is `svg`**
|
|
68
|
+
* (`png` visuals are loaded by the browser through an `img` element and are subject to the
|
|
69
|
+
* regular HTTP cache instead).
|
|
70
|
+
*
|
|
71
|
+
* Choose `in-memory-cache` to cache brand visuals in a JS cache (in-memory cache).
|
|
72
|
+
* Choose `web-cache-api` to cache brand visuals using the Web Cache API.
|
|
73
|
+
*
|
|
74
|
+
* NOTE: `cache-name` must be provided if `cache-strategy` is provided.
|
|
75
|
+
*
|
|
76
|
+
* If not provided or invalid value provided, the brand visuals will not be cached.
|
|
77
|
+
* @default undefined
|
|
78
|
+
*/
|
|
79
|
+
cacheStrategy?: CacheStrategy;
|
|
80
|
+
/**
|
|
81
|
+
* Brand visuals Cache Name to use (cache strategy must be provided)
|
|
82
|
+
*
|
|
83
|
+
* If provided, Brand visuals inside the provider will be cached in the
|
|
84
|
+
* cache (determined by `cache-strategy`) with the provided name.
|
|
85
|
+
*
|
|
86
|
+
* Brand visuals cache name must be unique, independent from other asset caches.
|
|
87
|
+
*
|
|
88
|
+
* NOTE: `cache-name` requires `cache-strategy` to be set.
|
|
89
|
+
*
|
|
90
|
+
* If not provided, the brand visuals will not be cached.
|
|
91
|
+
* @default undefined
|
|
92
|
+
*/
|
|
93
|
+
cacheName?: string;
|
|
94
|
+
private updateValuesInContext;
|
|
95
|
+
protected updateContext(): void;
|
|
96
|
+
}
|
|
97
|
+
export default BrandVisualProvider;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { property } from 'lit/decorators.js';
|
|
11
|
+
import { Provider } from '../../models';
|
|
12
|
+
import BrandVisualProviderContext from './brandvisualprovider.context';
|
|
13
|
+
import { ALLOWED_FILE_EXTENSIONS, DEFAULTS } from './brandvisualprovider.constants';
|
|
14
|
+
/**
|
|
15
|
+
* @tagname mdc-brandvisualprovider
|
|
16
|
+
*
|
|
17
|
+
* @slot - children
|
|
18
|
+
*/
|
|
19
|
+
class BrandVisualProvider extends Provider {
|
|
20
|
+
constructor() {
|
|
21
|
+
// initialise the context by running the Provider constructor:
|
|
22
|
+
super({
|
|
23
|
+
context: BrandVisualProviderContext.context,
|
|
24
|
+
initialValue: new BrandVisualProviderContext(),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Brand visual set to be used
|
|
28
|
+
*
|
|
29
|
+
* If `momentum-brand-visuals` is selected, the brand visuals will be fetched from the
|
|
30
|
+
* Momentum Design System brand visual set per a dynamic JS Import (no need to provide a URL).
|
|
31
|
+
* This requires the consumer to have the `@momentum-design/brand-visuals` package installed and the
|
|
32
|
+
* build tooling needs to support dynamic imports.
|
|
33
|
+
*
|
|
34
|
+
* If `custom-brand-visuals` is selected, the brand visuals will be fetched from the provided URL.
|
|
35
|
+
* This requires the consumer to provide a URL from which the brand visuals will be fetched and
|
|
36
|
+
* the consumer needs to make sure to bundle the brand visuals in the application.
|
|
37
|
+
*
|
|
38
|
+
* @default momentum-brand-visuals
|
|
39
|
+
*/
|
|
40
|
+
this.brandVisualSet = DEFAULTS.BRAND_VISUAL_SET;
|
|
41
|
+
/**
|
|
42
|
+
* File extension of brand visuals
|
|
43
|
+
* (if Brand visual set is `custom-brand-visuals`, this will be the file extension for brand visuals)
|
|
44
|
+
*
|
|
45
|
+
* `svg` visuals are fetched and inlined, `png` visuals are set as the `src` of an `img` element.
|
|
46
|
+
* Note that the two sets are not interchangeable: the device visuals only ship as `png`,
|
|
47
|
+
* every other visual only ships as `svg`.
|
|
48
|
+
*
|
|
49
|
+
* @default svg
|
|
50
|
+
*/
|
|
51
|
+
this.fileExtension = DEFAULTS.FILE_EXTENSION;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Context object of the BrandVisualProviderContext, to be consumed by child components
|
|
55
|
+
*/
|
|
56
|
+
static get Context() {
|
|
57
|
+
return BrandVisualProviderContext.context;
|
|
58
|
+
}
|
|
59
|
+
updateValuesInContext() {
|
|
60
|
+
// only update fileExtension on context if its an allowed fileExtension
|
|
61
|
+
if (this.fileExtension && ALLOWED_FILE_EXTENSIONS.includes(this.fileExtension)) {
|
|
62
|
+
this.context.value.fileExtension = this.fileExtension;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Ensure both fileExtension and context are updated to the default if its not an allowed fileExtension
|
|
66
|
+
this.fileExtension = DEFAULTS.FILE_EXTENSION;
|
|
67
|
+
this.context.value.fileExtension = DEFAULTS.FILE_EXTENSION;
|
|
68
|
+
}
|
|
69
|
+
this.context.value.brandVisualSet = this.brandVisualSet;
|
|
70
|
+
this.context.value.url = this.url;
|
|
71
|
+
this.context.value.cacheName = this.cacheName;
|
|
72
|
+
this.context.value.cacheStrategy = this.cacheStrategy;
|
|
73
|
+
}
|
|
74
|
+
updateContext() {
|
|
75
|
+
if (this.context.value.fileExtension !== this.fileExtension ||
|
|
76
|
+
this.context.value.brandVisualSet !== this.brandVisualSet ||
|
|
77
|
+
this.context.value.url !== this.url ||
|
|
78
|
+
this.context.value.cacheName !== this.cacheName ||
|
|
79
|
+
this.context.value.cacheStrategy !== this.cacheStrategy) {
|
|
80
|
+
this.updateValuesInContext();
|
|
81
|
+
this.context.updateObservers();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
__decorate([
|
|
86
|
+
property({ type: String, attribute: 'brand-visual-set', reflect: true }),
|
|
87
|
+
__metadata("design:type", String)
|
|
88
|
+
], BrandVisualProvider.prototype, "brandVisualSet", void 0);
|
|
89
|
+
__decorate([
|
|
90
|
+
property({ type: String }),
|
|
91
|
+
__metadata("design:type", String)
|
|
92
|
+
], BrandVisualProvider.prototype, "url", void 0);
|
|
93
|
+
__decorate([
|
|
94
|
+
property({ type: String, attribute: 'file-extension', reflect: true }),
|
|
95
|
+
__metadata("design:type", String)
|
|
96
|
+
], BrandVisualProvider.prototype, "fileExtension", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
property({ type: String, attribute: 'cache-strategy' }),
|
|
99
|
+
__metadata("design:type", String)
|
|
100
|
+
], BrandVisualProvider.prototype, "cacheStrategy", void 0);
|
|
101
|
+
__decorate([
|
|
102
|
+
property({ type: String, attribute: 'cache-name' }),
|
|
103
|
+
__metadata("design:type", String)
|
|
104
|
+
], BrandVisualProvider.prototype, "cacheName", void 0);
|
|
105
|
+
export default BrandVisualProvider;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const TAG_NAME: "mdc-brandvisualprovider";
|
|
2
|
+
declare const ALLOWED_FILE_EXTENSIONS: string[];
|
|
3
|
+
declare const DEFAULTS: {
|
|
4
|
+
readonly FILE_EXTENSION: "svg";
|
|
5
|
+
readonly BRAND_VISUAL_SET: "momentum-brand-visuals";
|
|
6
|
+
};
|
|
7
|
+
export { TAG_NAME, DEFAULTS, ALLOWED_FILE_EXTENSIONS };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import utils from '../../utils/tag-name';
|
|
2
|
+
const TAG_NAME = utils.constructTagName('brandvisualprovider');
|
|
3
|
+
// brand visuals ship as vectors (`dist/svg`) and, for the device photography,
|
|
4
|
+
// as raster images (`dist/png`) — so both are valid custom set extensions.
|
|
5
|
+
const ALLOWED_FILE_EXTENSIONS = ['svg', 'png'];
|
|
6
|
+
const DEFAULTS = {
|
|
7
|
+
FILE_EXTENSION: 'svg',
|
|
8
|
+
BRAND_VISUAL_SET: 'momentum-brand-visuals',
|
|
9
|
+
};
|
|
10
|
+
export { TAG_NAME, DEFAULTS, ALLOWED_FILE_EXTENSIONS };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BrandVisualSet, CacheStrategy } from './brandvisualprovider.types';
|
|
2
|
+
declare class BrandVisualProviderContext {
|
|
3
|
+
brandVisualSet?: BrandVisualSet;
|
|
4
|
+
fileExtension?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
cacheName?: string;
|
|
7
|
+
cacheStrategy?: CacheStrategy;
|
|
8
|
+
static readonly context: {
|
|
9
|
+
__context__: BrandVisualProviderContext;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export default BrandVisualProviderContext;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createContext } from '@lit/context';
|
|
2
|
+
import { TAG_NAME } from './brandvisualprovider.constants';
|
|
3
|
+
class BrandVisualProviderContext {
|
|
4
|
+
}
|
|
5
|
+
// create typed lit context as part of the BrandVisualProviderContext
|
|
6
|
+
BrandVisualProviderContext.context = createContext(TAG_NAME);
|
|
7
|
+
export default BrandVisualProviderContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,9 +11,9 @@ import { html } from 'lit';
|
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
12
12
|
import { Component } from '../../models';
|
|
13
13
|
import providerUtils from '../../utils/provider';
|
|
14
|
+
import { assetFetch } from '../../utils/asset-fetch';
|
|
14
15
|
import IconProvider from '../iconprovider/iconprovider.component';
|
|
15
16
|
import styles from './icon.styles';
|
|
16
|
-
import { svgFetch } from './icon.utils';
|
|
17
17
|
import { DEFAULTS } from './icon.constants';
|
|
18
18
|
/**
|
|
19
19
|
* @tagname mdc-icon
|
|
@@ -80,13 +80,14 @@ class Icon extends Component {
|
|
|
80
80
|
return this.abortController.signal;
|
|
81
81
|
};
|
|
82
82
|
// fetch icon data (including caching logic)
|
|
83
|
-
return
|
|
83
|
+
return assetFetch({
|
|
84
84
|
url,
|
|
85
85
|
name: this.name,
|
|
86
86
|
fileExtension,
|
|
87
87
|
cacheName,
|
|
88
88
|
cacheStrategy,
|
|
89
89
|
renewSignal,
|
|
90
|
+
assetType: 'icon',
|
|
90
91
|
})
|
|
91
92
|
.then(iconData => {
|
|
92
93
|
// parse the fetched icon string to an html element and set the attributes
|
|
@@ -11,10 +11,10 @@ import { html } from 'lit';
|
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
12
12
|
import { Component } from '../../models';
|
|
13
13
|
import providerUtils from '../../utils/provider';
|
|
14
|
+
import { assetFetch } from '../../utils/asset-fetch';
|
|
14
15
|
import IllustrationProvider from '../illustrationprovider/illustrationprovider.component';
|
|
15
16
|
import { ROLE } from '../../utils/roles';
|
|
16
17
|
import styles from './illustration.styles';
|
|
17
|
-
import { svgFetch } from './illustration.utils';
|
|
18
18
|
import { DEFAULTS } from './illustration.constants';
|
|
19
19
|
/**
|
|
20
20
|
* @tagname mdc-illustration
|
|
@@ -82,13 +82,14 @@ class Illustration extends Component {
|
|
|
82
82
|
return this.abortController.signal;
|
|
83
83
|
};
|
|
84
84
|
// fetch illustration data (including caching logic)
|
|
85
|
-
return
|
|
85
|
+
return assetFetch({
|
|
86
86
|
url,
|
|
87
87
|
name: this.name,
|
|
88
88
|
fileExtension,
|
|
89
89
|
cacheName,
|
|
90
90
|
cacheStrategy,
|
|
91
91
|
renewSignal,
|
|
92
|
+
assetType: 'illustration',
|
|
92
93
|
})
|
|
93
94
|
.then(illustrationData => {
|
|
94
95
|
// parse the fetched illustration string to an html element and set the attributes
|