@verbb/plugin-kit-core 2.0.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +46 -0
  4. package/dist/eslint/config.base.js +222 -0
  5. package/dist/eslint/config.react-hooks.js +45 -0
  6. package/dist/eslint/config.react-typescript.js +9 -0
  7. package/dist/eslint/config.react.js +10 -0
  8. package/dist/eslint/config.typescript-only.js +30 -0
  9. package/dist/eslint/config.typescript.js +7 -0
  10. package/dist/eslint/config.vite-react.js +5 -0
  11. package/dist/host/hostBridge.d.ts +40 -0
  12. package/dist/host/hostBridge.d.ts.map +1 -0
  13. package/dist/host/index.d.ts +3 -0
  14. package/dist/host/index.d.ts.map +1 -0
  15. package/dist/host/portal.d.ts +18 -0
  16. package/dist/host/portal.d.ts.map +1 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/plugin-kit-core.es.js +464 -0
  20. package/dist/plugin-kit-core.es.js.map +1 -0
  21. package/dist/plugin-kit-core.umd.js +528 -0
  22. package/dist/plugin-kit-core.umd.js.map +1 -0
  23. package/dist/prettier/config.mjs +10 -0
  24. package/dist/utils/collections.d.ts +79 -0
  25. package/dist/utils/collections.d.ts.map +1 -0
  26. package/dist/utils/forms.d.ts +27 -0
  27. package/dist/utils/forms.d.ts.map +1 -0
  28. package/dist/utils/handle.d.ts +17 -0
  29. package/dist/utils/handle.d.ts.map +1 -0
  30. package/dist/utils/index.d.ts +8 -0
  31. package/dist/utils/index.d.ts.map +1 -0
  32. package/dist/utils/markdown.d.ts +30 -0
  33. package/dist/utils/markdown.d.ts.map +1 -0
  34. package/dist/utils/promises.d.ts +13 -0
  35. package/dist/utils/promises.d.ts.map +1 -0
  36. package/dist/utils/query.d.ts +3 -0
  37. package/dist/utils/query.d.ts.map +1 -0
  38. package/dist/utils/string.d.ts +16 -0
  39. package/dist/utils/string.d.ts.map +1 -0
  40. package/package.json +57 -0
@@ -0,0 +1,528 @@
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("markdown-it")) : typeof define === "function" && define.amd ? define(["exports", "markdown-it"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.PluginKit = {}, global.MarkdownIt));
3
+ })(this, function(exports, markdown_it) {
4
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ markdown_it = __toESM(markdown_it, 1);
28
+ //#region src/host/portal.ts
29
+ var defaultPortalClassName;
30
+ var defaultPortalContainer;
31
+ var defaultShadowRootSelectors = ["[data-pk-shadow-root]"];
32
+ var setPortalClassName = (className) => {
33
+ defaultPortalClassName = className.trim() || void 0;
34
+ };
35
+ var getPortalClassName = (className) => {
36
+ return (className ?? defaultPortalClassName)?.trim() || void 0;
37
+ };
38
+ var resolvePortalContainer = (container) => {
39
+ if (!container) return;
40
+ if (typeof container === "object" && "current" in container) return container.current ?? void 0;
41
+ return container ?? void 0;
42
+ };
43
+ var setPortalContainer = (container) => {
44
+ defaultPortalContainer = resolvePortalContainer(container);
45
+ };
46
+ var getPortalContainer = (container) => {
47
+ return resolvePortalContainer(container) ?? defaultPortalContainer;
48
+ };
49
+ var setShadowRootSelectors = (selectors) => {
50
+ const normalizedSelectors = (selectors || []).map((selector) => selector.trim()).filter(Boolean);
51
+ defaultShadowRootSelectors = normalizedSelectors.length > 0 ? normalizedSelectors : ["[data-pk-shadow-root]"];
52
+ };
53
+ var getShadowRootSelectors = () => {
54
+ return defaultShadowRootSelectors;
55
+ };
56
+ /**
57
+ * Resolve where floating content should be portaled.
58
+ * Falls back to document.body when no container is configured.
59
+ */
60
+ var getPortalMountNode = (container) => {
61
+ const resolved = getPortalContainer(container);
62
+ if (resolved instanceof HTMLElement) return resolved;
63
+ if (resolved instanceof ShadowRoot) {
64
+ const target = getShadowRootSelectors().map((selector) => resolved.querySelector(selector)).find(Boolean) ?? (resolved.host instanceof HTMLElement ? resolved.host : void 0);
65
+ if (target) return target;
66
+ }
67
+ return document.body;
68
+ };
69
+ var getPortalTargetForAppend = () => {
70
+ const container = getPortalContainer();
71
+ if (!container) return;
72
+ if (container instanceof HTMLElement) return container;
73
+ const shadowRoot = container;
74
+ return getShadowRootSelectors().map((selector) => shadowRoot.querySelector(selector)).find(Boolean) ?? (shadowRoot.host instanceof HTMLElement ? shadowRoot.host : void 0);
75
+ };
76
+ //#endregion
77
+ //#region src/host/hostBridge.ts
78
+ var hostBridge = {};
79
+ var setHostBridge = (bridge = {}) => {
80
+ hostBridge = {
81
+ ...hostBridge,
82
+ ...bridge
83
+ };
84
+ };
85
+ var getHostBridge = () => {
86
+ return hostBridge;
87
+ };
88
+ var requireHostBridgeMethod = (methodName) => {
89
+ const method = hostBridge[methodName];
90
+ if (!method) throw new Error(`Plugin Kit host bridge method "${String(methodName)}" is required but was not configured.`);
91
+ return method;
92
+ };
93
+ var hostRequest = async (method, action, config) => {
94
+ return requireHostBridgeMethod("request")(method, action, config);
95
+ };
96
+ var hostOpenElementSelector = (elementType, options) => {
97
+ requireHostBridgeMethod("openElementSelector")(elementType, options);
98
+ };
99
+ var hostFormatDate = (date) => {
100
+ return requireHostBridgeMethod("formatDate")(date);
101
+ };
102
+ var hostGetTimepickerOptions = () => {
103
+ return requireHostBridgeMethod("getTimepickerOptions")();
104
+ };
105
+ var hostGetLocale = () => {
106
+ return requireHostBridgeMethod("getLocale")();
107
+ };
108
+ //#endregion
109
+ //#region src/utils/collections.ts
110
+ /**
111
+ * Collections utility for managing client-side collections of models
112
+ */
113
+ /**
114
+ * Generates a unique client-side ID string
115
+ * @param {string} [prefix='client'] - Optional prefix for the generated ID
116
+ * @returns {string} A unique ID string in the format: prefix_timestamp_randomString
117
+ */
118
+ var generateId = (prefix = "client") => {
119
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
120
+ };
121
+ /**
122
+ * Normalize a collection by adding _id to each item that doesn't have one
123
+ * @param {Array} collection - Array of items
124
+ * @returns {Array} - Normalized collection with _id on each item
125
+ */
126
+ var normalizeCollection = (collection = []) => {
127
+ return collection.map((item) => {
128
+ if (item._id) return item;
129
+ return {
130
+ ...item,
131
+ _id: generateId()
132
+ };
133
+ });
134
+ };
135
+ /**
136
+ * Create a new collection item
137
+ * @param {Object} itemData - Initial data for the new item
138
+ * @returns {Object} - The new item
139
+ */
140
+ var createItem = (itemData = {}) => {
141
+ return {
142
+ ...itemData,
143
+ _id: generateId()
144
+ };
145
+ };
146
+ /**
147
+ * Duplicate an existing item in a collection
148
+ * @param {Array} collection - Current collection
149
+ * @param {Object} item - Item to duplicate
150
+ * @param {Function} transformCallback - Optional callback to transform the duplicated item
151
+ * @returns {Object} - Updated collection with duplicated item
152
+ */
153
+ var duplicateItem = (collection = [], item, transformCallback = null) => {
154
+ const duplicatedItem = {
155
+ ...item,
156
+ _id: generateId()
157
+ };
158
+ const finalItem = transformCallback ? transformCallback(duplicatedItem) : duplicatedItem;
159
+ return [...collection, finalItem];
160
+ };
161
+ /**
162
+ * Delete a item from a collection
163
+ * @param {Array} collection - Current collection
164
+ * @param {Object} item - Item to delete
165
+ * @returns {Object} - Updated collection without the deleted item
166
+ */
167
+ var deleteItem = (collection = [], itemToDelete) => {
168
+ return collection.filter((item) => {
169
+ return item._id !== itemToDelete._id;
170
+ });
171
+ };
172
+ /**
173
+ * Update an item in a collection
174
+ * @param {Array} collection - Current collection
175
+ * @param {Object} item - Item to update
176
+ * @param {Object} updates - Updates to apply to the item
177
+ * @returns {Object} - Updated collection with updated item
178
+ */
179
+ var updateItem = (collection = [], itemToUpdate, updates) => {
180
+ return collection.map((item) => {
181
+ if (item._id === itemToUpdate._id) return {
182
+ ...item,
183
+ ...updates,
184
+ _id: item._id
185
+ };
186
+ return item;
187
+ });
188
+ };
189
+ /**
190
+ * Move an item to a new position in a collection
191
+ * @param {Array} collection - Current collection
192
+ * @param {Object} fromItem - Item to move
193
+ * @param {Object} toItem - Item to move to (insert before this item)
194
+ * @returns {Array} - Updated collection with moved item
195
+ */
196
+ var moveItem = (collection = [], fromItem, toItem) => {
197
+ if (fromItem._id === toItem._id) return collection;
198
+ const fromIndex = collection.findIndex((item) => {
199
+ return item._id === fromItem._id;
200
+ });
201
+ const toIndex = collection.findIndex((item) => {
202
+ return item._id === toItem._id;
203
+ });
204
+ if (fromIndex === -1 || toIndex === -1) return collection;
205
+ const newCollection = [...collection];
206
+ const [movedItem] = newCollection.splice(fromIndex, 1);
207
+ newCollection.splice(toIndex, 0, movedItem);
208
+ return newCollection;
209
+ };
210
+ /**
211
+ * Find an item in a collection by _id
212
+ * @param {Array} collection - Collection to search
213
+ * @param {string} _id - Client-side ID to find
214
+ * @returns {Object|null} - Found model or null
215
+ */
216
+ var findItemById = (collection = [], _id) => {
217
+ return collection.find((item) => {
218
+ return item._id === _id;
219
+ }) || null;
220
+ };
221
+ /**
222
+ * Get all items that have server-side IDs (existing items)
223
+ * @param {Array} collection - Collection to filter
224
+ * @returns {Array} - Items with server-side IDs
225
+ */
226
+ var getExistingItems = (collection = []) => {
227
+ return collection.filter((item) => {
228
+ return item.id;
229
+ });
230
+ };
231
+ /**
232
+ * Get all items that don't have server-side IDs (new items)
233
+ * @param {Array} collection - Collection to filter
234
+ * @returns {Array} - Items without server-side IDs
235
+ */
236
+ var getNewItems = (collection = []) => {
237
+ return collection.filter((item) => {
238
+ return !item.id;
239
+ });
240
+ };
241
+ var findRecursive = (items, predicate, optionsKey = "options") => {
242
+ for (const item of items) {
243
+ if (item[optionsKey] && Array.isArray(item[optionsKey])) {
244
+ const result = findRecursive(item[optionsKey], predicate, optionsKey);
245
+ if (result) return result;
246
+ }
247
+ if (predicate(item)) return item;
248
+ }
249
+ return null;
250
+ };
251
+ /**
252
+ * Creates a deep clone of a value using JSON serialization
253
+ * @param {any} value - The value to clone
254
+ * @returns {any} A deep clone of the input value, or undefined if input is undefined
255
+ */
256
+ var clone = function(value) {
257
+ if (value === void 0) return;
258
+ return JSON.parse(JSON.stringify(value));
259
+ };
260
+ //#endregion
261
+ //#region src/utils/forms.ts
262
+ var nl2br = (str) => {
263
+ return str.replace(/\n/g, "<br>");
264
+ };
265
+ var getErrorHeading = (error) => {
266
+ if (error.response?.statusText) return error.response.statusText;
267
+ if (error.message?.includes("Network Error")) return "Network Error";
268
+ if (error.message?.includes("timeout")) return "Request Timeout";
269
+ return "An error has occurred";
270
+ };
271
+ var getErrorText = (error) => {
272
+ if (error.response?.data?.message) return error.response.data.message;
273
+ if (error.response?.data?.error) return error.response.data.error;
274
+ if (error.message) return error.message;
275
+ return String(error);
276
+ };
277
+ var getErrorTrace = (error, maxTraceLines = 5) => {
278
+ const traces = [];
279
+ const file1 = error.response?.data?.file;
280
+ const line1 = error.response?.data?.line;
281
+ if (file1 && line1) traces.push(`${file1}:${line1}`);
282
+ const traceArray = error.response?.data?.trace || [];
283
+ for (let i = 0; i < Math.min(maxTraceLines, traceArray.length); i++) {
284
+ const traceItem = traceArray[i];
285
+ if (traceItem?.file && traceItem?.line) traces.push(`${traceItem.file}:${traceItem.line}`);
286
+ }
287
+ if (error.stack && traces.length === 0) traces.push(error.stack);
288
+ return {
289
+ traces,
290
+ traceAsString: traces.map(nl2br).join("<br>")
291
+ };
292
+ };
293
+ var getErrorMessage = function(error, maxTraceLines = 5) {
294
+ const { traces, traceAsString } = getErrorTrace(error, maxTraceLines);
295
+ return {
296
+ heading: getErrorHeading(error),
297
+ text: getErrorText(error),
298
+ trace: traceAsString,
299
+ traceAsString,
300
+ traceAsArray: traces
301
+ };
302
+ };
303
+ //#endregion
304
+ //#region src/utils/string.ts
305
+ /**
306
+ * Convert a string to a handle format
307
+ * @param {string} sourceValue - The source string to convert
308
+ * @param {string} handleCasing - The casing format ('camelCase', 'pascal', 'snake', 'kebab')
309
+ * @param {boolean} allowNonAlphaStart - Whether to allow non-alphabetic characters at the start
310
+ * @returns {string} The generated handle
311
+ */
312
+ var generateHandle = function(sourceValue, handleCasing = "camelCase", allowNonAlphaStart = false) {
313
+ let handle = sourceValue.replace("/<(.*?)>/g", "");
314
+ handle = handle.replace(/['"'""\[\]\(\)\{\}:]/g, "");
315
+ handle = handle.toLowerCase();
316
+ handle = window.Craft.asciiString(handle);
317
+ if (!allowNonAlphaStart) handle = handle.replace(/^[^a-z]+/, "");
318
+ const words = window.Craft.filterArray(handle.split(/[^a-z0-9]+/));
319
+ handle = "";
320
+ if (handleCasing === "snake") return words.join("_");
321
+ if (handleCasing === "kebab") return words.join("-");
322
+ for (let i = 0; i < words.length; i++) if (handleCasing !== "pascal" && i === 0) handle += words[i];
323
+ else handle += words[i].charAt(0).toUpperCase() + words[i].substr(1);
324
+ return handle;
325
+ };
326
+ /**
327
+ * Find a unique handle by checking against reserved handles and adding suffixes
328
+ * @param {string} baseHandle - The base handle to check
329
+ * @param {Array} allReservedHandles - Array of all reserved handles to check against (static + dynamic)
330
+ * @returns {string} A unique handle
331
+ */
332
+ var findUniqueHandle = (baseHandle, allReservedHandles = []) => {
333
+ if (!baseHandle) return "";
334
+ let handle = baseHandle;
335
+ let counter = 1;
336
+ while (allReservedHandles.includes(handle)) {
337
+ handle = `${baseHandle}${counter}`;
338
+ counter++;
339
+ }
340
+ return handle;
341
+ };
342
+ //#endregion
343
+ //#region src/utils/handle.ts
344
+ /** Minimal dot/bracket path getter so this stays dependency-free (no lodash). */
345
+ var getByPath = (source, path) => {
346
+ if (source == null || typeof source !== "object" || !path) return;
347
+ const segments = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
348
+ let current = source;
349
+ for (const segment of segments) {
350
+ if (current == null || typeof current !== "object") return;
351
+ current = current[segment];
352
+ }
353
+ return current;
354
+ };
355
+ var normalizeHandleSource = (value) => {
356
+ if (value == null) return "";
357
+ return String(value).replace(/\{[^}]*\}/g, " ").replace(/\s+/g, " ").trim();
358
+ };
359
+ /**
360
+ * Resolve dynamic reserved handles from other field values (e.g. a sibling field whose
361
+ * value would collide once slugified).
362
+ */
363
+ var getDynamicReservedHandles = (values, reservedFieldValues = []) => {
364
+ const dynamicHandles = [];
365
+ reservedFieldValues.forEach((fieldPath) => {
366
+ const value = getByPath(values, fieldPath);
367
+ if (value && typeof value === "string") {
368
+ const handleValue = generateHandle(normalizeHandleSource(value));
369
+ if (handleValue) dynamicHandles.push(handleValue);
370
+ }
371
+ });
372
+ return dynamicHandles;
373
+ };
374
+ var truncateHandle = (handle, maxLength) => {
375
+ if (!Number.isFinite(maxLength)) return handle;
376
+ const length = Math.max(Number(maxLength), 0);
377
+ return handle.slice(0, length);
378
+ };
379
+ var findUniqueHandleWithinMaxLength = (baseHandle, reservedHandles = [], maxLength) => {
380
+ if (!baseHandle) return "";
381
+ if (!Number.isFinite(maxLength)) return findUniqueHandle(baseHandle, reservedHandles);
382
+ const normalizedReserved = new Set((reservedHandles || []).map((handle) => {
383
+ return String(handle || "").toLowerCase();
384
+ }));
385
+ const truncatedBase = truncateHandle(baseHandle, maxLength);
386
+ if (!truncatedBase) return "";
387
+ if (!normalizedReserved.has(truncatedBase.toLowerCase())) return truncatedBase;
388
+ let suffix = 1;
389
+ while (suffix < 1e4) {
390
+ const suffixText = String(suffix);
391
+ const baseMaxLength = Math.max(Number(maxLength) - suffixText.length, 0);
392
+ const truncatedWithSuffix = `${truncatedBase.slice(0, baseMaxLength)}${suffixText}`;
393
+ if (!normalizedReserved.has(truncatedWithSuffix.toLowerCase())) return truncatedWithSuffix;
394
+ suffix += 1;
395
+ }
396
+ return truncatedBase;
397
+ };
398
+ /**
399
+ * Generate a unique handle from a human-readable source value, honouring reserved handles
400
+ * (static + dynamically derived from other field values) and an optional max length.
401
+ */
402
+ var buildUniqueHandleFromSource = ({ sourceValue, values = {}, reservedHandles = [], reservedFieldValues = [], maxLength }) => {
403
+ const baseHandle = generateHandle(normalizeHandleSource(sourceValue));
404
+ const dynamicHandles = getDynamicReservedHandles(values, reservedFieldValues);
405
+ return findUniqueHandleWithinMaxLength(baseHandle, [...reservedHandles, ...dynamicHandles], maxLength);
406
+ };
407
+ //#endregion
408
+ //#region src/utils/markdown.ts
409
+ /**
410
+ * Initialize markdown-it instance with secure defaults and common options
411
+ * - HTML is disabled for security
412
+ * - Links are auto-detected
413
+ * - Typography features like smart quotes are enabled
414
+ * - Line breaks are converted to <br> tags
415
+ */
416
+ var md = new markdown_it.default({
417
+ html: false,
418
+ linkify: true,
419
+ typographer: true,
420
+ breaks: true
421
+ });
422
+ /**
423
+ * Renders markdown content as block-level HTML
424
+ * Includes block elements like headers, paragraphs, lists etc.
425
+ *
426
+ * @param content - The markdown string to render
427
+ * @returns Rendered HTML string, or empty string if no content provided
428
+ */
429
+ var renderMarkdown = (content) => {
430
+ if (!content) return "";
431
+ return md.render(content);
432
+ };
433
+ /**
434
+ * Renders markdown content as inline HTML only
435
+ * Excludes block-level elements, only processes inline markdown syntax
436
+ *
437
+ * @param content - The markdown string to render
438
+ * @returns Rendered HTML string, or empty string if no content provided
439
+ */
440
+ var renderInlineMarkdown = (content) => {
441
+ if (!content) return "";
442
+ return md.renderInline(content);
443
+ };
444
+ //#endregion
445
+ //#region src/utils/promises.ts
446
+ /**
447
+ * Creates a function that ensures a promise takes at least a minimum amount of time to resolve
448
+ *
449
+ * @param ms - The minimum time in milliseconds that the promise should take
450
+ * @returns A function that wraps a promise or promise-returning function
451
+ * @example
452
+ * ```ts
453
+ * const slowFetch = takeAtLeast(1000)(fetch('https://api.example.com'));
454
+ * // Will take at least 1 second even if the fetch is faster
455
+ * ```
456
+ */
457
+ var takeAtLeast = function(ms) {
458
+ /**
459
+ * Wraps a promise or promise-returning function to ensure minimum execution time
460
+ *
461
+ * @param promiseOrFn - A promise or a function that returns a promise
462
+ * @returns A promise that resolves with the original promise's value after at least `ms` milliseconds
463
+ * @throws Will throw if the original promise rejects
464
+ */
465
+ return function(promiseOrFn) {
466
+ const promise = typeof promiseOrFn === "function" ? promiseOrFn() : promiseOrFn;
467
+ const delay = new Promise((resolve) => {
468
+ return setTimeout(resolve, ms);
469
+ });
470
+ return Promise.allSettled([promise, delay]).then((results) => {
471
+ const [promiseResult] = results;
472
+ if (promiseResult.status === "rejected") throw promiseResult.reason;
473
+ return promiseResult.value;
474
+ });
475
+ };
476
+ };
477
+ //#endregion
478
+ //#region src/utils/query.ts
479
+ var getQueryParam = (key) => {
480
+ return new URLSearchParams(window.location.search).get(key);
481
+ };
482
+ var setQueryParam = (key, value) => {
483
+ const url = new URL(window.location.href);
484
+ url.searchParams.set(key, value);
485
+ window.history.replaceState({}, "", url.toString());
486
+ };
487
+ //#endregion
488
+ exports.buildUniqueHandleFromSource = buildUniqueHandleFromSource;
489
+ exports.clone = clone;
490
+ exports.createItem = createItem;
491
+ exports.deleteItem = deleteItem;
492
+ exports.duplicateItem = duplicateItem;
493
+ exports.findItemById = findItemById;
494
+ exports.findRecursive = findRecursive;
495
+ exports.findUniqueHandle = findUniqueHandle;
496
+ exports.generateHandle = generateHandle;
497
+ exports.generateId = generateId;
498
+ exports.getDynamicReservedHandles = getDynamicReservedHandles;
499
+ exports.getErrorMessage = getErrorMessage;
500
+ exports.getExistingItems = getExistingItems;
501
+ exports.getHostBridge = getHostBridge;
502
+ exports.getNewItems = getNewItems;
503
+ exports.getPortalClassName = getPortalClassName;
504
+ exports.getPortalContainer = getPortalContainer;
505
+ exports.getPortalMountNode = getPortalMountNode;
506
+ exports.getPortalTargetForAppend = getPortalTargetForAppend;
507
+ exports.getQueryParam = getQueryParam;
508
+ exports.getShadowRootSelectors = getShadowRootSelectors;
509
+ exports.hostFormatDate = hostFormatDate;
510
+ exports.hostGetLocale = hostGetLocale;
511
+ exports.hostGetTimepickerOptions = hostGetTimepickerOptions;
512
+ exports.hostOpenElementSelector = hostOpenElementSelector;
513
+ exports.hostRequest = hostRequest;
514
+ exports.md = md;
515
+ exports.moveItem = moveItem;
516
+ exports.normalizeCollection = normalizeCollection;
517
+ exports.renderInlineMarkdown = renderInlineMarkdown;
518
+ exports.renderMarkdown = renderMarkdown;
519
+ exports.setHostBridge = setHostBridge;
520
+ exports.setPortalClassName = setPortalClassName;
521
+ exports.setPortalContainer = setPortalContainer;
522
+ exports.setQueryParam = setQueryParam;
523
+ exports.setShadowRootSelectors = setShadowRootSelectors;
524
+ exports.takeAtLeast = takeAtLeast;
525
+ exports.updateItem = updateItem;
526
+ });
527
+
528
+ //# sourceMappingURL=plugin-kit-core.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-kit-core.umd.js","names":[],"sources":["../src/host/portal.ts","../src/host/hostBridge.ts","../src/utils/collections.ts","../src/utils/forms.ts","../src/utils/string.ts","../src/utils/handle.ts","../src/utils/markdown.ts","../src/utils/promises.ts","../src/utils/query.ts"],"sourcesContent":["export type PortalContainer = HTMLElement | ShadowRoot | null;\n\nexport type PortalContainerRef = {\n current: PortalContainer;\n};\n\nexport type PortalContainerInput = PortalContainer | PortalContainerRef;\n\nlet defaultPortalClassName: string | undefined;\nlet defaultPortalContainer: PortalContainer | undefined;\nlet defaultShadowRootSelectors: string[] = ['[data-pk-shadow-root]'];\n\nexport const setPortalClassName = (className: string): void => {\n defaultPortalClassName = className.trim() || undefined;\n};\n\nexport const getPortalClassName = (className?: string): string | undefined => {\n return (className ?? defaultPortalClassName)?.trim() || undefined;\n};\n\nconst resolvePortalContainer = (container?: PortalContainerInput): PortalContainer | undefined => {\n if (!container) {\n return undefined;\n }\n\n if (typeof container === 'object' && 'current' in container) {\n return container.current ?? undefined;\n }\n\n return container ?? undefined;\n};\n\nexport const setPortalContainer = (container: PortalContainerInput): void => {\n defaultPortalContainer = resolvePortalContainer(container);\n};\n\nexport const getPortalContainer = (container?: PortalContainerInput): PortalContainer | undefined => {\n return resolvePortalContainer(container) ?? defaultPortalContainer;\n};\n\nexport const setShadowRootSelectors = (selectors: string[]): void => {\n const normalizedSelectors = (selectors || [])\n .map((selector) => selector.trim())\n .filter(Boolean);\n\n defaultShadowRootSelectors = normalizedSelectors.length > 0\n ? normalizedSelectors\n : ['[data-pk-shadow-root]'];\n};\n\nexport const getShadowRootSelectors = (): string[] => {\n return defaultShadowRootSelectors;\n};\n\n/**\n * Resolve where floating content should be portaled.\n * Falls back to document.body when no container is configured.\n */\nexport const getPortalMountNode = (container?: PortalContainerInput): HTMLElement => {\n const resolved = getPortalContainer(container);\n\n if (resolved instanceof HTMLElement) {\n return resolved;\n }\n\n if (resolved instanceof ShadowRoot) {\n const target = getShadowRootSelectors()\n .map((selector) => resolved.querySelector<HTMLElement>(selector))\n .find(Boolean)\n ?? (resolved.host instanceof HTMLElement ? resolved.host : undefined);\n\n if (target) {\n return target;\n }\n }\n\n return document.body;\n};\n\nexport const getPortalTargetForAppend = (): HTMLElement | undefined => {\n const container = getPortalContainer();\n if (!container) {\n return undefined;\n }\n\n if (container instanceof HTMLElement) {\n return container;\n }\n\n const shadowRoot = container;\n return getShadowRootSelectors()\n .map((selector) => shadowRoot.querySelector<HTMLElement>(selector))\n .find(Boolean)\n ?? (shadowRoot.host instanceof HTMLElement ? shadowRoot.host : undefined);\n};\n","export type HostRequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport type HostRequestConfig = {\n data?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type HostSelectedElement = {\n id?: number;\n siteId?: number;\n label?: string;\n url?: string;\n [key: string]: unknown;\n};\n\nexport type HostElementSelectorOptions = {\n storageKey: string;\n sources?: string[];\n criteria?: Record<string, unknown>;\n multiSelect?: boolean;\n limit?: number | null;\n defaultSiteId?: number;\n autoFocusSearchBox?: boolean;\n showSiteMenu?: boolean;\n onShow?: () => void;\n onSelect: (elements: HostSelectedElement[]) => void;\n closeOtherModals?: boolean;\n};\n\nexport type PluginKitHostBridge = {\n request: <T = unknown>(method: HostRequestMethod, action: string, config?: HostRequestConfig) => Promise<T>;\n openElementSelector: (elementType: string, options: HostElementSelectorOptions) => void;\n formatDate: (date: Date) => string;\n getTimepickerOptions: () => Record<string, unknown>;\n getLocale: () => string;\n};\n\nlet hostBridge: Partial<PluginKitHostBridge> = {};\n\nexport const setHostBridge = (bridge: Partial<PluginKitHostBridge> = {}): void => {\n hostBridge = {\n ...hostBridge,\n ...bridge,\n };\n};\n\nexport const getHostBridge = (): Partial<PluginKitHostBridge> => {\n return hostBridge;\n};\n\nconst requireHostBridgeMethod = <K extends keyof PluginKitHostBridge>(\n methodName: K,\n): NonNullable<PluginKitHostBridge[K]> => {\n const method = hostBridge[methodName];\n\n if (!method) {\n throw new Error(`Plugin Kit host bridge method \"${String(methodName)}\" is required but was not configured.`);\n }\n\n return method as NonNullable<PluginKitHostBridge[K]>;\n};\n\nexport const hostRequest = async <T = unknown>(\n method: HostRequestMethod,\n action: string,\n config?: HostRequestConfig,\n): Promise<T> => {\n const request = requireHostBridgeMethod('request');\n return request(method, action, config);\n};\n\nexport const hostOpenElementSelector = (elementType: string, options: HostElementSelectorOptions): void => {\n const openElementSelector = requireHostBridgeMethod('openElementSelector');\n openElementSelector(elementType, options);\n};\n\nexport const hostFormatDate = (date: Date): string => {\n const formatDate = requireHostBridgeMethod('formatDate');\n return formatDate(date);\n};\n\nexport const hostGetTimepickerOptions = (): Record<string, unknown> => {\n const getTimepickerOptions = requireHostBridgeMethod('getTimepickerOptions');\n return getTimepickerOptions();\n};\n\nexport const hostGetLocale = (): string => {\n const getLocale = requireHostBridgeMethod('getLocale');\n return getLocale();\n};\n","/**\n * Collections utility for managing client-side collections of models\n */\n\n/**\n * Generates a unique client-side ID string\n * @param {string} [prefix='client'] - Optional prefix for the generated ID\n * @returns {string} A unique ID string in the format: prefix_timestamp_randomString\n */\nexport const generateId = (prefix = 'client'): string => {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n};\n\n/**\n * Normalize a collection by adding _id to each item that doesn't have one\n * @param {Array} collection - Array of items\n * @returns {Array} - Normalized collection with _id on each item\n */\nexport const normalizeCollection = (collection: any[] = []): any[] => {\n return collection.map((item) => {\n // If item already has _id, keep it (for client-side created items)\n if (item._id) {\n return item;\n }\n\n // Generate a client-side internal ID for server-side items\n return {\n ...item,\n _id: generateId(),\n };\n });\n};\n\n/**\n * Create a new collection item\n * @param {Object} itemData - Initial data for the new item\n * @returns {Object} - The new item\n */\nexport const createItem = (itemData: any = {}): any => {\n return {\n ...itemData,\n _id: generateId(),\n };\n};\n\n/**\n * Duplicate an existing item in a collection\n * @param {Array} collection - Current collection\n * @param {Object} item - Item to duplicate\n * @param {Function} transformCallback - Optional callback to transform the duplicated item\n * @returns {Object} - Updated collection with duplicated item\n */\nexport const duplicateItem = (collection: any[] = [], item: any, transformCallback: ((item: any) => any) | null = null): any[] => {\n // Create base duplicated item\n const duplicatedItem = {\n ...item,\n // Generate new client-side ID\n _id: generateId(),\n };\n\n // Apply custom transformation if provided\n const finalItem = transformCallback ? transformCallback(duplicatedItem) : duplicatedItem;\n\n return [...collection, finalItem];\n};\n\n/**\n * Delete a item from a collection\n * @param {Array} collection - Current collection\n * @param {Object} item - Item to delete\n * @returns {Object} - Updated collection without the deleted item\n */\nexport const deleteItem = (collection: any[] = [], itemToDelete: any): any[] => {\n return collection.filter((item) => { return item._id !== itemToDelete._id; });\n};\n\n/**\n * Update an item in a collection\n * @param {Array} collection - Current collection\n * @param {Object} item - Item to update\n * @param {Object} updates - Updates to apply to the item\n * @returns {Object} - Updated collection with updated item\n */\nexport const updateItem = (collection: any[] = [], itemToUpdate: any, updates: any): any[] => {\n return collection.map((item) => {\n if (item._id === itemToUpdate._id) {\n return {\n ...item,\n ...updates,\n // Preserve the _id\n _id: item._id,\n };\n }\n return item;\n });\n};\n\n/**\n * Move an item to a new position in a collection\n * @param {Array} collection - Current collection\n * @param {Object} fromItem - Item to move\n * @param {Object} toItem - Item to move to (insert before this item)\n * @returns {Array} - Updated collection with moved item\n */\nexport const moveItem = (collection: any[] = [], fromItem: any, toItem: any): any[] => {\n if (fromItem._id === toItem._id) {\n return collection;\n }\n\n const fromIndex = collection.findIndex((item) => { return item._id === fromItem._id; });\n const toIndex = collection.findIndex((item) => { return item._id === toItem._id; });\n\n if (fromIndex === -1 || toIndex === -1) {\n return collection;\n }\n\n const newCollection = [...collection];\n const [movedItem] = newCollection.splice(fromIndex, 1);\n newCollection.splice(toIndex, 0, movedItem);\n\n return newCollection;\n};\n\n/**\n * Find an item in a collection by _id\n * @param {Array} collection - Collection to search\n * @param {string} _id - Client-side ID to find\n * @returns {Object|null} - Found model or null\n */\nexport const findItemById = (collection: any[] = [], _id: string): any | null => {\n return collection.find((item) => { return item._id === _id; }) || null;\n};\n\n/**\n * Get all items that have server-side IDs (existing items)\n * @param {Array} collection - Collection to filter\n * @returns {Array} - Items with server-side IDs\n */\nexport const getExistingItems = (collection: any[] = []): any[] => {\n return collection.filter((item) => { return item.id; });\n};\n\n/**\n * Get all items that don't have server-side IDs (new items)\n * @param {Array} collection - Collection to filter\n * @returns {Array} - Items without server-side IDs\n */\nexport const getNewItems = (collection: any[] = []): any[] => {\n return collection.filter((item) => { return !item.id; });\n};\n\nexport const findRecursive = <T = any>(items: T[], predicate: (item: T) => boolean, optionsKey = 'options'): T | null => {\n for (const item of items) {\n // If this item has nested options, search recursively\n if ((item as any)[optionsKey] && Array.isArray((item as any)[optionsKey])) {\n const result = findRecursive((item as any)[optionsKey], predicate, optionsKey);\n\n if (result) {\n return result;\n }\n }\n\n // Check if this item matches the predicate\n if (predicate(item)) {\n return item;\n }\n }\n\n return null;\n};\n\n/**\n * Creates a deep clone of a value using JSON serialization\n * @param {any} value - The value to clone\n * @returns {any} A deep clone of the input value, or undefined if input is undefined\n */\nexport const clone = function <T>(value: T): T | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return JSON.parse(JSON.stringify(value));\n};\n","interface ErrorContent {\n heading: string;\n text: string;\n trace: string;\n traceAsString: string;\n traceAsArray: string[];\n}\n\ninterface ServerError {\n response?: {\n statusText?: string;\n data?: {\n message?: string;\n error?: string;\n file?: string;\n line?: string;\n trace?: Array<{\n file?: string;\n line?: string;\n }>;\n };\n };\n message?: string;\n stack?: string;\n}\n\nconst nl2br = (str: string): string => {\n return str.replace(/\\n/g, '<br>');\n};\n\nconst getErrorHeading = (error: ServerError): string => {\n // Server error status text (e.g., \"Internal Server Error\", \"Bad Request\")\n if (error.response?.statusText) {\n return error.response.statusText;\n }\n\n // Network errors or other client-side errors\n if (error.message?.includes('Network Error')) {\n return 'Network Error';\n }\n\n if (error.message?.includes('timeout')) {\n return 'Request Timeout';\n }\n\n // Default fallback\n return 'An error has occurred';\n};\n\nconst getErrorText = (error: ServerError): string => {\n // Server-side error messages\n if (error.response?.data?.message) {\n return error.response.data.message;\n }\n\n if (error.response?.data?.error) {\n return error.response.data.error;\n }\n\n // Client-side error messages\n if (error.message) {\n return error.message;\n }\n\n // Fallback to string representation\n return String(error);\n};\n\nconst getErrorTrace = (error: ServerError, maxTraceLines: number = 5): { traces: string[], traceAsString: string } => {\n const traces: string[] = [];\n\n // Server-side file and line information\n const file1 = error.response?.data?.file;\n const line1 = error.response?.data?.line;\n\n if (file1 && line1) {\n traces.push(`${file1}:${line1}`);\n }\n\n // Server-side stack trace (up to maxTraceLines)\n const traceArray = error.response?.data?.trace || [];\n\n for (let i = 0; i < Math.min(maxTraceLines, traceArray.length); i++) {\n const traceItem = traceArray[i];\n\n if (traceItem?.file && traceItem?.line) {\n traces.push(`${traceItem.file}:${traceItem.line}`);\n }\n }\n\n // Client-side stack trace - only if there's no server-side trace\n if (error.stack && traces.length === 0) {\n traces.push(error.stack);\n }\n\n return {\n traces,\n traceAsString: traces.map(nl2br).join('<br>'),\n };\n};\n\nexport const getErrorMessage = function(error: ServerError, maxTraceLines: number = 5): ErrorContent {\n const { traces, traceAsString } = getErrorTrace(error, maxTraceLines);\n\n return {\n heading: getErrorHeading(error),\n text: getErrorText(error),\n trace: traceAsString, // Keep for backward compatibility\n traceAsString,\n traceAsArray: traces,\n };\n};\n","/**\n * Convert a string to a handle format\n * @param {string} sourceValue - The source string to convert\n * @param {string} handleCasing - The casing format ('camelCase', 'pascal', 'snake', 'kebab')\n * @param {boolean} allowNonAlphaStart - Whether to allow non-alphabetic characters at the start\n * @returns {string} The generated handle\n */\nexport const generateHandle = function(sourceValue: string, handleCasing: string = 'camelCase', allowNonAlphaStart: boolean = false): string {\n // Remove HTML tags\n let handle = sourceValue.replace('/<(.*?)>/g', '');\n\n // Remove inner-word punctuation\n\n handle = handle.replace(/['\"'\"\"\\[\\]\\(\\)\\{\\}:]/g, '');\n\n // Make it lowercase\n handle = handle.toLowerCase();\n\n // Convert extended ASCII characters to basic ASCII\n handle = (window as any).Craft.asciiString(handle);\n\n if (!allowNonAlphaStart) {\n // Handle must start with a letter\n handle = handle.replace(/^[^a-z]+/, '');\n }\n\n // Get the \"words\"\n const words = (window as any).Craft.filterArray(handle.split(/[^a-z0-9]+/));\n handle = '';\n\n if (handleCasing === 'snake') {\n return words.join('_');\n }\n\n if (handleCasing === 'kebab') {\n return words.join('-');\n }\n\n // Make it camelCase\n for (let i = 0; i < words.length; i++) {\n if (handleCasing !== 'pascal' && i === 0) {\n handle += words[i];\n } else {\n handle += words[i].charAt(0).toUpperCase() + words[i].substr(1);\n }\n }\n\n return handle;\n};\n\n/**\n * Find a unique handle by checking against reserved handles and adding suffixes\n * @param {string} baseHandle - The base handle to check\n * @param {Array} allReservedHandles - Array of all reserved handles to check against (static + dynamic)\n * @returns {string} A unique handle\n */\nexport const findUniqueHandle = (baseHandle: string, allReservedHandles: string[] = []): string => {\n if (!baseHandle) { return ''; }\n\n let handle = baseHandle;\n let counter = 1;\n\n // Keep adding numbers until we find a unique handle\n while (allReservedHandles.includes(handle)) {\n handle = `${baseHandle}${counter}`;\n counter++;\n }\n\n return handle;\n};\n","import { findUniqueHandle, generateHandle } from './string';\n\n/** Minimal dot/bracket path getter so this stays dependency-free (no lodash). */\nconst getByPath = (source: unknown, path: string): unknown => {\n if (source == null || typeof source !== 'object' || !path) {\n return undefined;\n }\n\n const segments = path.replace(/\\[(\\d+)\\]/g, '.$1').split('.').filter(Boolean);\n let current: unknown = source;\n\n for (const segment of segments) {\n if (current == null || typeof current !== 'object') {\n return undefined;\n }\n\n current = (current as Record<string, unknown>)[segment];\n }\n\n return current;\n};\n\nconst normalizeHandleSource = (value: unknown): string => {\n if (value == null) {\n return '';\n }\n\n return String(value)\n // Strip variable/template tokens so handle generation uses human text only.\n .replace(/\\{[^}]*\\}/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n};\n\n/**\n * Resolve dynamic reserved handles from other field values (e.g. a sibling field whose\n * value would collide once slugified).\n */\nexport const getDynamicReservedHandles = (\n values: Record<string, unknown>,\n reservedFieldValues: string[] = [],\n): string[] => {\n const dynamicHandles: string[] = [];\n\n reservedFieldValues.forEach((fieldPath) => {\n const value = getByPath(values, fieldPath);\n\n if (value && typeof value === 'string') {\n const handleValue = generateHandle(normalizeHandleSource(value));\n\n if (handleValue) {\n dynamicHandles.push(handleValue);\n }\n }\n });\n\n return dynamicHandles;\n};\n\nconst truncateHandle = (handle: string, maxLength?: number): string => {\n if (!Number.isFinite(maxLength)) {\n return handle;\n }\n\n const length = Math.max(Number(maxLength), 0);\n return handle.slice(0, length);\n};\n\nconst findUniqueHandleWithinMaxLength = (\n baseHandle: string,\n reservedHandles: string[] = [],\n maxLength?: number,\n): string => {\n if (!baseHandle) {\n return '';\n }\n\n if (!Number.isFinite(maxLength)) {\n return findUniqueHandle(baseHandle, reservedHandles);\n }\n\n const normalizedReserved = new Set((reservedHandles || []).map((handle) => {\n return String(handle || '').toLowerCase();\n }));\n\n const truncatedBase = truncateHandle(baseHandle, maxLength);\n if (!truncatedBase) {\n return '';\n }\n\n if (!normalizedReserved.has(truncatedBase.toLowerCase())) {\n return truncatedBase;\n }\n\n let suffix = 1;\n\n while (suffix < 10000) {\n const suffixText = String(suffix);\n const baseMaxLength = Math.max(Number(maxLength) - suffixText.length, 0);\n const truncatedWithSuffix = `${truncatedBase.slice(0, baseMaxLength)}${suffixText}`;\n\n if (!normalizedReserved.has(truncatedWithSuffix.toLowerCase())) {\n return truncatedWithSuffix;\n }\n\n suffix += 1;\n }\n\n return truncatedBase;\n};\n\n/**\n * Generate a unique handle from a human-readable source value, honouring reserved handles\n * (static + dynamically derived from other field values) and an optional max length.\n */\nexport const buildUniqueHandleFromSource = ({\n sourceValue,\n values = {},\n reservedHandles = [],\n reservedFieldValues = [],\n maxLength,\n}: {\n sourceValue: unknown;\n values?: Record<string, unknown>;\n reservedHandles?: string[];\n reservedFieldValues?: string[];\n maxLength?: number;\n}): string => {\n const baseHandle = generateHandle(normalizeHandleSource(sourceValue));\n const dynamicHandles = getDynamicReservedHandles(values, reservedFieldValues);\n const allReservedHandles = [...reservedHandles, ...dynamicHandles];\n\n return findUniqueHandleWithinMaxLength(baseHandle, allReservedHandles, maxLength);\n};\n","import MarkdownIt from 'markdown-it';\n\n/**\n * Initialize markdown-it instance with secure defaults and common options\n * - HTML is disabled for security\n * - Links are auto-detected\n * - Typography features like smart quotes are enabled\n * - Line breaks are converted to <br> tags\n */\nconst md = new MarkdownIt({\n html: false, // Disable HTML for security\n linkify: true, // Auto-detect links\n typographer: true, // Enable typographic replacements\n breaks: true, // Convert line breaks to <br>\n});\n\n/**\n * Renders markdown content as block-level HTML\n * Includes block elements like headers, paragraphs, lists etc.\n *\n * @param content - The markdown string to render\n * @returns Rendered HTML string, or empty string if no content provided\n */\nexport const renderMarkdown = (content: string): string => {\n if (!content) { return ''; }\n\n return md.render(content);\n};\n\n/**\n * Renders markdown content as inline HTML only\n * Excludes block-level elements, only processes inline markdown syntax\n *\n * @param content - The markdown string to render\n * @returns Rendered HTML string, or empty string if no content provided\n */\nexport const renderInlineMarkdown = (content: string): string => {\n if (!content) { return ''; }\n\n return md.renderInline(content);\n};\n\n/**\n * Export the configured markdown-it instance for direct usage\n * Allows access to the full markdown-it API if needed\n */\nexport { md };\n","/**\n * Creates a function that ensures a promise takes at least a minimum amount of time to resolve\n *\n * @param ms - The minimum time in milliseconds that the promise should take\n * @returns A function that wraps a promise or promise-returning function\n * @example\n * ```ts\n * const slowFetch = takeAtLeast(1000)(fetch('https://api.example.com'));\n * // Will take at least 1 second even if the fetch is faster\n * ```\n */\nexport const takeAtLeast = function(ms: number) {\n /**\n * Wraps a promise or promise-returning function to ensure minimum execution time\n *\n * @param promiseOrFn - A promise or a function that returns a promise\n * @returns A promise that resolves with the original promise's value after at least `ms` milliseconds\n * @throws Will throw if the original promise rejects\n */\n return function <T>(promiseOrFn: Promise<T> | (() => Promise<T>)): Promise<T> {\n const promise = typeof promiseOrFn === 'function' ? promiseOrFn() : promiseOrFn;\n const delay = new Promise<void>((resolve) => { return setTimeout(resolve, ms); });\n\n return Promise.allSettled([promise, delay]).then((results) => {\n const [promiseResult] = results;\n\n if (promiseResult.status === 'rejected') {\n throw promiseResult.reason;\n }\n\n return promiseResult.value;\n });\n };\n};\n","export const getQueryParam = (key: string): string | null => {\n const urlParams = new URLSearchParams(window.location.search);\n return urlParams.get(key);\n};\n\nexport const setQueryParam = (key: string, value: string): void => {\n const url = new URL(window.location.href);\n url.searchParams.set(key, value);\n window.history.replaceState({}, '', url.toString());\n};\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export default {
2
+ singleQuote: true,
3
+ semi: true,
4
+ tabWidth: 4,
5
+ useTabs: false,
6
+ trailingComma: 'all',
7
+ bracketSpacing: true,
8
+ arrowParens: 'always',
9
+ endOfLine: 'lf',
10
+ };