@momentum-design/components 0.116.2 → 0.117.1
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 +319 -310
- package/dist/browser/index.js.map +4 -4
- package/dist/components/icon/icon.utils.d.ts +1 -1
- package/dist/components/icon/icon.utils.js +2 -2
- package/dist/components/iconprovider/iconprovider.component.d.ts +3 -1
- package/dist/components/iconprovider/iconprovider.component.js +1 -1
- package/dist/components/iconprovider/iconprovider.constants.d.ts +0 -1
- package/dist/components/iconprovider/iconprovider.constants.js +0 -1
- package/dist/components/illustration/illustration.component.d.ts +91 -0
- package/dist/components/illustration/illustration.component.js +220 -0
- package/dist/components/illustration/illustration.constants.d.ts +5 -0
- package/dist/components/illustration/illustration.constants.js +6 -0
- package/dist/components/illustration/illustration.styles.d.ts +2 -0
- package/dist/components/illustration/illustration.styles.js +15 -0
- package/dist/components/illustration/illustration.types.d.ts +2 -0
- package/dist/components/illustration/illustration.types.js +1 -0
- package/dist/components/illustration/illustration.utils.d.ts +32 -0
- package/dist/components/illustration/illustration.utils.js +79 -0
- package/dist/components/illustration/index.d.ts +7 -0
- package/dist/components/illustration/index.js +4 -0
- package/dist/components/illustrationprovider/illustrationprovider.component.d.ts +97 -0
- package/dist/components/illustrationprovider/illustrationprovider.component.js +123 -0
- package/dist/components/illustrationprovider/illustrationprovider.constants.d.ts +7 -0
- package/dist/components/illustrationprovider/illustrationprovider.constants.js +8 -0
- package/dist/components/illustrationprovider/illustrationprovider.context.d.ts +12 -0
- package/dist/components/illustrationprovider/illustrationprovider.context.js +7 -0
- package/dist/components/illustrationprovider/illustrationprovider.types.d.ts +3 -0
- package/dist/components/illustrationprovider/illustrationprovider.types.js +1 -0
- package/dist/components/illustrationprovider/index.d.ts +7 -0
- package/dist/components/illustrationprovider/index.js +4 -0
- package/dist/components/toast/index.d.ts +0 -1
- package/dist/components/toast/index.js +0 -1
- package/dist/components/toast/toast.component.d.ts +2 -1
- package/dist/components/toast/toast.component.js +6 -4
- package/dist/custom-elements.json +1394 -1060
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -3
- package/dist/react/iconprovider/index.d.ts +1 -1
- package/dist/react/iconprovider/index.js +1 -1
- package/dist/react/illustration/index.d.ts +40 -0
- package/dist/react/illustration/index.js +49 -0
- package/dist/react/illustrationprovider/index.d.ts +31 -0
- package/dist/react/illustrationprovider/index.js +40 -0
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.js +3 -1
- package/dist/react/toast/index.d.ts +0 -1
- package/dist/react/toast/index.js +0 -1
- package/dist/utils/{icon-cache → assets-cache}/index.d.ts +2 -2
- package/dist/utils/{icon-cache → assets-cache}/index.js +3 -3
- package/package.json +1 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { assetsCache } from '../../utils/assets-cache';
|
2
2
|
/**
|
3
3
|
* Utility function for fetching the icon from the provided `request`.
|
4
4
|
* It will throw an error if the response is not ok.
|
@@ -45,7 +45,7 @@ const svgFetch = async ({ url, name, fileExtension, cacheStrategy, cacheName, re
|
|
45
45
|
if (!cacheName || !cacheStrategy || !['in-memory-cache', 'web-cache-api'].includes(cacheStrategy)) {
|
46
46
|
return fetchIcon(request).then(response => response.text());
|
47
47
|
}
|
48
|
-
return
|
48
|
+
return assetsCache(cacheName, cacheStrategy).then(iconsCache => iconsCache
|
49
49
|
.get(request)
|
50
50
|
.then(responseFromCache => {
|
51
51
|
// **If entry in cache, return**
|
@@ -8,7 +8,7 @@ import type { CacheStrategy, IconSet } from './iconprovider.types';
|
|
8
8
|
* Attribute `iconSet` can be set to either `momentum-icons` or `custom-icons`.
|
9
9
|
* If `momentum-icons` is selected, the icons will be fetched from the
|
10
10
|
* Momentum Design System icon set per a dynamic JS Import (no need to provide a URL).
|
11
|
-
* This requires the consumer to have the `@momentum-
|
11
|
+
* This requires the consumer to have the `@momentum-design/icons` package installed and the
|
12
12
|
* build tooling needs to support dynamic imports.
|
13
13
|
*
|
14
14
|
* If `custom-icons` is selected, the icons will be fetched from the provided URL.
|
@@ -94,6 +94,8 @@ declare class IconProvider extends Provider<IconProviderContext> {
|
|
94
94
|
* If provided, Icons inside the provider will be cached in the
|
95
95
|
* cache (determined by `cache-strategy`) with the provided name.
|
96
96
|
*
|
97
|
+
* Icons cache name must be unique, independent from other asset caches.
|
98
|
+
*
|
97
99
|
* NOTE: `cache-name` requires `cache-strategy` to be set.
|
98
100
|
*
|
99
101
|
* If not provided, the icons will not be cached.
|
@@ -18,7 +18,7 @@ import { ALLOWED_FILE_EXTENSIONS, DEFAULTS, ALLOWED_LENGTH_UNITS } from './iconp
|
|
18
18
|
* Attribute `iconSet` can be set to either `momentum-icons` or `custom-icons`.
|
19
19
|
* If `momentum-icons` is selected, the icons will be fetched from the
|
20
20
|
* Momentum Design System icon set per a dynamic JS Import (no need to provide a URL).
|
21
|
-
* This requires the consumer to have the `@momentum-
|
21
|
+
* This requires the consumer to have the `@momentum-design/icons` package installed and the
|
22
22
|
* build tooling needs to support dynamic imports.
|
23
23
|
*
|
24
24
|
* If `custom-icons` is selected, the icons will be fetched from the provided URL.
|
@@ -6,7 +6,6 @@ declare const DEFAULTS: {
|
|
6
6
|
readonly FILE_EXTENSION: "svg";
|
7
7
|
readonly LENGTH_UNIT: "em";
|
8
8
|
readonly SIZE: number;
|
9
|
-
readonly SHOULD_CACHE: false;
|
10
9
|
readonly ICON_SET: "momentum-icons";
|
11
10
|
};
|
12
11
|
export { TAG_NAME, DEFAULTS, ALLOWED_FILE_EXTENSIONS, ALLOWED_LENGTH_UNITS, LENGTH_UNIT_SIZE };
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { CSSResult } from 'lit';
|
2
|
+
import { Component } from '../../models';
|
3
|
+
import type { IllustrationNames } from './illustration.types';
|
4
|
+
/**
|
5
|
+
* Illustration component that dynamically displays SVG illustrations based on a valid name.
|
6
|
+
*
|
7
|
+
* This component must be mounted within an `IllustrationProvider` component.
|
8
|
+
*
|
9
|
+
* The `IllustrationProvider` defines the source URL from which illustrations are consumed.
|
10
|
+
* The `Illustration` component accepts a `name` attribute, which corresponds to
|
11
|
+
* the file name of the illustration to be loaded from the specified URL.
|
12
|
+
*
|
13
|
+
* Once fetched, the illustration will be rendered. If the fetching process is unsuccessful,
|
14
|
+
* no illustration will be displayed.
|
15
|
+
*
|
16
|
+
* Default sizing of the illustration is controlled by choosing a different illustration name, can be overridden with the `--mdc-illustration-size` CSS property.
|
17
|
+
* Coloring of the illustration is currently baked into the svg, meaning that the illustration name determines
|
18
|
+
* the coloring.
|
19
|
+
*
|
20
|
+
* Regarding accessibility, there are two types of illustrations: decorative and informative.
|
21
|
+
*
|
22
|
+
* ### Decorative Illustrations
|
23
|
+
* - Decorative illustrations do not convey any essential information to the content of a page.
|
24
|
+
* - They should be hidden from screen readers (SR) to prevent confusion for users.
|
25
|
+
* - For decorative illustrations, an `aria-label` is not required, and the `role` will be set to null.
|
26
|
+
*
|
27
|
+
* ### Informative Illustrations
|
28
|
+
* - Informative illustrations convey important information that is not adequately represented
|
29
|
+
* by surrounding text or components.
|
30
|
+
* - They provide valuable context and must be announced by assistive technologies.
|
31
|
+
* - For informative illustrations, an `aria-label` is required, and the `role` will be set to "img" automatically.
|
32
|
+
* - If an `aria-label` is provided, the role will be set to 'img'; if it is absent,
|
33
|
+
* the role will be unset.
|
34
|
+
*
|
35
|
+
* @tagname mdc-illustration
|
36
|
+
*
|
37
|
+
* @cssproperty --mdc-illustration-size - Allows customization of the illustration size.
|
38
|
+
*
|
39
|
+
* @csspart illustration - The svg inside the illustration element.
|
40
|
+
*/
|
41
|
+
declare class Illustration extends Component {
|
42
|
+
private illustrationData?;
|
43
|
+
/**
|
44
|
+
* Name of the illustration (= filename)
|
45
|
+
*/
|
46
|
+
name?: IllustrationNames;
|
47
|
+
/**
|
48
|
+
* Aria-label attribute to be set for accessibility
|
49
|
+
*/
|
50
|
+
ariaLabel: string | null;
|
51
|
+
/**
|
52
|
+
* Aria-labelledby attribute to be set for accessibility
|
53
|
+
*/
|
54
|
+
ariaLabelledby: string | null;
|
55
|
+
private readonly illustrationProviderContext;
|
56
|
+
private abortController?;
|
57
|
+
constructor();
|
58
|
+
/**
|
59
|
+
* Parse the illustration string to an html element, set the attributes and
|
60
|
+
* return the illustration element
|
61
|
+
*
|
62
|
+
* @param illustrationData - The illustration string to be parsed
|
63
|
+
* @returns illustrationElement
|
64
|
+
*/
|
65
|
+
private prepareIllustrationElement;
|
66
|
+
/**
|
67
|
+
* Fetches the illustration (currently only svg) and sets state and attributes once fetched successfully
|
68
|
+
*
|
69
|
+
* This method uses abortController.signal to cancel the fetch request when the component is disconnected or updated.
|
70
|
+
* If the request is aborted after the fetch() call has been fulfilled but before the response body has been read,
|
71
|
+
* then attempting to read the response body will reject with an AbortError exception.
|
72
|
+
*/
|
73
|
+
private getIllustrationData;
|
74
|
+
/**
|
75
|
+
* Sets the illustrationData state to the fetched illustration.
|
76
|
+
* Dispatches a 'load' event on the component once the illustration has been successfully loaded.
|
77
|
+
* @param illustrationHtml - The illustration html element which has been fetched from the illustration provider.
|
78
|
+
*/
|
79
|
+
private handleIllustrationLoadedSuccess;
|
80
|
+
/**
|
81
|
+
* Dispatches an 'error' event on the component when the illustration fetching has failed.
|
82
|
+
* This event bubbles and is cancelable.
|
83
|
+
* The error detail is set to the error object.
|
84
|
+
*/
|
85
|
+
private handleIllustrationLoadedFailure;
|
86
|
+
updated(changedProperties: Map<string, any>): void;
|
87
|
+
disconnectedCallback(): void;
|
88
|
+
render(): import("lit-html").TemplateResult<1>;
|
89
|
+
static styles: Array<CSSResult>;
|
90
|
+
}
|
91
|
+
export default Illustration;
|
@@ -0,0 +1,220 @@
|
|
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 { html } from 'lit';
|
11
|
+
import { property, state } from 'lit/decorators.js';
|
12
|
+
import { Component } from '../../models';
|
13
|
+
import providerUtils from '../../utils/provider';
|
14
|
+
import IllustrationProvider from '../illustrationprovider/illustrationprovider.component';
|
15
|
+
import styles from './illustration.styles';
|
16
|
+
import { svgFetch } from './illustration.utils';
|
17
|
+
import { DEFAULTS } from './illustration.constants';
|
18
|
+
/**
|
19
|
+
* Illustration component that dynamically displays SVG illustrations based on a valid name.
|
20
|
+
*
|
21
|
+
* This component must be mounted within an `IllustrationProvider` component.
|
22
|
+
*
|
23
|
+
* The `IllustrationProvider` defines the source URL from which illustrations are consumed.
|
24
|
+
* The `Illustration` component accepts a `name` attribute, which corresponds to
|
25
|
+
* the file name of the illustration to be loaded from the specified URL.
|
26
|
+
*
|
27
|
+
* Once fetched, the illustration will be rendered. If the fetching process is unsuccessful,
|
28
|
+
* no illustration will be displayed.
|
29
|
+
*
|
30
|
+
* Default sizing of the illustration is controlled by choosing a different illustration name, can be overridden with the `--mdc-illustration-size` CSS property.
|
31
|
+
* Coloring of the illustration is currently baked into the svg, meaning that the illustration name determines
|
32
|
+
* the coloring.
|
33
|
+
*
|
34
|
+
* Regarding accessibility, there are two types of illustrations: decorative and informative.
|
35
|
+
*
|
36
|
+
* ### Decorative Illustrations
|
37
|
+
* - Decorative illustrations do not convey any essential information to the content of a page.
|
38
|
+
* - They should be hidden from screen readers (SR) to prevent confusion for users.
|
39
|
+
* - For decorative illustrations, an `aria-label` is not required, and the `role` will be set to null.
|
40
|
+
*
|
41
|
+
* ### Informative Illustrations
|
42
|
+
* - Informative illustrations convey important information that is not adequately represented
|
43
|
+
* by surrounding text or components.
|
44
|
+
* - They provide valuable context and must be announced by assistive technologies.
|
45
|
+
* - For informative illustrations, an `aria-label` is required, and the `role` will be set to "img" automatically.
|
46
|
+
* - If an `aria-label` is provided, the role will be set to 'img'; if it is absent,
|
47
|
+
* the role will be unset.
|
48
|
+
*
|
49
|
+
* @tagname mdc-illustration
|
50
|
+
*
|
51
|
+
* @cssproperty --mdc-illustration-size - Allows customization of the illustration size.
|
52
|
+
*
|
53
|
+
* @csspart illustration - The svg inside the illustration element.
|
54
|
+
*/
|
55
|
+
class Illustration extends Component {
|
56
|
+
constructor() {
|
57
|
+
super();
|
58
|
+
/**
|
59
|
+
* Name of the illustration (= filename)
|
60
|
+
*/
|
61
|
+
this.name = DEFAULTS.NAME;
|
62
|
+
/**
|
63
|
+
* Aria-label attribute to be set for accessibility
|
64
|
+
*/
|
65
|
+
this.ariaLabel = null;
|
66
|
+
/**
|
67
|
+
* Aria-labelledby attribute to be set for accessibility
|
68
|
+
*/
|
69
|
+
this.ariaLabelledby = null;
|
70
|
+
this.illustrationProviderContext = providerUtils.consume({
|
71
|
+
host: this,
|
72
|
+
context: IllustrationProvider.Context,
|
73
|
+
});
|
74
|
+
this.abortController = new AbortController(); // Initialize AbortController
|
75
|
+
}
|
76
|
+
/**
|
77
|
+
* Parse the illustration string to an html element, set the attributes and
|
78
|
+
* return the illustration element
|
79
|
+
*
|
80
|
+
* @param illustrationData - The illustration string to be parsed
|
81
|
+
* @returns illustrationElement
|
82
|
+
*/
|
83
|
+
prepareIllustrationElement(illustrationData) {
|
84
|
+
const illustrationElement = new DOMParser().parseFromString(illustrationData, 'text/html').body.children[0];
|
85
|
+
if (this.name) {
|
86
|
+
illustrationElement.setAttribute('data-name', this.name);
|
87
|
+
}
|
88
|
+
illustrationElement.setAttribute('part', 'illustration');
|
89
|
+
// set aria-hidden=true for SVG to avoid screen readers
|
90
|
+
illustrationElement.setAttribute('aria-hidden', 'true');
|
91
|
+
return illustrationElement;
|
92
|
+
}
|
93
|
+
/**
|
94
|
+
* Fetches the illustration (currently only svg) and sets state and attributes once fetched successfully
|
95
|
+
*
|
96
|
+
* This method uses abortController.signal to cancel the fetch request when the component is disconnected or updated.
|
97
|
+
* If the request is aborted after the fetch() call has been fulfilled but before the response body has been read,
|
98
|
+
* then attempting to read the response body will reject with an AbortError exception.
|
99
|
+
*/
|
100
|
+
async getIllustrationData() {
|
101
|
+
if (this.illustrationProviderContext.value) {
|
102
|
+
const { fileExtension, url, cacheName, illustrationSet, cacheStrategy } = this.illustrationProviderContext.value;
|
103
|
+
if (illustrationSet === 'custom-illustrations' && url && fileExtension && this.name) {
|
104
|
+
// function to abort the fetch request and create a new signal
|
105
|
+
// (directly passing the abortcontroller to the fetch request per reference
|
106
|
+
// will not work due to JS call-by-sharing behavior)
|
107
|
+
const renewSignal = () => {
|
108
|
+
var _a;
|
109
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
110
|
+
this.abortController = new AbortController();
|
111
|
+
return this.abortController.signal;
|
112
|
+
};
|
113
|
+
// fetch illustration data (including caching logic)
|
114
|
+
return svgFetch({
|
115
|
+
url,
|
116
|
+
name: this.name,
|
117
|
+
fileExtension,
|
118
|
+
cacheName,
|
119
|
+
cacheStrategy,
|
120
|
+
renewSignal,
|
121
|
+
})
|
122
|
+
.then(illustrationData => {
|
123
|
+
// parse the fetched illustration string to an html element and set the attributes
|
124
|
+
const illustrationElement = this.prepareIllustrationElement(illustrationData);
|
125
|
+
this.handleIllustrationLoadedSuccess(illustrationElement);
|
126
|
+
})
|
127
|
+
.catch(error => {
|
128
|
+
this.handleIllustrationLoadedFailure(error);
|
129
|
+
});
|
130
|
+
}
|
131
|
+
if (illustrationSet === 'momentum-illustrations' && this.name) {
|
132
|
+
// dynamic import of the lit template from the momentum illustrations package
|
133
|
+
return import(`@momentum-design/illustrations/dist/ts/${this.name}.ts`)
|
134
|
+
.then(module => {
|
135
|
+
this.handleIllustrationLoadedSuccess(module.default());
|
136
|
+
})
|
137
|
+
.catch(error => {
|
138
|
+
this.handleIllustrationLoadedFailure(error);
|
139
|
+
});
|
140
|
+
}
|
141
|
+
}
|
142
|
+
const noIllustrationProviderError = new Error('IllustrationProvider not found or not properly set up.');
|
143
|
+
this.handleIllustrationLoadedFailure(noIllustrationProviderError);
|
144
|
+
return Promise.reject(noIllustrationProviderError);
|
145
|
+
}
|
146
|
+
/**
|
147
|
+
* Sets the illustrationData state to the fetched illustration.
|
148
|
+
* Dispatches a 'load' event on the component once the illustration has been successfully loaded.
|
149
|
+
* @param illustrationHtml - The illustration html element which has been fetched from the illustration provider.
|
150
|
+
*/
|
151
|
+
handleIllustrationLoadedSuccess(illustrationHtml) {
|
152
|
+
// update illustrationData state once fetched:
|
153
|
+
this.illustrationData = illustrationHtml;
|
154
|
+
// when illustration is fetched successfully, trigger illustration load event.
|
155
|
+
const loadEvent = new Event('load', {
|
156
|
+
bubbles: true,
|
157
|
+
cancelable: true,
|
158
|
+
});
|
159
|
+
this.dispatchEvent(loadEvent);
|
160
|
+
}
|
161
|
+
/**
|
162
|
+
* Dispatches an 'error' event on the component when the illustration fetching has failed.
|
163
|
+
* This event bubbles and is cancelable.
|
164
|
+
* The error detail is set to the error object.
|
165
|
+
*/
|
166
|
+
handleIllustrationLoadedFailure(error) {
|
167
|
+
const errorEvent = new CustomEvent('error', {
|
168
|
+
bubbles: true,
|
169
|
+
cancelable: true,
|
170
|
+
detail: { error },
|
171
|
+
});
|
172
|
+
this.dispatchEvent(errorEvent);
|
173
|
+
}
|
174
|
+
updated(changedProperties) {
|
175
|
+
super.updated(changedProperties);
|
176
|
+
if (changedProperties.has('name')) {
|
177
|
+
// fetch illustration data if name changes:
|
178
|
+
this.getIllustrationData().catch(err => {
|
179
|
+
if (err.name !== 'AbortError' && this.onerror) {
|
180
|
+
this.onerror(err);
|
181
|
+
}
|
182
|
+
});
|
183
|
+
}
|
184
|
+
if (changedProperties.has('ariaLabel') || changedProperties.has('ariaLabelledBy')) {
|
185
|
+
this.role = this.ariaLabel || this.ariaLabelledby ? 'img' : null;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
disconnectedCallback() {
|
189
|
+
var _a;
|
190
|
+
super.disconnectedCallback();
|
191
|
+
// abort the fetch request when the component is disconnected
|
192
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
193
|
+
this.abortController = undefined; // reset the abort controller
|
194
|
+
}
|
195
|
+
render() {
|
196
|
+
return html ` ${this.illustrationData} `;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
Illustration.styles = [...Component.styles, ...styles];
|
200
|
+
__decorate([
|
201
|
+
state(),
|
202
|
+
__metadata("design:type", HTMLElement)
|
203
|
+
], Illustration.prototype, "illustrationData", void 0);
|
204
|
+
__decorate([
|
205
|
+
property({ type: String, reflect: true }),
|
206
|
+
__metadata("design:type", String)
|
207
|
+
], Illustration.prototype, "name", void 0);
|
208
|
+
__decorate([
|
209
|
+
property({ type: String, attribute: 'aria-label' }),
|
210
|
+
__metadata("design:type", Object)
|
211
|
+
], Illustration.prototype, "ariaLabel", void 0);
|
212
|
+
__decorate([
|
213
|
+
property({ type: String, attribute: 'aria-labelledby' }),
|
214
|
+
__metadata("design:type", Object)
|
215
|
+
], Illustration.prototype, "ariaLabelledby", void 0);
|
216
|
+
__decorate([
|
217
|
+
state(),
|
218
|
+
__metadata("design:type", AbortController)
|
219
|
+
], Illustration.prototype, "abortController", void 0);
|
220
|
+
export default Illustration;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { css } from 'lit';
|
2
|
+
import { hostFitContentStyles } from '../../utils/styles';
|
3
|
+
const styles = [
|
4
|
+
hostFitContentStyles,
|
5
|
+
css `
|
6
|
+
:host {
|
7
|
+
--mdc-illustration-size: auto;
|
8
|
+
}
|
9
|
+
:host::part(illustration) {
|
10
|
+
height: var(--mdc-illustration-size);
|
11
|
+
width: var(--mdc-illustration-size);
|
12
|
+
}
|
13
|
+
`,
|
14
|
+
];
|
15
|
+
export default styles;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import type { CacheStrategy } from '../../utils/assets-cache';
|
2
|
+
interface Args {
|
3
|
+
url: string;
|
4
|
+
name: string;
|
5
|
+
fileExtension: string;
|
6
|
+
cacheStrategy?: CacheStrategy;
|
7
|
+
cacheName?: string;
|
8
|
+
renewSignal: () => AbortSignal;
|
9
|
+
}
|
10
|
+
/**
|
11
|
+
* Fetches a dynamic SVG illustration based on the provided `url`, `name` and `fileExtension`.
|
12
|
+
* The fetch is aborted if the signal is aborted.
|
13
|
+
*
|
14
|
+
* This function also includes the logic to cache the fetched illustration using the In Memory Cache or Web Cache API.
|
15
|
+
* If the `cacheStrategy` is set to `web-cache-api` or `in-memory-cache` and `cacheName` is provided,
|
16
|
+
* the fetched illustration will be cached using the respective cache.
|
17
|
+
*
|
18
|
+
* It will throw an error if the response is not ok.
|
19
|
+
*
|
20
|
+
* @param url - The base url of the illustration
|
21
|
+
* @param name - The name of the illustration
|
22
|
+
* @param fileExtension - The file extension of the illustration
|
23
|
+
* @param signal - The signal to abort the fetch.
|
24
|
+
* It is used to cancel the fetch when the component is disconnected or updated.
|
25
|
+
* @param cacheStrategy - The cache strategy to use.
|
26
|
+
* @param cacheName - The cache name to use.
|
27
|
+
*
|
28
|
+
* @returns Response string from the fetch
|
29
|
+
* @throws Error if the response is not ok
|
30
|
+
*/
|
31
|
+
declare const svgFetch: ({ url, name, fileExtension, cacheStrategy, cacheName, renewSignal }: Args) => Promise<string>;
|
32
|
+
export { svgFetch };
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { assetsCache } from '../../utils/assets-cache';
|
2
|
+
/**
|
3
|
+
* Utility function for fetching the illustration from the provided `request`.
|
4
|
+
* It will throw an error if the response is not ok.
|
5
|
+
* @param request - The request object to fetch the illustration
|
6
|
+
* @returns Promise<Response> - The response from the fetch
|
7
|
+
* @throws Error if the response is not ok
|
8
|
+
*/
|
9
|
+
const fetchIllustration = async (request) => fetch(request).then(response => {
|
10
|
+
if (!response.ok) {
|
11
|
+
throw new Error('There was a problem while fetching the illustration!');
|
12
|
+
}
|
13
|
+
return response;
|
14
|
+
});
|
15
|
+
/**
|
16
|
+
* Fetches a dynamic SVG illustration based on the provided `url`, `name` and `fileExtension`.
|
17
|
+
* The fetch is aborted if the signal is aborted.
|
18
|
+
*
|
19
|
+
* This function also includes the logic to cache the fetched illustration using the In Memory Cache or Web Cache API.
|
20
|
+
* If the `cacheStrategy` is set to `web-cache-api` or `in-memory-cache` and `cacheName` is provided,
|
21
|
+
* the fetched illustration will be cached using the respective cache.
|
22
|
+
*
|
23
|
+
* It will throw an error if the response is not ok.
|
24
|
+
*
|
25
|
+
* @param url - The base url of the illustration
|
26
|
+
* @param name - The name of the illustration
|
27
|
+
* @param fileExtension - The file extension of the illustration
|
28
|
+
* @param signal - The signal to abort the fetch.
|
29
|
+
* It is used to cancel the fetch when the component is disconnected or updated.
|
30
|
+
* @param cacheStrategy - The cache strategy to use.
|
31
|
+
* @param cacheName - The cache name to use.
|
32
|
+
*
|
33
|
+
* @returns Response string from the fetch
|
34
|
+
* @throws Error if the response is not ok
|
35
|
+
*/
|
36
|
+
const svgFetch = async ({ url, name, fileExtension, cacheStrategy, cacheName, renewSignal }) => {
|
37
|
+
// abort the previous fetch request if it is still pending
|
38
|
+
// and create a new signal
|
39
|
+
const signal = renewSignal();
|
40
|
+
const request = new Request(`${url}/${name}.${fileExtension}`, {
|
41
|
+
signal,
|
42
|
+
});
|
43
|
+
// if there is no cache defined (cacheName and cacheStrategy properly set),
|
44
|
+
// fetch the illustration and return the response
|
45
|
+
if (!cacheName || !cacheStrategy || !['in-memory-cache', 'web-cache-api'].includes(cacheStrategy)) {
|
46
|
+
return fetchIllustration(request).then(response => response.text());
|
47
|
+
}
|
48
|
+
return assetsCache(cacheName, cacheStrategy).then(illustrationsCache => illustrationsCache
|
49
|
+
.get(request)
|
50
|
+
.then(responseFromCache => {
|
51
|
+
// **If entry in cache, return**
|
52
|
+
if (responseFromCache) {
|
53
|
+
return responseFromCache;
|
54
|
+
}
|
55
|
+
// **Otherwise, fetch and cache if successful**
|
56
|
+
// Both fetchIllustration() and illustrationsCache.set() "consume" the request,
|
57
|
+
// so we need to make a copy.
|
58
|
+
// (see https://developer.mozilla.org/en-US/docs/Web/API/Request/clone)
|
59
|
+
return fetchIllustration(request.clone()).then(response => {
|
60
|
+
var _a;
|
61
|
+
// This avoids caching responses that we know are errors
|
62
|
+
// (i.e. HTTP status code of 4xx or 5xx).
|
63
|
+
if (response.status < 400 && response.headers.has('content-type')) {
|
64
|
+
// Call .clone() on the response to save copy to cache.
|
65
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Request/clone
|
66
|
+
return (_a = illustrationsCache.set) === null || _a === void 0 ? void 0 : _a.call(illustrationsCache, request, response.clone()).then(() => response.text());
|
67
|
+
}
|
68
|
+
return response.text();
|
69
|
+
});
|
70
|
+
})
|
71
|
+
.catch(error => {
|
72
|
+
// Note that a HTTP error response (e.g. 404) will NOT trigger
|
73
|
+
// an exception.
|
74
|
+
// It will return a normal response object that has the appropriate
|
75
|
+
// error code set.
|
76
|
+
throw new Error(`Error in caching the Illustration ${name}, ${error}`);
|
77
|
+
}));
|
78
|
+
};
|
79
|
+
export { svgFetch };
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { Provider } from '../../models';
|
2
|
+
import IllustrationProviderContext from './illustrationprovider.context';
|
3
|
+
import type { CacheStrategy, IllustrationSet } from './illustrationprovider.types';
|
4
|
+
/**
|
5
|
+
* IllustrationProvider component, which allows to be consumed from sub components
|
6
|
+
* (see `providerUtils.consume` for how to consume)
|
7
|
+
*
|
8
|
+
* Attribute `illustrationSet` can be set to either `momentum-illustrations` or `custom-illustrations`.
|
9
|
+
* If `momentum-illustrations` is selected, the illustrations will be fetched from the
|
10
|
+
* Momentum Design System illustration set per a dynamic JS Import (no need to provide a URL).
|
11
|
+
* This requires the consumer to have the `@momentum-design/illustrations` package installed and the
|
12
|
+
* build tooling needs to support dynamic imports.
|
13
|
+
*
|
14
|
+
* If `custom-illustrations` is selected, the illustrations will be fetched from the provided URL.
|
15
|
+
* This requires the consumer to provide a URL from which the illustrations will be fetched and
|
16
|
+
* the consumer needs to make sure to bundle the illustrations in the application.
|
17
|
+
*
|
18
|
+
* If `cacheStrategy` is provided (only works with illustrationSet = `custom-illustrations`), the
|
19
|
+
* IllustrationProvider will cache the illustrations in the selected cache (either web-api-cache or in-memory-cache),
|
20
|
+
* to avoid fetching the same illustration multiple times over the network.
|
21
|
+
* This is useful when the same illustration is used multiple times in the application.
|
22
|
+
* To consider:
|
23
|
+
* - The `in-memory-cache` is not persisted and will be lost when the
|
24
|
+
* IllustrationProvider is removed from the DOM.
|
25
|
+
* - The `web-api-cache` is persisted, but only works in https environments
|
26
|
+
* (https://developer.mozilla.org/en-US/docs/Web/API/Cache).
|
27
|
+
*
|
28
|
+
* @tagname mdc-illustrationprovider
|
29
|
+
*
|
30
|
+
* @slot - children
|
31
|
+
*/
|
32
|
+
declare class IllustrationProvider extends Provider<IllustrationProviderContext> {
|
33
|
+
constructor();
|
34
|
+
/**
|
35
|
+
* Context object of the IllustrationProviderContext, to be consumed by child components
|
36
|
+
*/
|
37
|
+
static get Context(): {
|
38
|
+
__context__: IllustrationProviderContext;
|
39
|
+
};
|
40
|
+
/**
|
41
|
+
* Illustration set to be used
|
42
|
+
*
|
43
|
+
* If `momentum-illustrations` is selected, the illustrations will be fetched from the
|
44
|
+
* Momentum Design System illustration set per a dynamic JS Import (no need to provide a URL).
|
45
|
+
* This requires the consumer to have the `@momentum-designs` package installed and the
|
46
|
+
* build tooling needs to support dynamic imports.
|
47
|
+
*
|
48
|
+
* If `custom-illustrations` is selected, the illustrations will be fetched from the provided URL.
|
49
|
+
* This requires the consumer to provide a URL from which the illustrations will be fetched and
|
50
|
+
* the consumer needs to make sure to bundle the illustrations in the application.
|
51
|
+
*
|
52
|
+
* @default momentum-illustrations
|
53
|
+
*/
|
54
|
+
illustrationSet?: IllustrationSet;
|
55
|
+
/**
|
56
|
+
* Url of where illustrations will be fetched from
|
57
|
+
* (if Illustration set is `custom-illustrations`, this will be the base url)
|
58
|
+
*/
|
59
|
+
url?: string;
|
60
|
+
/**
|
61
|
+
* File extension of illustrations
|
62
|
+
* (if Illustration set is `custom-illustrations`, this will be the file extension for illustrations)
|
63
|
+
* @default svg
|
64
|
+
*/
|
65
|
+
fileExtension?: string;
|
66
|
+
/**
|
67
|
+
* Illustrations Cache Strategy to use
|
68
|
+
*
|
69
|
+
* **Can only be used if Illustration set is `custom-illustrations`**
|
70
|
+
*
|
71
|
+
* Choose `in-memory-cache` to cache illustrations in a JS cache (in-memory cache).
|
72
|
+
* Choose `web-cache-api` to cache illustrations 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 illustrations will not be cached.
|
77
|
+
* @default undefined
|
78
|
+
*/
|
79
|
+
cacheStrategy?: CacheStrategy;
|
80
|
+
/**
|
81
|
+
* Illustrations Cache Name to use (cache strategy must be provided)
|
82
|
+
*
|
83
|
+
* If provided, Illustrations inside the provider will be cached in the
|
84
|
+
* cache (determined by `cache-strategy`) with the provided name.
|
85
|
+
*
|
86
|
+
* Illustrations 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 illustrations will not be cached.
|
91
|
+
* @default undefined
|
92
|
+
*/
|
93
|
+
cacheName?: string;
|
94
|
+
private updateValuesInContext;
|
95
|
+
protected updateContext(): void;
|
96
|
+
}
|
97
|
+
export default IllustrationProvider;
|