@schukai/monster 3.88.1 → 3.89.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.
@@ -12,31 +12,31 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import {instanceSymbol} from "../../constants.mjs";
16
- import {buildMap} from "../../data/buildmap.mjs";
17
- import {Pathfinder} from "../../data/pathfinder.mjs";
18
- import {addAttributeToken} from "../../dom/attributes.mjs";
15
+ import { instanceSymbol } from "../../constants.mjs";
16
+ import { buildMap } from "../../data/buildmap.mjs";
17
+ import { Pathfinder } from "../../data/pathfinder.mjs";
18
+ import { addAttributeToken } from "../../dom/attributes.mjs";
19
19
  import {
20
- ATTRIBUTE_ERRORMESSAGE,
21
- ATTRIBUTE_ROLE,
20
+ ATTRIBUTE_ERRORMESSAGE,
21
+ ATTRIBUTE_ROLE,
22
22
  } from "../../dom/constants.mjs";
23
23
  import {
24
- assembleMethodSymbol,
25
- registerCustomElement,
24
+ assembleMethodSymbol,
25
+ registerCustomElement,
26
26
  } from "../../dom/customelement.mjs";
27
27
  import {
28
- findTargetElementFromEvent,
29
- fireCustomEvent,
28
+ findTargetElementFromEvent,
29
+ fireCustomEvent,
30
30
  } from "../../dom/events.mjs";
31
- import {isArray, isPrimitive, isIterable} from "../../types/is.mjs";
32
- import {validateString} from "../../types/validate.mjs";
33
- import {ActionButton} from "./action-button.mjs";
34
- import {ApiButtonStyleSheet} from "./stylesheet/api-button.mjs";
35
- import {isObject, isFunction} from "../../types/is.mjs";
36
- import {getGlobal} from "../../types/global.mjs";
37
- import {Formatter} from "../../text/formatter.mjs";
31
+ import { isArray, isPrimitive, isIterable } from "../../types/is.mjs";
32
+ import { validateString } from "../../types/validate.mjs";
33
+ import { ActionButton } from "./action-button.mjs";
34
+ import { ApiButtonStyleSheet } from "./stylesheet/api-button.mjs";
35
+ import { isObject, isFunction } from "../../types/is.mjs";
36
+ import { getGlobal } from "../../types/global.mjs";
37
+ import { Formatter } from "../../text/formatter.mjs";
38
38
 
39
- export {ApiButton};
39
+ export { ApiButton };
40
40
 
41
41
  /**
42
42
  * @private
@@ -67,220 +67,220 @@ const containerElementSymbol = Symbol("containerElement");
67
67
  * @fires monster-api-button-failed
68
68
  */
69
69
  class ApiButton extends ActionButton {
70
- /**
71
- * This method is called by the `instanceof` operator.
72
- * @return {symbol}
73
- */
74
- static get [instanceSymbol]() {
75
- return Symbol.for("@schukai/monster/components/form/api-button@@instance");
76
- }
77
-
78
- /**
79
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
80
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
81
- *
82
- * The individual configuration values can be found in the table.
83
- *
84
- * @property {object} mapping - The mapping object.
85
- * @property {string} mapping.selector - The selector to find the buttons in the response.
86
- * @property {string} mapping.labelSelector - The selector to find the label for the button.
87
- * @property {string} mapping.labelTemplate - The template to create the label for the button.
88
- * @property {string} mapping.apiTemplate - The template to create the api for the button.
89
- * @property {string} mapping.urlTemplate - The template to create the url for the button.
90
- * @property {function} mapping.filter - The filter function to filter the buttons.
91
- * @property {string} url - The url to fetch the data.
92
- * @property {object} api - The api options.
93
- * @property {object} api.fetch - The fetch options.
94
- * @property {string} api.body - The body template.
95
- * @property {object} callbacks - The callbacks object.
96
- * @property {function} callbacks.beforeApi - The beforeApi callback.
97
- * @property {object} fetch - The fetch options.
98
- * @property {string} fetch.redirect - The redirect option.
99
- * @property {string} fetch.method - The method option.
100
- * @property {string} fetch.mode - The mode option.
101
- * @property {string} fetch.credentials - The credentials option.
102
- * @property {object} fetch.headers - The headers option.
103
- * @property {string} fetch.headers.accept - The acceptance option.
104
- * @extends {ActionButton.defaults}
105
- */
106
- get defaults() {
107
- const opts = Object.assign({}, super.defaults, {
108
- mapping: {
109
- selector: "*",
110
- labelSelector: "",
111
- labelTemplate: "",
112
- apiTemplate: "",
113
- urlTemplate: "",
114
- filter: "",
115
- },
116
- api: {
117
- fetch: {
118
- method: "POST",
119
- redirect: "error",
120
- mode: "same-origin",
121
- credentials: "same-origin",
122
- headers: {
123
- accept: "application/json",
124
- },
125
- },
126
- body: {},
127
- },
128
- url: "",
129
- callbacks: {
130
- beforeApi: null,
131
- },
132
- fetch: {
133
- redirect: "error",
134
- method: "GET",
135
- mode: "same-origin",
136
- credentials: "same-origin",
137
- headers: {
138
- accept: "application/json",
139
- },
140
- },
141
- });
142
-
143
- opts["actions"]["execute"] = executeAPIButton.bind(self);
144
-
145
- return opts;
146
- }
147
-
148
- /**
149
- *
150
- * @return {Promise}
151
- */
152
- fetch(url) {
153
- if (url instanceof URL) {
154
- url = url.toString();
155
- }
156
-
157
- if (url !== undefined) {
158
- url = validateString(url);
159
- }
160
-
161
- return fetchData.call(this, url).then((map) => {
162
- if (
163
- isObject(map) ||
164
- isArray(map) | (map instanceof Set) ||
165
- map instanceof Map
166
- ) {
167
- this.importButtons(map);
168
- }
169
- });
170
- }
171
-
172
- /**
173
- * Import buttons from a map.
174
- *
175
- * @param {array|object|Map|Set} data
176
- * @return {ApiButton}
177
- * @throws {Error} map is not iterable
178
- * @throws {Error} missing label configuration
179
- */
180
- importButtons(data) {
181
- const mappingOptions = this.getOption("mapping", {});
182
- const selector = mappingOptions?.["selector"];
183
- const labelSelector = mappingOptions?.["labelSelector"];
184
- const labelTemplate = mappingOptions?.["labelTemplate"];
185
- const apiTemplate = mappingOptions?.["apiTemplate"];
186
- let urlTemplate = mappingOptions?.["urlTemplate"];
187
- const filter = mappingOptions?.["filter"];
188
-
189
- let flag = false;
190
- let apiEqualUrl = false;
191
- if (labelTemplate === "") {
192
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template");
193
- flag = true;
194
- }
195
-
196
- if (apiTemplate === "") {
197
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty api template");
198
- flag = true;
199
- }
200
-
201
- if (urlTemplate === "") {
202
- urlTemplate = apiTemplate;
203
- apiEqualUrl = true;
204
- }
205
-
206
- if (flag === true) {
207
- throw new Error("missing label or api configuration");
208
- }
209
-
210
- if (isPrimitive(labelSelector) && labelSelector !== "") {
211
- const finder = new Pathfinder(data);
212
- const label = finder.getVia(labelSelector);
213
- this.setOption("labels.button", label);
214
- this.value = label;
215
- }
216
-
217
- let labelMap;
218
- const urlMap = buildMap(data, selector, urlTemplate, apiTemplate, filter);
219
- if (apiEqualUrl === true) {
220
- labelMap = urlMap;
221
- } else {
222
- labelMap = buildMap(data, selector, labelTemplate, apiTemplate, filter);
223
- }
224
-
225
- const buttons = [];
226
- if (!isIterable(urlMap)) {
227
- throw new Error("map is not iterable");
228
- }
229
-
230
- for (const [iterKey] of urlMap) {
231
- const vmUrl = urlMap.get(iterKey);
232
- const vmLabel = labelMap.get(iterKey);
233
- buttons.push({
234
- label: vmLabel,
235
- class: "monster-button-outline-primary monster-border-0",
236
- action: this.getOption("actions.execute"),
237
- url: vmUrl,
238
- cmd: iterKey,
239
- });
240
- }
241
-
242
- try {
243
- this.updateI18n();
244
- } catch (e) {
245
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
246
- }
247
-
248
- this.setOption("buttons", buttons);
249
-
250
- fireCustomEvent(this, "monster-button-set", {
251
- buttons: buttons,
252
- });
253
-
254
- return this;
255
- }
256
-
257
- /**
258
- *
259
- * @return {ApiButton}
260
- */
261
- [assembleMethodSymbol]() {
262
- super[assembleMethodSymbol]();
263
- initControlReferences.call(this);
264
- initEventHandler.call(this);
265
-
266
- return this;
267
- }
268
-
269
- /**
270
- * @return {string}
271
- */
272
- static getTag() {
273
- return "monster-api-button";
274
- }
275
-
276
- /**
277
- * @return {Array<CSSStyleSheet>}
278
- */
279
- static getCSSStyleSheet() {
280
- const styles = super.getCSSStyleSheet();
281
- styles.push(ApiButtonStyleSheet);
282
- return styles;
283
- }
70
+ /**
71
+ * This method is called by the `instanceof` operator.
72
+ * @return {symbol}
73
+ */
74
+ static get [instanceSymbol]() {
75
+ return Symbol.for("@schukai/monster/components/form/api-button@@instance");
76
+ }
77
+
78
+ /**
79
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
80
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
81
+ *
82
+ * The individual configuration values can be found in the table.
83
+ *
84
+ * @property {object} mapping - The mapping object.
85
+ * @property {string} mapping.selector - The selector to find the buttons in the response.
86
+ * @property {string} mapping.labelSelector - The selector to find the label for the button.
87
+ * @property {string} mapping.labelTemplate - The template to create the label for the button.
88
+ * @property {string} mapping.apiTemplate - The template to create the api for the button.
89
+ * @property {string} mapping.urlTemplate - The template to create the url for the button.
90
+ * @property {function} mapping.filter - The filter function to filter the buttons.
91
+ * @property {string} url - The url to fetch the data.
92
+ * @property {object} api - The api options.
93
+ * @property {object} api.fetch - The fetch options.
94
+ * @property {string} api.body - The body template.
95
+ * @property {object} callbacks - The callbacks object.
96
+ * @property {function} callbacks.beforeApi - The beforeApi callback.
97
+ * @property {object} fetch - The fetch options.
98
+ * @property {string} fetch.redirect - The redirect option.
99
+ * @property {string} fetch.method - The method option.
100
+ * @property {string} fetch.mode - The mode option.
101
+ * @property {string} fetch.credentials - The credentials option.
102
+ * @property {object} fetch.headers - The headers option.
103
+ * @property {string} fetch.headers.accept - The acceptance option.
104
+ * @extends {ActionButton.defaults}
105
+ */
106
+ get defaults() {
107
+ const opts = Object.assign({}, super.defaults, {
108
+ mapping: {
109
+ selector: "*",
110
+ labelSelector: "",
111
+ labelTemplate: "",
112
+ apiTemplate: "",
113
+ urlTemplate: "",
114
+ filter: "",
115
+ },
116
+ api: {
117
+ fetch: {
118
+ method: "POST",
119
+ redirect: "error",
120
+ mode: "same-origin",
121
+ credentials: "same-origin",
122
+ headers: {
123
+ accept: "application/json",
124
+ },
125
+ },
126
+ body: {},
127
+ },
128
+ url: "",
129
+ callbacks: {
130
+ beforeApi: null,
131
+ },
132
+ fetch: {
133
+ redirect: "error",
134
+ method: "GET",
135
+ mode: "same-origin",
136
+ credentials: "same-origin",
137
+ headers: {
138
+ accept: "application/json",
139
+ },
140
+ },
141
+ });
142
+
143
+ opts["actions"]["execute"] = executeAPIButton.bind(self);
144
+
145
+ return opts;
146
+ }
147
+
148
+ /**
149
+ *
150
+ * @return {Promise}
151
+ */
152
+ fetch(url) {
153
+ if (url instanceof URL) {
154
+ url = url.toString();
155
+ }
156
+
157
+ if (url !== undefined) {
158
+ url = validateString(url);
159
+ }
160
+
161
+ return fetchData.call(this, url).then((map) => {
162
+ if (
163
+ isObject(map) ||
164
+ isArray(map) | (map instanceof Set) ||
165
+ map instanceof Map
166
+ ) {
167
+ this.importButtons(map);
168
+ }
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Import buttons from a map.
174
+ *
175
+ * @param {array|object|Map|Set} data
176
+ * @return {ApiButton}
177
+ * @throws {Error} map is not iterable
178
+ * @throws {Error} missing label configuration
179
+ */
180
+ importButtons(data) {
181
+ const mappingOptions = this.getOption("mapping", {});
182
+ const selector = mappingOptions?.["selector"];
183
+ const labelSelector = mappingOptions?.["labelSelector"];
184
+ const labelTemplate = mappingOptions?.["labelTemplate"];
185
+ const apiTemplate = mappingOptions?.["apiTemplate"];
186
+ let urlTemplate = mappingOptions?.["urlTemplate"];
187
+ const filter = mappingOptions?.["filter"];
188
+
189
+ let flag = false;
190
+ let apiEqualUrl = false;
191
+ if (labelTemplate === "") {
192
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template");
193
+ flag = true;
194
+ }
195
+
196
+ if (apiTemplate === "") {
197
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty api template");
198
+ flag = true;
199
+ }
200
+
201
+ if (urlTemplate === "") {
202
+ urlTemplate = apiTemplate;
203
+ apiEqualUrl = true;
204
+ }
205
+
206
+ if (flag === true) {
207
+ throw new Error("missing label or api configuration");
208
+ }
209
+
210
+ if (isPrimitive(labelSelector) && labelSelector !== "") {
211
+ const finder = new Pathfinder(data);
212
+ const label = finder.getVia(labelSelector);
213
+ this.setOption("labels.button", label);
214
+ this.value = label;
215
+ }
216
+
217
+ let labelMap;
218
+ const urlMap = buildMap(data, selector, urlTemplate, apiTemplate, filter);
219
+ if (apiEqualUrl === true) {
220
+ labelMap = urlMap;
221
+ } else {
222
+ labelMap = buildMap(data, selector, labelTemplate, apiTemplate, filter);
223
+ }
224
+
225
+ const buttons = [];
226
+ if (!isIterable(urlMap)) {
227
+ throw new Error("map is not iterable");
228
+ }
229
+
230
+ for (const [iterKey] of urlMap) {
231
+ const vmUrl = urlMap.get(iterKey);
232
+ const vmLabel = labelMap.get(iterKey);
233
+ buttons.push({
234
+ label: vmLabel,
235
+ class: "monster-button-outline-primary monster-border-0",
236
+ action: this.getOption("actions.execute"),
237
+ url: vmUrl,
238
+ cmd: iterKey,
239
+ });
240
+ }
241
+
242
+ try {
243
+ this.updateI18n();
244
+ } catch (e) {
245
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
246
+ }
247
+
248
+ this.setOption("buttons", buttons);
249
+
250
+ fireCustomEvent(this, "monster-button-set", {
251
+ buttons: buttons,
252
+ });
253
+
254
+ return this;
255
+ }
256
+
257
+ /**
258
+ *
259
+ * @return {ApiButton}
260
+ */
261
+ [assembleMethodSymbol]() {
262
+ super[assembleMethodSymbol]();
263
+ initControlReferences.call(this);
264
+ initEventHandler.call(this);
265
+
266
+ return this;
267
+ }
268
+
269
+ /**
270
+ * @return {string}
271
+ */
272
+ static getTag() {
273
+ return "monster-api-button";
274
+ }
275
+
276
+ /**
277
+ * @return {Array<CSSStyleSheet>}
278
+ */
279
+ static getCSSStyleSheet() {
280
+ const styles = super.getCSSStyleSheet();
281
+ styles.push(ApiButtonStyleSheet);
282
+ return styles;
283
+ }
284
284
  }
285
285
 
286
286
  /**
@@ -290,145 +290,145 @@ class ApiButton extends ActionButton {
290
290
  * @param {Monster.Components.Form.ApiButton} element
291
291
  */
292
292
  function executeAPIButton(event, button, element) {
293
- const self = element;
294
-
295
- const fetchOptions = self.getOption("api.fetch", {});
296
-
297
- const callback = self.getOption("callbacks.beforeApi");
298
- if (isFunction(callback)) {
299
- callback.call(self, fetchOptions);
300
- }
301
-
302
- let url = undefined;
303
- let label = undefined;
304
- let key = undefined;
305
-
306
- const attr = button.getAttribute("data-monster-insert-reference");
307
- if (attr) {
308
- const index = attr.split("-")[1];
309
- const b = self.getOption("buttons." + index);
310
-
311
- url = b?.["url"];
312
- label = b?.["label"];
313
- key = b?.["cmd"];
314
- }
315
-
316
- const body = self.getOption("api.body");
317
- if (isObject(body)) {
318
- const bodyString = JSON.stringify(body);
319
-
320
- const obj = {
321
- url: url,
322
- label: label,
323
- value: self.getOption("value"),
324
- key: key,
325
- id: self.getOption("id"),
326
- };
327
-
328
- fetchOptions.body = new Formatter(obj, {}).format(bodyString);
329
- }
330
-
331
- if (button instanceof HTMLElement) {
332
- button.setState("activity");
333
- }
334
-
335
- fireCustomEvent(self, "monster-api-button-click", {
336
- button,
337
- });
338
-
339
- const global = getGlobal();
340
- global
341
- .fetch(url, fetchOptions)
342
- .then((response) => {
343
- if (!response.ok) {
344
- if (button instanceof HTMLElement) {
345
- button.setState("successful", 4000);
346
- }
347
- return Promise.reject(response);
348
- }
349
-
350
- const contentType = response?.headers?.get("content-type");
351
- if (contentType && contentType.indexOf("application/json") !== -1) {
352
- return response
353
- .text()
354
- .then((text) => {
355
- try {
356
- const data = JSON.parse(text); // Try to parse the response as JSON
357
-
358
- if (button instanceof HTMLElement) {
359
- button.setState("successful", 4000);
360
- }
361
-
362
- fireCustomEvent(self, "monster-api-button-successful", {
363
- button,
364
- data,
365
- response,
366
- contentType: response.headers.get("Content-Type"),
367
- });
368
- } catch (error) {
369
- if (button instanceof HTMLElement) {
370
- button.setState("failed", 4000);
371
- button.setMessage(error.message).showMessage(2000);
372
- }
373
-
374
- fireCustomEvent(self, "monster-api-button-failed", {
375
- button,
376
- error,
377
- response,
378
- contentType: response.headers.get("Content-Type"),
379
- });
380
- }
381
- })
382
- .catch((error) => {
383
- if (button instanceof HTMLElement) {
384
- button.setState("failed", 4000);
385
- button.setMessage("request failed").showMessage(2000);
386
- }
387
-
388
- fireCustomEvent(self, "monster-api-button-failed", {
389
- button,
390
- error,
391
- response,
392
- contentType: response.headers.get("Content-Type"),
393
- });
394
- });
395
- } else {
396
- return response
397
- .blob()
398
- .then((data) => {
399
- fireCustomEvent(self, "monster-api-button-successful", {
400
- button,
401
- data,
402
- response,
403
- contentType: response.headers.get("Content-Type"),
404
- });
405
- })
406
- .catch((error) => {
407
- if (button instanceof HTMLElement) {
408
- button.setState("failed", 4000);
409
- button.setMessage("request failed").showMessage(2000);
410
- }
411
-
412
- fireCustomEvent(self, "monster-api-button-failed", {
413
- button,
414
- error,
415
- response,
416
- contentType: response.headers.get("Content-Type"),
417
- });
418
- });
419
- }
420
- })
421
- .catch((error) => {
422
- if (button instanceof HTMLElement) {
423
- button.setState("failed", 4000);
424
- button.setMessage(error.message).showMessage(2000);
425
- }
426
-
427
- fireCustomEvent(self, "monster-api-button-failed", {
428
- button,
429
- error,
430
- });
431
- });
293
+ const self = element;
294
+
295
+ const fetchOptions = self.getOption("api.fetch", {});
296
+
297
+ const callback = self.getOption("callbacks.beforeApi");
298
+ if (isFunction(callback)) {
299
+ callback.call(self, fetchOptions);
300
+ }
301
+
302
+ let url = undefined;
303
+ let label = undefined;
304
+ let key = undefined;
305
+
306
+ const attr = button.getAttribute("data-monster-insert-reference");
307
+ if (attr) {
308
+ const index = attr.split("-")[1];
309
+ const b = self.getOption("buttons." + index);
310
+
311
+ url = b?.["url"];
312
+ label = b?.["label"];
313
+ key = b?.["cmd"];
314
+ }
315
+
316
+ const body = self.getOption("api.body");
317
+ if (isObject(body)) {
318
+ const bodyString = JSON.stringify(body);
319
+
320
+ const obj = {
321
+ url: url,
322
+ label: label,
323
+ value: self.getOption("value"),
324
+ key: key,
325
+ id: self.getOption("id"),
326
+ };
327
+
328
+ fetchOptions.body = new Formatter(obj, {}).format(bodyString);
329
+ }
330
+
331
+ if (button instanceof HTMLElement) {
332
+ button.setState("activity");
333
+ }
334
+
335
+ fireCustomEvent(self, "monster-api-button-click", {
336
+ button,
337
+ });
338
+
339
+ const global = getGlobal();
340
+ global
341
+ .fetch(url, fetchOptions)
342
+ .then((response) => {
343
+ if (!response.ok) {
344
+ if (button instanceof HTMLElement) {
345
+ button.setState("successful", 4000);
346
+ }
347
+ return Promise.reject(response);
348
+ }
349
+
350
+ const contentType = response?.headers?.get("content-type");
351
+ if (contentType && contentType.indexOf("application/json") !== -1) {
352
+ return response
353
+ .text()
354
+ .then((text) => {
355
+ try {
356
+ const data = JSON.parse(text); // Try to parse the response as JSON
357
+
358
+ if (button instanceof HTMLElement) {
359
+ button.setState("successful", 4000);
360
+ }
361
+
362
+ fireCustomEvent(self, "monster-api-button-successful", {
363
+ button,
364
+ data,
365
+ response,
366
+ contentType: response.headers.get("Content-Type"),
367
+ });
368
+ } catch (error) {
369
+ if (button instanceof HTMLElement) {
370
+ button.setState("failed", 4000);
371
+ button.setMessage(error.message).showMessage(2000);
372
+ }
373
+
374
+ fireCustomEvent(self, "monster-api-button-failed", {
375
+ button,
376
+ error,
377
+ response,
378
+ contentType: response.headers.get("Content-Type"),
379
+ });
380
+ }
381
+ })
382
+ .catch((error) => {
383
+ if (button instanceof HTMLElement) {
384
+ button.setState("failed", 4000);
385
+ button.setMessage("request failed").showMessage(2000);
386
+ }
387
+
388
+ fireCustomEvent(self, "monster-api-button-failed", {
389
+ button,
390
+ error,
391
+ response,
392
+ contentType: response.headers.get("Content-Type"),
393
+ });
394
+ });
395
+ } else {
396
+ return response
397
+ .blob()
398
+ .then((data) => {
399
+ fireCustomEvent(self, "monster-api-button-successful", {
400
+ button,
401
+ data,
402
+ response,
403
+ contentType: response.headers.get("Content-Type"),
404
+ });
405
+ })
406
+ .catch((error) => {
407
+ if (button instanceof HTMLElement) {
408
+ button.setState("failed", 4000);
409
+ button.setMessage("request failed").showMessage(2000);
410
+ }
411
+
412
+ fireCustomEvent(self, "monster-api-button-failed", {
413
+ button,
414
+ error,
415
+ response,
416
+ contentType: response.headers.get("Content-Type"),
417
+ });
418
+ });
419
+ }
420
+ })
421
+ .catch((error) => {
422
+ if (button instanceof HTMLElement) {
423
+ button.setState("failed", 4000);
424
+ button.setMessage(error.message).showMessage(2000);
425
+ }
426
+
427
+ fireCustomEvent(self, "monster-api-button-failed", {
428
+ button,
429
+ error,
430
+ });
431
+ });
432
432
  }
433
433
 
434
434
  /**
@@ -439,29 +439,29 @@ function executeAPIButton(event, button, element) {
439
439
  * @throws {TypeError} unsupported response
440
440
  */
441
441
  function fetchData(url) {
442
- if (!url) url = this.getOption("url");
443
- if (!url) return Promise.resolve();
444
-
445
- const fetchOptions = this.getOption("fetch", {});
446
-
447
- const global = getGlobal();
448
- return global
449
- .fetch(url, fetchOptions)
450
- .then((response) => {
451
- const contentType = response.headers.get("content-type");
452
- if (contentType && contentType.indexOf("application/json") !== -1) {
453
- return response.text();
454
- }
455
-
456
- throw new TypeError(`unsupported response ${contentType}`);
457
- })
458
- .then((text) => {
459
- try {
460
- return Promise.resolve(JSON.parse(text));
461
- } catch (e) {
462
- throw new TypeError("the result cannot be parsed");
463
- }
464
- });
442
+ if (!url) url = this.getOption("url");
443
+ if (!url) return Promise.resolve();
444
+
445
+ const fetchOptions = this.getOption("fetch", {});
446
+
447
+ const global = getGlobal();
448
+ return global
449
+ .fetch(url, fetchOptions)
450
+ .then((response) => {
451
+ const contentType = response.headers.get("content-type");
452
+ if (contentType && contentType.indexOf("application/json") !== -1) {
453
+ return response.text();
454
+ }
455
+
456
+ throw new TypeError(`unsupported response ${contentType}`);
457
+ })
458
+ .then((text) => {
459
+ try {
460
+ return Promise.resolve(JSON.parse(text));
461
+ } catch (e) {
462
+ throw new TypeError("the result cannot be parsed");
463
+ }
464
+ });
465
465
  }
466
466
 
467
467
  /**
@@ -469,27 +469,27 @@ function fetchData(url) {
469
469
  * @return {ApiButton}
470
470
  */
471
471
  function initEventHandler() {
472
- this[containerElementSymbol].addEventListener("click", (event) => {
473
- const element = findTargetElementFromEvent(
474
- event,
475
- "data-monster-insert-reference",
476
- );
477
-
478
- if (!(element instanceof HTMLElement)) {
479
- return;
480
- }
481
-
482
- const attr = element.getAttribute("data-monster-insert-reference");
483
- if (attr) {
484
- const index = attr.split("-")[1];
485
- const b = this.getOption("buttons." + index);
486
- if (isObject(b) && isFunction(b?.action)) {
487
- b.action(event, element, this);
488
- }
489
- }
490
- });
491
-
492
- return this;
472
+ this[containerElementSymbol].addEventListener("click", (event) => {
473
+ const element = findTargetElementFromEvent(
474
+ event,
475
+ "data-monster-insert-reference",
476
+ );
477
+
478
+ if (!(element instanceof HTMLElement)) {
479
+ return;
480
+ }
481
+
482
+ const attr = element.getAttribute("data-monster-insert-reference");
483
+ if (attr) {
484
+ const index = attr.split("-")[1];
485
+ const b = this.getOption("buttons." + index);
486
+ if (isObject(b) && isFunction(b?.action)) {
487
+ b.action(event, element, this);
488
+ }
489
+ }
490
+ });
491
+
492
+ return this;
493
493
  }
494
494
 
495
495
  /**
@@ -497,10 +497,10 @@ function initEventHandler() {
497
497
  * @return {ApiButton}
498
498
  */
499
499
  function initControlReferences() {
500
- this[containerElementSymbol] = this.shadowRoot.querySelector(
501
- `[${ATTRIBUTE_ROLE}=container]`,
502
- );
503
- return this;
500
+ this[containerElementSymbol] = this.shadowRoot.querySelector(
501
+ `[${ATTRIBUTE_ROLE}=container]`,
502
+ );
503
+ return this;
504
504
  }
505
505
 
506
506
  registerCustomElement(ApiButton);