diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 896ae19ee..bb559f83f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,13 +37,19 @@ Thank you for your interest in contributing to GrapesJS! We welcome all types of pnpm install ``` -5. Start the development server: +5. Run the build script: + + ```bash + pnpm run build + ``` + +6. Start the development server: ```bash pnpm start ``` -6. Open `http://localhost:8080/` in your browser to see the editor in action. +7. Open `http://localhost:8080/` in your browser to see the editor in action. ## Development Workflow diff --git a/docs/README.md b/docs/README.md index 57dc78734..2ccdf9689 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,13 @@ [[toc]] +::: tip + +Supercharge your web builder with the [Grapes Studio SDK](https://app.grapesjs.com/docs-sdk/overview/getting-started) — a customizable GrapesJS experience, complete with a polished UI that’s ready to embed. + +::: + + ## What is GrapesJS? At first glance one might think this is just another page/HTML builder, but it's something more. GrapesJS is a multi-purpose, Web Builder Framework, which means it allows you to easily create a drag & drop enabled builder of "things". By "things" we mean anything with HTML-like structure, which entails much more than web pages. We use HTML-like structure basically everywhere: Newsletters (eg. [MJML](https://mjml.io/)), Native Mobile Applications (eg. [React Native](https://github.com/facebook/react-native)), Native Desktop Applications (eg. [Vuido](https://vuido.mimec.org)), PDFs (eg. [React PDF](https://github.com/diegomura/react-pdf)), etc. So, for everything you can imagine as a set of elements like `... other nested elements ...` you can create easily a GrapesJS builder around it and then use it independently in your applications. diff --git a/docs/getting-started.md b/docs/getting-started.md index 780d2873a..f53dd88a8 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -10,6 +10,12 @@ meta: This is a step-by-step guide for anyone who wants to create their own builder with GrapesJS. This is not a comprehensive guide, just a concise overview of the most common modules. Follow along to create a page builder from scratch. Skip to the end of this page to see the [final result](#final-result). +::: tip + +Looking for a customizable version of GrapesJS with an embeddable, production-ready UI? [Explore the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/overview/getting-started) + +::: + ## Import the library Before you start using GrapesJS, you'll have to import it. Let's import the latest version: diff --git a/docs/modules/Assets.md b/docs/modules/Assets.md index 61669da79..f6fb5c681 100644 --- a/docs/modules/Assets.md +++ b/docs/modules/Assets.md @@ -8,6 +8,10 @@ title: Asset Manager In this section, you will see how to setup and take the full advantage of built-in Asset Manager in GrapesJS. The Asset Manager is lightweight and implements just an `image` in its core, but as you'll see next it's easy to extend and create your own asset types. +::: tip +Want an asset manager that looks great out of the box? [Try the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/configuration/assets/overview?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## Configuration diff --git a/docs/modules/Blocks.md b/docs/modules/Blocks.md index 29c4c2c12..a0bf00100 100644 --- a/docs/modules/Blocks.md +++ b/docs/modules/Blocks.md @@ -16,6 +16,10 @@ To get a better understanding of the content in this guide, we recommend reading This guide is referring to GrapesJS v0.17.27 or higher ::: +::: tip +Need a sleek block UI that’s easy to extend and customize? [Explore the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/configuration/blocks?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## Configuration diff --git a/docs/modules/Components-js.md b/docs/modules/Components-js.md index 7803d8c64..f3c281fd7 100644 --- a/docs/modules/Components-js.md +++ b/docs/modules/Components-js.md @@ -11,6 +11,10 @@ This guide is referring to GrapesJS v0.16.34 or higher.

To get a better understanding of the content in this guide, we recommend reading [Components](Components.html) and [Traits] first ::: +::: tip +Prefer a modern UI that's production-ready? [Get started with the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/configuration/components/overview?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## Basic scripts diff --git a/docs/modules/Components.md b/docs/modules/Components.md index 47e23c8d9..7e1787b2d 100644 --- a/docs/modules/Components.md +++ b/docs/modules/Components.md @@ -10,6 +10,10 @@ The Component is a base element of the template. It might be something simple an This guide is referring to GrapesJS v0.15.8 or higher ::: +::: tip +Skip the boilerplate—use a refined component editor out of the box. [Checkout the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/configuration/components/overview?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## How Components work? diff --git a/docs/modules/Pages.md b/docs/modules/Pages.md index 5de374ed3..8e5298044 100644 --- a/docs/modules/Pages.md +++ b/docs/modules/Pages.md @@ -10,6 +10,9 @@ The Pages module in GrapesJS allows you to create a project with multiple pages. This guide is referring to GrapesJS v0.21.1 or higher ::: +::: tip +Want pages to just work, with a polished UI? [See how the Grapes Studio SDK does it!](https://app.grapesjs.com/docs-sdk/configuration/pages?utm_source=grapesjs-docs&utm_medium=tip) +::: [[toc]] ## Initialization diff --git a/docs/modules/Plugins.md b/docs/modules/Plugins.md index 5c1fff8b8..18b541d34 100644 --- a/docs/modules/Plugins.md +++ b/docs/modules/Plugins.md @@ -10,6 +10,10 @@ Creating plugins in GrapesJS is pretty straightforward and here you'll get how t This guide is referring to GrapesJS v0.21.2 or higher ::: +::: tip +Looking for plugins that are tested, verified, and built to scale? [Browse them all in the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/plugins/overview?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## Basic plugin diff --git a/docs/modules/Storage.md b/docs/modules/Storage.md index 9c9dc8078..553d684d3 100644 --- a/docs/modules/Storage.md +++ b/docs/modules/Storage.md @@ -10,6 +10,10 @@ The Storage Manager is a built-in module that allows the persistence of your pro This guide requires GrapesJS v0.19.\* or higher ::: +::: tip +Need more powerful and customizable storage options? [The Grapes Studio SDK has you covered.](https://app.grapesjs.com/docs-sdk/configuration/projects?utm_source=grapesjs-docs&utm_medium=tip#storage) +::: + [[toc]] ## Configuration diff --git a/docs/modules/Style-manager.md b/docs/modules/Style-manager.md index f903b4a68..cc6efce7a 100644 --- a/docs/modules/Style-manager.md +++ b/docs/modules/Style-manager.md @@ -16,6 +16,10 @@ To get a better understanding of the content in this guide, we recommend reading This guide is referring to GrapesJS v0.18.1 or higher ::: +::: tip +Looking for a UI that is easy and ready to customize? [Checkout the Grapes Studio SDK!](https://app.grapesjs.com/docs-sdk/configuration/components/overview?utm_source=grapesjs-docs&utm_medium=tip) +::: + [[toc]] ## Configuration diff --git a/docs/modules/Traits.md b/docs/modules/Traits.md index 567240c64..e70b4880a 100644 --- a/docs/modules/Traits.md +++ b/docs/modules/Traits.md @@ -11,6 +11,10 @@ This guide is referring to GrapesJS v0.21.9 or higher.

To get a better understanding of the content in this guide we recommend reading [Components](Components.html) first ::: +::: tip +Want traits that look great and work out of the box? [See how the Grapes Studio SDK handles it.](https://app.grapesjs.com/docs-sdk/configuration/components/properties?utm_source=grapesjs-docs&utm_medium=tip#traits) +::: + [[toc]] ## Add Traits to Components diff --git a/package.json b/package.json index 9d1357a7d..d09fddb3f 100644 --- a/package.json +++ b/package.json @@ -47,14 +47,14 @@ "eslint-config-standard-with-typescript": "43.0.1", "eslint-plugin-import": "2.29.1", "eslint-plugin-jest": "28.8.3", - "eslint-plugin-n": "17.10.2", + "eslint-plugin-n": "17.17.0", "eslint-plugin-prettier": "5.2.1", "eslint-plugin-promise": "7.1.0", "eslint-plugin-react-hooks": "4.6.2", "jest": "29.7.0", "prettier": "3.3.3", "ts-jest": "29.2.4", - "ts-loader": "9.5.1", + "ts-loader": "9.5.2", "ts-node": "10.9.2", "typescript": "5.5.4" }, diff --git a/packages/cli/package.json b/packages/cli/package.json index 03263a04d..ba33a61f1 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -29,7 +29,7 @@ "license": "BSD-3-Clause", "dependencies": { "@babel/core": "7.25.2", - "@babel/plugin-transform-runtime": "7.25.4", + "@babel/plugin-transform-runtime": "7.26.10", "@babel/preset-env": "7.25.4", "@babel/runtime": "7.25.6", "babel-loader": "9.1.3", diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index 2afb77f0b..71d8a0819 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -52,10 +52,15 @@ export const buildLocale = async (opts: BuildOptions = {}) => { const babelOpts = { ...babelConfig(buildWebpackArgs(opts) as any) }; fs.readdirSync(localDst).forEach((file) => { const filePath = `${localDst}/${file}`; + const esModuleFileName = filePath.replace(/\.[^.]+$/, '.mjs'); + fs.copyFileSync(filePath, esModuleFileName); const compiled = transformFileSync(filePath, babelOpts).code; fs.writeFileSync(filePath, compiled); }); + // Remove the index.mjs as it is useless + fs.unlinkSync(`${localDst}/index.mjs`); + printRow('Locale files building completed successfully!'); }; diff --git a/packages/core/src/canvas/index.ts b/packages/core/src/canvas/index.ts index 3e4aca716..9169d565c 100644 --- a/packages/core/src/canvas/index.ts +++ b/packages/core/src/canvas/index.ts @@ -515,7 +515,7 @@ export default class CanvasModule extends Module { * @return {Object} * @private */ - getMouseRelativeCanvas(ev: MouseEvent | { clientX: number; clientY: number }, opts: any) { + getMouseRelativeCanvas(ev: MouseEvent | { clientX: number; clientY: number }, opts?: Record) { const zoom = this.getZoomDecimal(); const canvasView = this.getCanvasView(); const canvasPos = canvasView.getPosition(opts) ?? { top: 0, left: 0 }; diff --git a/packages/core/src/commands/config/config.ts b/packages/core/src/commands/config/config.ts index 9712308cd..3f1822bb3 100644 --- a/packages/core/src/commands/config/config.ts +++ b/packages/core/src/commands/config/config.ts @@ -1,4 +1,9 @@ -import { CommandObject } from '../view/CommandAbstract'; +import type { CommandObject, CommandOptions } from '../view/CommandAbstract'; + +interface CommandConfigDefaultOptions { + run?: (options: CommandOptions) => CommandOptions; + stop?: (options: CommandOptions) => CommandOptions; +} export interface CommandsConfig { /** @@ -19,12 +24,40 @@ export interface CommandsConfig { * @default true */ strict?: boolean; + + /** + * Default options for commands + * These options will be merged with the options passed when the command is run. + * This allows you to define common behavior for commands in one place. + * @default {} + * @example + * defaultOptions: { + * 'core:component-drag': { + * run: (options: Record) => ({ + * ...options, + * skipGuidesRender: true, + * addStyle({ component, styles, partial }) { + * component.addStyle(styles, { partial }); + * }, + * }), + * stop: (options: Record) => ({ + * ...options, + * * skipGuidesRender: true, + * addStyle({ component, styles, partial }) { + * component.addStyle(styles, { partial }); + * }, + * }), + * } + * } + */ + defaultOptions?: Record; } const config: () => CommandsConfig = () => ({ stylePrefix: 'com-', defaults: {}, strict: true, + defaultOptions: {}, }); export default config; diff --git a/packages/core/src/commands/index.ts b/packages/core/src/commands/index.ts index c1cf426c9..a43f88b4f 100644 --- a/packages/core/src/commands/index.ts +++ b/packages/core/src/commands/index.ts @@ -389,6 +389,8 @@ export default class CommandsModule extends Module this.guidesStatic, - guidesTarget: () => this.guidesTarget, - ...dragger, + guidesStatic: () => this.guidesStatic ?? [], + guidesTarget: () => this.guidesTarget ?? [], + ...(opts.dragger ?? {}), }; this.setupGuides(); this.opts = opts; this.editor = editor; this.em = editor.getModel(); - this.target = target; - this.isTran = mode == 'translate'; + this.target = opts.target; + this.isTran = opts.mode == 'translate'; this.guidesContainer = this.getGuidesContainer(); this.guidesTarget = this.getGuidesTarget(); this.guidesStatic = this.getGuidesStatic(); + let drg = this.dragger; if (!drg) { @@ -60,19 +57,22 @@ export default { drg.setOptions(config); } - event && drg.start(event); - this.toggleDrag(1); + opts.event && drg.start(opts.event); + this.toggleDrag(true); this.em.trigger(`${evName}:start`, this.getEventOpts()); return drg; }, getEventOpts() { + const guidesActive = this.guidesTarget?.filter((item) => item.active) ?? []; return { mode: this.opts.mode, + component: this.target, target: this.target, guidesTarget: this.guidesTarget, guidesStatic: this.guidesStatic, + guidesMatched: this.getGuidesMatched(guidesActive), }; }, @@ -81,9 +81,9 @@ export default { }, setupGuides() { - (this.guides || []).forEach((item: any) => { + (this.guides ?? []).forEach((item) => { const { guide } = item; - guide && guide.parentNode.removeChild(guide); + guide?.parentNode?.removeChild(guide); }); this.guides = []; }, @@ -93,7 +93,7 @@ export default { if (!guidesEl) { const { editor, em, opts } = this; - const pfx = editor.getConfig().stylePrefix; + const pfx = editor.getConfig().stylePrefix ?? ''; const elInfoX = document.createElement('div'); const elInfoY = document.createElement('div'); const guideContent = `
@@ -107,18 +107,18 @@ export default { elInfoY.innerHTML = guideContent; guidesEl.appendChild(elInfoX); guidesEl.appendChild(elInfoY); - editor.Canvas.getGlobalToolsEl().appendChild(guidesEl); + editor.Canvas.getGlobalToolsEl()?.appendChild(guidesEl); this.guidesEl = guidesEl; this.elGuideInfoX = elInfoX; this.elGuideInfoY = elInfoY; - this.elGuideInfoContentX = elInfoX.querySelector(`.${pfx}guide-info__content`); - this.elGuideInfoContentY = elInfoY.querySelector(`.${pfx}guide-info__content`); + this.elGuideInfoContentX = elInfoX.querySelector(`.${pfx}guide-info__content`) ?? undefined; + this.elGuideInfoContentY = elInfoY.querySelector(`.${pfx}guide-info__content`) ?? undefined; em.on( 'canvas:update frame:scroll', debounce(() => { this.updateGuides(); - opts.debug && this.guides?.forEach((item: any) => this.renderGuide(item)); + opts.debug && this.guides?.forEach((item) => this.renderGuide(item)); }, 200), ); } @@ -127,32 +127,39 @@ export default { }, getGuidesStatic() { - let result: any = []; + let result: Guide[] = []; const el = this.target.getEl(); - const { parentNode = {} } = el; - each(parentNode.children, (item) => (result = result.concat(el !== item ? this.getElementGuides(item) : []))); + const parentNode = el?.parentElement; + if (!parentNode) return []; + each( + parentNode.children, + (item) => (result = result.concat(el !== item ? this.getElementGuides(item as HTMLElement) : [])), + ); return result.concat(this.getElementGuides(parentNode)); }, getGuidesTarget() { - return this.getElementGuides(this.target.getEl()); + return this.getElementGuides(this.target.getEl()!); }, - updateGuides(guides: any) { - let lastEl: any; - let lastPos: any; - (guides || this.guides).forEach((item: any) => { + updateGuides(guides) { + let lastEl: HTMLElement; + let lastPos: ComponentOrigRect; + const guidesToUpdate = guides ?? this.guides ?? []; + guidesToUpdate.forEach((item) => { const { origin } = item; const pos = lastEl === origin ? lastPos : this.getElementPos(origin); lastEl = origin; lastPos = pos; - each(this.getGuidePosUpdate(item, pos), (val, key) => (item[key] = val)); + each(this.getGuidePosUpdate(item, pos), (val, key) => { + (item as Record)[key] = val; + }); item.originRect = pos; }); }, - getGuidePosUpdate(item: any, rect: any) { + getGuidePosUpdate(item, rect) { const result: { x?: number; y?: number } = {}; const { top, height, left, width } = rect; @@ -180,16 +187,17 @@ export default { return result; }, - renderGuide(item: any = {}) { - const el = item.guide || document.createElement('div'); + renderGuide(item) { + if (this.opts.skipGuidesRender) return; + const el = item.guide ?? document.createElement('div'); const un = 'px'; const guideSize = item.active ? 2 : 1; - let numEl = el.children[0]; - el.style = `position: absolute; background-color: ${item.active ? 'green' : 'red'};`; + + el.style.cssText = `position: absolute; background-color: ${item.active ? 'green' : 'red'};`; if (!el.children.length) { - numEl = document.createElement('div'); - numEl.style = 'position: absolute; color: red; padding: 5px; top: 0; left: 0;'; + const numEl = document.createElement('div'); + numEl.style.cssText = 'position: absolute; color: red; padding: 5px; top: 0; left: 0;'; el.appendChild(numEl); } @@ -197,7 +205,7 @@ export default { el.style.width = '100%'; el.style.height = `${guideSize}${un}`; el.style.top = `${item.y}${un}`; - el.style.left = 0; + el.style.left = '0'; } else { el.style.width = `${guideSize}${un}`; el.style.height = '100%'; @@ -205,38 +213,52 @@ export default { el.style.top = `0${un}`; } - !item.guide && this.guidesContainer.appendChild(el); + !item.guide && this.guidesContainer?.appendChild(el); return el; }, - getElementPos(el: HTMLElement) { + getElementPos(el) { return this.editor.Canvas.getElementPos(el, { noScroll: 1 }); }, - getElementGuides(el: HTMLElement) { + getElementGuides(el) { const { opts } = this; + const origin = el; const originRect = this.getElementPos(el); + const component = getComponentModel(el); + const componentView = getComponentView(el); + const { top, height, left, width } = originRect; - // @ts-ignore - const guides: Guide[] = [ + const guidePoints: { type: string; x?: number; y?: number }[] = [ { type: 't', y: top }, // Top { type: 'b', y: top + height }, // Bottom { type: 'l', x: left }, // Left { type: 'r', x: left + width }, // Right { type: 'x', x: left + width / 2 }, // Mid x { type: 'y', y: top + height / 2 }, // Mid y - ].map((item) => ({ - ...item, - origin: el, - originRect, - guide: opts.debug && this.renderGuide(item), - })); - guides.forEach((item) => this.guides?.push(item)); + ]; + + const guides = guidePoints.map((guidePoint) => { + const guide = opts.debug ? this.renderGuide(guidePoint) : undefined; + return { + ...guidePoint, + component, + componentView, + componentEl: origin, + origin, + componentElRect: originRect, + originRect, + guideEl: guide, + guide, + }; + }) as Guide[]; + + guides.forEach((guidePoint) => this.guides?.push(guidePoint)); return guides; }, - getTranslate(transform: string, axis = 'x') { + getTranslate(transform, axis = 'x') { let result = 0; (transform || '').split(' ').forEach((item) => { const itemStr = item.trim(); @@ -246,7 +268,7 @@ export default { return result; }, - setTranslate(transform: string, axis: string, value: string) { + setTranslate(transform, axis, value) { const fn = `translate${axis.toUpperCase()}(`; const val = `${fn}${value})`; let result = (transform || '') @@ -264,35 +286,39 @@ export default { getPosition() { const { target, isTran } = this; - const { left, top, transform } = target.getStyle(); + const targetStyle = target.getStyle(); + + const transform = targetStyle.transform as string | undefined; + const left = targetStyle.left as string | undefined; + const top = targetStyle.top as string | undefined; + let x = 0; let y = 0; - if (isTran) { + if (isTran && transform) { x = this.getTranslate(transform); y = this.getTranslate(transform, 'y'); } else { - x = parseFloat(left || 0); - y = parseFloat(top || 0); + x = parseFloat(left ?? '0'); + y = parseFloat(top ?? '0'); } return { x, y }; }, - setPosition({ x, y, end, position, width, height }: any) { - const { target, isTran, em } = this; + setPosition({ x, y, end, position, width, height }) { + const { target, isTran, em, opts } = this; const unit = 'px'; const __p = !end; // Indicate if partial change - const left = `${parseInt(x, 10)}${unit}`; - const top = `${parseInt(y, 10)}${unit}`; + const left = `${parseInt(`${x}`, 10)}${unit}`; + const top = `${parseInt(`${y}`, 10)}${unit}`; let styleUp = {}; if (isTran) { - let transform = target.getStyle()['transform'] || ''; + let transform = (target.getStyle()?.transform ?? '') as string; transform = this.setTranslate(transform, 'x', left); transform = this.setTranslate(transform, 'y', top); styleUp = { transform, __p }; - target.addStyle(styleUp, { avoidStore: !end }); } else { const adds: any = { position, width, height }; const style: any = { left, top, __p }; @@ -301,10 +327,15 @@ export default { if (prop) style[add] = prop; }); styleUp = style; + } + + if (opts.addStyle) { + opts.addStyle({ component: target, styles: styleUp, partial: !end }); + } else { target.addStyle(styleUp, { avoidStore: !end }); } - em?.Styles.__emitCmpStyleUpdate(styleUp, { components: em.getSelected() }); + em.Styles.__emitCmpStyleUpdate(styleUp, { components: em.getSelected() }); }, _getDragData() { @@ -316,35 +347,37 @@ export default { }; }, - onStart(event: Event) { + onStart(event) { const { target, editor, isTran, opts } = this; - const { center, onStart } = opts; const { Canvas } = editor; const style = target.getStyle(); const position = 'absolute'; const relPos = [position, 'relative']; - onStart && onStart(this._getDragData()); + opts.onStart?.(this._getDragData()); if (isTran) return; if (style.position !== position) { - let { left, top, width, height } = Canvas.offset(target.getEl()); + let { left, top, width, height } = Canvas.offset(target.getEl()!); let parent = target.parent(); - let parentRel; + let parentRel = null; // Check for the relative parent do { - const pStyle = parent.getStyle(); - parentRel = relPos.indexOf(pStyle.position) >= 0 ? parent : null; - parent = parent.parent(); + const pStyle = parent?.getStyle(); + const position = pStyle?.position as string | undefined; + if (position) { + parentRel = relPos.indexOf(position) >= 0 ? parent : null; + } + parent = parent?.parent(); } while (parent && !parentRel); // Center the target to the pointer position (used in Droppable for Blocks) - if (center) { - const { x, y } = Canvas.getMouseRelativeCanvas(event); + if (opts.center) { + const { x, y } = Canvas.getMouseRelativeCanvas(event as MouseEvent); left = x; top = y; } else if (parentRel) { - const offsetP = Canvas.offset(parentRel.getEl()); + const offsetP = Canvas.offset(parentRel.getEl()!); left = left - offsetP.left; top = top - offsetP.top; } @@ -357,102 +390,167 @@ export default { position, }); } + + // Recalculate guides to avoid issues with the new position durin the first drag + this.guidesStatic = this.getGuidesStatic(); }, - onDrag(...args: any) { + onDrag() { const { guidesTarget, opts } = this; - const { onDrag } = opts; + this.updateGuides(guidesTarget); - opts.debug && guidesTarget.forEach((item: any) => this.renderGuide(item)); - opts.guidesInfo && this.renderGuideInfo(guidesTarget.filter((item: any) => item.active)); - onDrag && onDrag(this._getDragData()); + opts.debug && guidesTarget?.forEach((item) => this.renderGuide(item)); + opts.guidesInfo && this.renderGuideInfo(guidesTarget?.filter((item) => item.active) ?? []); + opts.onDrag?.(this._getDragData()); + + this.em.trigger(`${evName}:move`, this.getEventOpts()); }, - onEnd(ev: Event, dragger: any, opt = {}) { + onEnd(ev, _dragger, opt) { const { editor, opts, id } = this; - const { onEnd } = opts; - onEnd && onEnd(ev, opt, { event: ev, ...opt, ...this._getDragData() }); - editor.stopCommand(id); + opts.onEnd?.(ev, opt, { event: ev, ...opt, ...this._getDragData() }); + editor.stopCommand(`${id}`); this.hideGuidesInfo(); + this.em.trigger(`${evName}:end`, this.getEventOpts()); }, hideGuidesInfo() { ['X', 'Y'].forEach((item) => { - const guide = this[`elGuideInfo${item}`]; + const guide = this[`elGuideInfo${item}` as ElGuideInfoKey]; if (guide) guide.style.display = 'none'; }); }, - /** - * Render guides with spacing information - */ - renderGuideInfo(guides: Guide[] = []) { - const { guidesStatic } = this; + renderGuideInfo(guides = []) { this.hideGuidesInfo(); - guides.forEach((item) => { - const { origin, x } = item; - const rectOrigin = this.getElementPos(origin); - const axis = isUndefined(x) ? 'y' : 'x'; - const isY = axis === 'y'; - const origEdge1 = rectOrigin[isY ? 'left' : 'top']; - const origEdge1Raw = rectOrigin.rect[isY ? 'left' : 'top']; - const origEdge2 = isY ? origEdge1 + rectOrigin.width : origEdge1 + rectOrigin.height; - const origEdge2Raw = isY ? origEdge1Raw + rectOrigin.rect.width : origEdge1Raw + rectOrigin.rect.height; - const elGuideInfo = this[`elGuideInfo${axis.toUpperCase()}`]; - const elGuideInfoCnt = this[`elGuideInfoContent${axis.toUpperCase()}`]; - const guideInfoStyle = elGuideInfo.style; - - // Find the nearest element - const res = guidesStatic - ?.filter((stat) => stat.type === item.type) - .map((stat) => { - const { left, width, top, height } = stat.originRect; + + const guidesMatched = this.getGuidesMatched(guides); + + guidesMatched.forEach((guideMatched) => { + if (!this.opts.skipGuidesRender) { + this.renderSingleGuideInfo(guideMatched); + } + + this.em.trigger(`${evName}:active`, { + ...this.getEventOpts(), + ...guideMatched, + }); + }); + }, + + renderSingleGuideInfo(guideMatched) { + const { posFirst, posSecond, size, sizeRaw, guide, elGuideInfo, elGuideInfoCnt } = guideMatched; + + const axis = isUndefined(guide.x) ? 'y' : 'x'; + const isY = axis === 'y'; + + const guideInfoStyle = elGuideInfo.style; + + guideInfoStyle.display = ''; + guideInfoStyle[isY ? 'top' : 'left'] = `${posFirst}px`; + guideInfoStyle[isY ? 'left' : 'top'] = `${posSecond}px`; + guideInfoStyle[isY ? 'width' : 'height'] = `${size}px`; + + elGuideInfoCnt.innerHTML = `${Math.round(sizeRaw)}px`; + }, + + getGuidesMatched(guides = []) { + const { guidesStatic = [] } = this; + return guides + .map((guide) => { + const { origin, x } = guide; + const rectOrigin = this.getElementPos(origin); + const axis = isUndefined(x) ? 'y' : 'x'; + const isY = axis === 'y'; + + // Calculate the edges of the element + const origEdge1 = rectOrigin[isY ? 'left' : 'top']; + const origEdge1Raw = rectOrigin.rect[isY ? 'left' : 'top']; + const origEdge2 = isY ? origEdge1 + rectOrigin.width : origEdge1 + rectOrigin.height; + const origEdge2Raw = isY ? origEdge1Raw + rectOrigin.rect.width : origEdge1Raw + rectOrigin.rect.height; + + // Find the nearest element + const guidesMatched = guidesStatic + .filter((guideStatic) => { + // Define complementary guide types + const complementaryTypes: Record = { + l: ['r', 'x'], // Left can match with Right or Middle (horizontal) + r: ['l', 'x'], // Right can match with Left or Middle (horizontal) + x: ['l', 'r'], // Middle (horizontal) can match with Left or Right + t: ['b', 'y'], // Top can match with Bottom or Middle (vertical) + b: ['t', 'y'], // Bottom can match with Top or Middle (vertical) + y: ['t', 'b'], // Middle (vertical) can match with Top or Bottom + }; + + // Check if the guide type matches or is complementary + return guideStatic.type === guide.type || complementaryTypes[guide.type]?.includes(guideStatic.type); + }) + .map((guideStatic) => { + const { left, width, top, height } = guideStatic.originRect; + const statEdge1 = isY ? left : top; + const statEdge2 = isY ? left + width : top + height; + return { + gap: statEdge2 < origEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2, + guide: guideStatic, + }; + }) + .filter((item) => item.gap > 0) + .sort((a, b) => a.gap - b.gap) + .map((item) => item.guide) + // Filter the guides that don't match the position of the dragged element + .filter((item) => { + switch (guide.type) { + case 'l': + case 'r': + case 'x': + return Math.abs(item.x - guide.x) < 1; + case 't': + case 'b': + case 'y': + return Math.abs(item.y - guide.y) < 1; + default: + return false; + } + }); + + // TODO: consider supporting multiple guides + const firstGuideMatched = guidesMatched[0]; + + if (firstGuideMatched) { + const { left, width, top, height, rect } = firstGuideMatched.originRect; + const isEdge1 = isY ? left < rectOrigin.left : top < rectOrigin.top; const statEdge1 = isY ? left : top; + const statEdge1Raw = isY ? rect.left : rect.top; const statEdge2 = isY ? left + width : top + height; + const statEdge2Raw = isY ? rect.left + rect.width : rect.top + rect.height; + const posFirst = isY ? guide.y : guide.x; + const posSecond = isEdge1 ? statEdge2 : origEdge2; + const size = isEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2; + const sizeRaw = isEdge1 ? origEdge1Raw - statEdge2Raw : statEdge1Raw - origEdge2Raw; + + const elGuideInfo = this[`elGuideInfo${axis.toUpperCase()}` as ElGuideInfoKey]!; + const elGuideInfoCnt = this[`elGuideInfoContent${axis.toUpperCase()}` as ElGuideInfoContentKey]!; + return { - gap: statEdge2 < origEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2, - guide: stat, + guide, + guidesStatic, + matched: firstGuideMatched, + posFirst, + posSecond, + size, + sizeRaw, + elGuideInfo, + elGuideInfoCnt, }; - }) - .filter((item) => item.gap > 0) - .sort((a, b) => a.gap - b.gap) - .map((item) => item.guide)[0]; - - if (res) { - const { left, width, top, height, rect } = res.originRect; - const isEdge1 = isY ? left < rectOrigin.left : top < rectOrigin.top; - const statEdge1 = isY ? left : top; - const statEdge1Raw = isY ? rect.left : rect.top; - const statEdge2 = isY ? left + width : top + height; - const statEdge2Raw = isY ? rect.left + rect.width : rect.top + rect.height; - const posFirst = isY ? item.y : item.x; - const posSecond = isEdge1 ? statEdge2 : origEdge2; - const pos2 = `${posFirst}px`; - const size = isEdge1 ? origEdge1 - statEdge2 : statEdge1 - origEdge2; - const sizeRaw = isEdge1 ? origEdge1Raw - statEdge2Raw : statEdge1Raw - origEdge2Raw; - guideInfoStyle.display = ''; - guideInfoStyle[isY ? 'top' : 'left'] = pos2; - guideInfoStyle[isY ? 'left' : 'top'] = `${posSecond}px`; - guideInfoStyle[isY ? 'width' : 'height'] = `${size}px`; - elGuideInfoCnt.innerHTML = `${Math.round(sizeRaw)}px`; - this.em.trigger(`${evName}:active`, { - ...this.getEventOpts(), - guide: item, - guidesStatic, - matched: res, - posFirst, - posSecond, - size, - sizeRaw, - elGuideInfo, - elGuideInfoCnt, - }); - } - }); + } else { + return null; + } + }) + .filter(Boolean) as GuideMatched[]; }, - toggleDrag(enable: boolean) { + toggleDrag(enable) { const { ppfx, editor } = this; const methodCls = enable ? 'add' : 'remove'; const classes = [`${ppfx}is__grabbing`]; @@ -461,11 +559,206 @@ export default { classes.forEach((cls) => body.classList[methodCls](cls)); Canvas[enable ? 'startAutoscroll' : 'stopAutoscroll'](); }, -} as CommandObject< - any, - { - guidesStatic?: Guide[]; - guides?: Guide[]; - [k: string]: any; - } ->; + + // These properties values are set in the run method, they need to be initialized here to avoid TS errors + editor: undefined as unknown as Editor, + em: undefined as unknown as EditorModel, + opts: undefined as unknown as ComponentDragOpts, + target: undefined as unknown as Component, +} as CommandObject; + +interface ComponentDragProps { + editor: Editor; + em?: EditorModel; + guides?: Guide[]; + guidesContainer?: HTMLElement; + guidesEl?: HTMLElement; + guidesStatic?: Guide[]; + guidesTarget?: Guide[]; + isTran?: boolean; + opts: ComponentDragOpts; + target: Component; + elGuideInfoX?: HTMLElement; + elGuideInfoY?: HTMLElement; + elGuideInfoContentX?: HTMLElement; + elGuideInfoContentY?: HTMLElement; + dragger?: Dragger; + + getEventOpts: () => ComponentDragEventProps; + stop: () => void; + setupGuides: () => void; + getGuidesContainer: () => HTMLElement; + getGuidesStatic: () => Guide[]; + getGuidesTarget: () => Guide[]; + updateGuides: (guides?: Guide[]) => void; + getGuidePosUpdate: (item: Guide, rect: ComponentOrigRect) => { x?: number; y?: number }; + renderGuide: (item: { active?: boolean; guide?: HTMLElement; x?: number; y?: number }) => HTMLElement; + getElementPos: (el: HTMLElement) => ComponentOrigRect; + getElementGuides: (el: HTMLElement) => Guide[]; + getTranslate: (transform: string, axis?: string) => number; + setTranslate: (transform: string, axis: string, value: string) => string; + getPosition: DraggerOptions['getPosition']; + setPosition: (data: any) => void; // TODO: fix any + _getDragData: () => { target: Component; parent?: Component; index?: number }; + onStart: DraggerOptions['onStart']; + onDrag: DraggerOptions['onDrag']; + onEnd: DraggerOptions['onEnd']; + hideGuidesInfo: () => void; + renderGuideInfo: (guides?: Guide[]) => void; + renderSingleGuideInfo: (guideMatched: GuideMatched) => void; + getGuidesMatched: (guides?: Guide[]) => GuideMatched[]; + toggleDrag: (enable?: boolean) => void; +} + +type ComponentDragOpts = { + target: Component; + center?: number; + debug?: boolean; + dragger?: DraggerOptions; + event?: Event; + guidesInfo?: number; + mode?: 'absolute' | 'translate'; + skipGuidesRender?: boolean; + addStyle?: (data: { component?: Component; styles?: Record; partial?: boolean }) => void; + onStart?: (data: any) => Editor; + onDrag?: (data: any) => Editor; + onEnd?: (ev: Event, opt: any, data: any) => void; +}; + +/** + * Represents the properties of the drag events. + */ +type ComponentDragEventProps = { + /** + * The mode of the drag (absolute or translate). + */ + mode: ComponentDragOpts['mode']; + /** + * The component being dragged. + * @deprecated Use `component` instead. + */ + target: Component; + /** + * The component being dragged. + */ + component: Component; + /** + * The guides of the component being dragged. + * @deprecated Use `guidesMatched` instead. + */ + guidesTarget: Guide[]; + /** + * All the guides except the ones of the component being dragged. + * @deprecated Use `guidesMatched` instead. + */ + guidesStatic: Guide[]; + /** + * The guides that are being matched. + */ + guidesMatched: GuideMatched[]; +}; + +/** + * Represents a guide used during component dragging. + */ +type Guide = { + /** + * The type of the guide (e.g., 't', 'b', 'l', 'r', 'x', 'y'). + */ + type: string; + /** + * The vertical position of the guide. + */ + y: number; + /** + * The horizontal position of the guide. + */ + x: number; + /** + * The component associated with the guide. + */ + component: Component; + /** + * The view of the component associated with the guide. + */ + componentView: ComponentView; + /** + * The HTML element associated with the guide. + * @deprecated Use `componentEl` instead. + */ + origin: HTMLElement; + /** + * The HTML element associated with the guide. + */ + componentEl: HTMLElement; + /** + * The rectangle (position and dimensions) of the guide's element. + * @deprecated Use `componentElRect` instead. + */ + originRect: ComponentOrigRect; + /** + * The rectangle (position and dimensions) of the guide's element. + */ + componentElRect: ComponentOrigRect; + /** + * The HTML element representing the guide. + * @deprecated Use `guideEl` instead. + */ + guide?: HTMLElement; + /** + * The HTML element representing the guide. + */ + guideEl?: HTMLElement; + /** + * Indicates whether the guide is active. + * @todo The `active` property is not set in the code, but the value is changing. + */ + active?: boolean; +}; + +/** + * Represents a matched guide during component dragging. + */ +type GuideMatched = { + /** + * The static guides used for matching. + */ + guidesStatic: Guide[]; + /** + * The origin component guide. + */ + guide: Guide; + /** + * The matched component guide. + */ + matched: Guide; + /** + * The primary position of the guide (either x or y depending on the axis). + */ + posFirst: number; + /** + * The secondary position of the guide (the opposite axis of posFirst). + */ + posSecond: number; + /** + * The distance between the two matched guides in pixels. + */ + size: number; + /** + * The raw distance between the two matched guides in pixels. + */ + sizeRaw: number; + /** + * The HTML element representing the guide info (line between the guides). + */ + elGuideInfo: HTMLElement; + /** + * The container element for the guide info (text content of the line). + */ + elGuideInfoCnt: HTMLElement; +}; + +type ComponentRect = { left: number; width: number; top: number; height: number }; +type ComponentOrigRect = ComponentRect & { rect: ComponentRect }; +type ElGuideInfoKey = 'elGuideInfoX' | 'elGuideInfoY'; +type ElGuideInfoContentKey = 'elGuideInfoContentX' | 'elGuideInfoContentY'; diff --git a/packages/core/src/data_sources/model/ComponentDataVariable.ts b/packages/core/src/data_sources/model/ComponentDataVariable.ts index 504956c40..6f8aa0d97 100644 --- a/packages/core/src/data_sources/model/ComponentDataVariable.ts +++ b/packages/core/src/data_sources/model/ComponentDataVariable.ts @@ -1,8 +1,14 @@ +import { ObjectAny } from '../../common'; import Component from '../../dom_components/model/Component'; -import { ComponentOptions } from '../../dom_components/model/types'; +import { ComponentDefinition, ComponentOptions, ComponentProperties } from '../../dom_components/model/types'; import { toLowerCase } from '../../utils/mixins'; import DataVariable, { DataVariableProps, DataVariableType } from './DataVariable'; +export interface ComponentDataVariableProps extends ComponentProperties { + type: typeof DataVariableType; + dataResolver: DataVariableProps; +} + export default class ComponentDataVariable extends Component { dataResolver: DataVariable; @@ -10,17 +16,20 @@ export default class ComponentDataVariable extends Component { return { // @ts-ignore ...super.defaults, - type: DataVariableType, - path: '', - defaultValue: '', droppable: false, + type: DataVariableType, + dataResolver: { + path: '', + defaultValue: '', + }, }; } - constructor(props: DataVariableProps, opt: ComponentOptions) { + constructor(props: ComponentDataVariableProps, opt: ComponentOptions) { super(props, opt); - const { type, path, defaultValue } = props; - this.dataResolver = new DataVariable({ type, path, defaultValue }, opt); + + this.dataResolver = new DataVariable(props.dataResolver, opt); + this.listenToPropsChange(); } getPath() { @@ -47,6 +56,23 @@ export default class ComponentDataVariable extends Component { this.dataResolver.set('defaultValue', newValue); } + private listenToPropsChange() { + this.on('change:dataResolver', () => { + this.dataResolver.set(this.get('dataResolver')); + }); + } + + toJSON(opts?: ObjectAny): ComponentDefinition { + const json = super.toJSON(opts); + const dataResolver = this.dataResolver.toJSON(); + delete dataResolver.type; + + return { + ...json, + dataResolver, + }; + } + static isComponent(el: HTMLElement) { return toLowerCase(el.tagName) === DataVariableType; } diff --git a/packages/core/src/data_sources/model/DataResolverListener.ts b/packages/core/src/data_sources/model/DataResolverListener.ts index 0b13f8a43..b10f7e262 100644 --- a/packages/core/src/data_sources/model/DataResolverListener.ts +++ b/packages/core/src/data_sources/model/DataResolverListener.ts @@ -4,7 +4,11 @@ import { Model } from '../../common'; import EditorModel from '../../editor/model/Editor'; import DataVariable, { DataVariableType } from './DataVariable'; import { DataResolver } from '../types'; -import { DataCondition, DataConditionType } from './conditional_variables/DataCondition'; +import { + DataCondition, + DataConditionOutputChangedEvent, + DataConditionType, +} from './conditional_variables/DataCondition'; import { DataCollectionVariableType } from './data_collection/constants'; import DataCollectionVariable from './data_collection/DataCollectionVariable'; @@ -64,12 +68,13 @@ export default class DataResolverListener { } private listenToConditionalVariable(dataVariable: DataCondition): ListenerWithCallback[] { - const { em } = this; - const dataListeners = dataVariable.getDependentDataVariables().flatMap((dataVariable) => { - return this.listenToDataVariable(new DataVariable(dataVariable, { em })); - }); - - return dataListeners; + return [ + { + obj: dataVariable, + event: DataConditionOutputChangedEvent, + callback: this.onChange, + }, + ]; } private listenToDataVariable(dataVariable: DataVariable): ListenerWithCallback[] { diff --git a/packages/core/src/data_sources/model/DataVariable.ts b/packages/core/src/data_sources/model/DataVariable.ts index caaaa5722..f64a86d87 100644 --- a/packages/core/src/data_sources/model/DataVariable.ts +++ b/packages/core/src/data_sources/model/DataVariable.ts @@ -4,7 +4,7 @@ import EditorModel from '../../editor/model/Editor'; export const DataVariableType = 'data-variable' as const; export interface DataVariableProps { - type: typeof DataVariableType; + type?: typeof DataVariableType; path: string; defaultValue?: string; } diff --git a/packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts b/packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts index 755262883..f5e21d52d 100644 --- a/packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts +++ b/packages/core/src/data_sources/model/conditional_variables/ComponentDataCondition.ts @@ -1,61 +1,123 @@ import Component from '../../../dom_components/model/Component'; -import { ComponentDefinition, ComponentOptions } from '../../../dom_components/model/types'; +import { + ComponentDefinition as ComponentProperties, + ComponentDefinitionDefined, + ComponentOptions, + ToHTMLOptions, + ComponentAddType, +} from '../../../dom_components/model/types'; import { toLowerCase } from '../../../utils/mixins'; -import { DataCondition, DataConditionProps, DataConditionType } from './DataCondition'; +import { DataCondition, DataConditionOutputChangedEvent, DataConditionProps, DataConditionType } from './DataCondition'; import { ConditionProps } from './DataConditionEvaluator'; +import { StringOperation } from './operators/StringOperator'; +import { ObjectAny } from '../../../common'; +import { DataConditionIfTrueType, DataConditionIfFalseType } from './constants'; + +export type DataConditionDisplayType = typeof DataConditionIfTrueType | typeof DataConditionIfFalseType; + +export interface ComponentDataConditionProps extends ComponentProperties { + type: typeof DataConditionType; + dataResolver: DataConditionProps; +} export default class ComponentDataCondition extends Component { dataResolver: DataCondition; - constructor(props: DataConditionProps, opt: ComponentOptions) { - const dataConditionInstance = new DataCondition(props, { em: opt.em }); - - super( - { - ...props, - type: DataConditionType, - components: dataConditionInstance.getDataValue(), - droppable: false, + get defaults(): ComponentDefinitionDefined { + return { + // @ts-ignore + ...super.defaults, + droppable: false, + type: DataConditionType, + dataResolver: { + condition: { + left: '', + operator: StringOperation.equalsIgnoreCase, + right: '', + }, }, - opt, - ); - this.dataResolver = dataConditionInstance; - this.dataResolver.onValueChange = this.handleConditionChange.bind(this); + components: [ + { + type: DataConditionIfTrueType, + }, + { + type: DataConditionIfFalseType, + }, + ], + }; } - getCondition() { - return this.dataResolver.getCondition(); + constructor(props: ComponentDataConditionProps, opt: ComponentOptions) { + // @ts-ignore + super(props, opt); + + const { condition } = props.dataResolver; + this.dataResolver = new DataCondition({ condition }, { em: opt.em }); + + this.listenToPropsChange(); } - getIfTrue() { - return this.dataResolver.getIfTrue(); + isTrue() { + return this.dataResolver.isTrue(); } - getIfFalse() { - return this.dataResolver.getIfFalse(); + getCondition() { + return this.dataResolver.getCondition(); } - private handleConditionChange() { - this.components(this.dataResolver.getDataValue()); + getIfTrueContent(): Component | undefined { + return this.components().at(0); } - static isComponent(el: HTMLElement) { - return toLowerCase(el.tagName) === DataConditionType; + getIfFalseContent(): Component | undefined { + return this.components().at(1); + } + + getOutputContent(): Component | undefined { + return this.isTrue() ? this.getIfTrueContent() : this.getIfFalseContent(); } setCondition(newCondition: ConditionProps) { this.dataResolver.setCondition(newCondition); } - setIfTrue(newIfTrue: any) { - this.dataResolver.setIfTrue(newIfTrue); + setIfTrueComponents(content: ComponentAddType) { + this.setComponentsAtIndex(0, content); + } + + setIfFalseComponents(content: ComponentAddType) { + this.setComponentsAtIndex(1, content); + } + + getInnerHTML(opts?: ToHTMLOptions): string { + return this.getOutputContent()?.getInnerHTML(opts) ?? ''; + } + + private setComponentsAtIndex(index: number, newContent: ComponentAddType) { + const component = this.components().at(index); + component?.components(newContent); + } + + private listenToPropsChange() { + this.on('change:dataResolver', () => { + this.dataResolver.set(this.get('dataResolver')); + }); } - setIfFalse(newIfFalse: any) { - this.dataResolver.setIfFalse(newIfFalse); + toJSON(opts?: ObjectAny): ComponentProperties { + const json = super.toJSON(opts); + const dataResolver = this.dataResolver.toJSON(); + delete dataResolver.type; + delete dataResolver.ifTrue; + delete dataResolver.ifFalse; + + return { + ...json, + dataResolver, + }; } - toJSON(): ComponentDefinition { - return this.dataResolver.toJSON(); + static isComponent(el: HTMLElement) { + return toLowerCase(el.tagName) === DataConditionType; } } diff --git a/packages/core/src/data_sources/model/conditional_variables/ConditionalOutputBase.ts b/packages/core/src/data_sources/model/conditional_variables/ConditionalOutputBase.ts new file mode 100644 index 000000000..65bc1f92b --- /dev/null +++ b/packages/core/src/data_sources/model/conditional_variables/ConditionalOutputBase.ts @@ -0,0 +1,19 @@ +import Component from '../../../dom_components/model/Component'; +import { ComponentDefinitionDefined, ToHTMLOptions } from '../../../dom_components/model/types'; +import { toLowerCase } from '../../../utils/mixins'; +import { isDataConditionDisplayType } from '../../utils'; + +export default class ConditionalOutputBase extends Component { + get defaults(): ComponentDefinitionDefined { + return { + // @ts-ignore + ...super.defaults, + removable: false, + draggable: false, + }; + } + + static isComponent(el: HTMLElement) { + return isDataConditionDisplayType(toLowerCase(el.tagName)); + } +} diff --git a/packages/core/src/data_sources/model/conditional_variables/DataCondition.ts b/packages/core/src/data_sources/model/conditional_variables/DataCondition.ts index fc72ef2f0..1f3c03cc1 100644 --- a/packages/core/src/data_sources/model/conditional_variables/DataCondition.ts +++ b/packages/core/src/data_sources/model/conditional_variables/DataCondition.ts @@ -2,7 +2,7 @@ import { Model } from '../../../common'; import EditorModel from '../../../editor/model/Editor'; import DataVariable, { DataVariableProps } from '../DataVariable'; import DataResolverListener from '../DataResolverListener'; -import { evaluateVariable, isDataVariable } from '../utils'; +import { resolveDynamicValue, isDataVariable } from '../../utils'; import { DataConditionEvaluator, ConditionProps } from './DataConditionEvaluator'; import { AnyTypeOperation } from './operators/AnyTypeOperator'; import { BooleanOperation } from './operators/BooleanOperator'; @@ -10,12 +10,14 @@ import { NumberOperation } from './operators/NumberOperator'; import { StringOperation } from './operators/StringOperator'; import { isUndefined } from 'underscore'; -export const DataConditionType = 'data-condition'; +export const DataConditionType = 'data-condition' as const; +export const DataConditionEvaluationChangedEvent = 'data-condition-evaluation-changed'; +export const DataConditionOutputChangedEvent = 'data-condition-output-changed'; export interface ExpressionProps { - left: any; - operator: AnyTypeOperation | StringOperation | NumberOperation; - right: any; + left?: any; + operator?: AnyTypeOperation | StringOperation | NumberOperation; + right?: any; } export interface LogicGroupProps { @@ -24,129 +26,159 @@ export interface LogicGroupProps { } export interface DataConditionProps { - type: typeof DataConditionType; + type?: typeof DataConditionType; condition: ConditionProps; - ifTrue: any; - ifFalse: any; + ifTrue?: any; + ifFalse?: any; } -interface DataConditionPropsDefined extends Omit { - condition: DataConditionEvaluator; -} - -export class DataCondition extends Model { +export class DataCondition extends Model { private em: EditorModel; private resolverListeners: DataResolverListener[] = []; - private _onValueChange?: () => void; - - constructor( - props: { - condition: ConditionProps; - ifTrue: any; - ifFalse: any; - }, - opts: { em: EditorModel; onValueChange?: () => void }, - ) { + private _previousEvaluationResult: boolean | null = null; + private _conditionEvaluator: DataConditionEvaluator; + + defaults() { + return { + type: DataConditionType, + condition: { + left: '', + operator: StringOperation.equalsIgnoreCase, + right: '', + }, + ifTrue: {}, + ifFalse: {}, + }; + } + + constructor(props: DataConditionProps, opts: { em: EditorModel; onValueChange?: () => void }) { if (isUndefined(props.condition)) { opts.em.logError('No condition was provided to a conditional component.'); } - const conditionInstance = new DataConditionEvaluator({ condition: props.condition }, { em: opts.em }); - - super({ - type: DataConditionType, - ...props, - condition: conditionInstance, - }); + // @ts-ignore + super(props, opts); this.em = opts.em; - this.listenToDataVariables(); - this._onValueChange = opts.onValueChange; - - this.on('change:condition change:ifTrue change:ifFalse', () => { - this.listenToDataVariables(); - this._onValueChange?.(); - }); - } - private get conditionEvaluator() { - return this.get('condition')!; + const { condition = {} } = props; + const instance = new DataConditionEvaluator({ condition }, { em: this.em }); + this._conditionEvaluator = instance; + this.listenToDataVariables(); + this.listenToPropsChange(); } getCondition(): ConditionProps { - return this.get('condition')?.get('condition')!; + return this._conditionEvaluator.get('condition')!; } getIfTrue() { - return this.get('ifTrue')!; + return this.get('ifTrue'); } getIfFalse() { - return this.get('ifFalse')!; + return this.get('ifFalse'); + } + + setCondition(condition: ConditionProps) { + this._conditionEvaluator.set('condition', condition); + this.trigger(DataConditionOutputChangedEvent, this.getDataValue()); + } + + setIfTrue(newIfTrue: any) { + this.set('ifTrue', newIfTrue); + } + + setIfFalse(newIfFalse: any) { + this.set('ifFalse', newIfFalse); } isTrue(): boolean { - return this.conditionEvaluator.evaluate(); + return this._conditionEvaluator.evaluate(); } getDataValue(skipDynamicValueResolution: boolean = false): any { - const ifTrue = this.get('ifTrue'); - const ifFalse = this.get('ifFalse'); + const ifTrue = this.getIfTrue(); + const ifFalse = this.getIfFalse(); const isConditionTrue = this.isTrue(); if (skipDynamicValueResolution) { return isConditionTrue ? ifTrue : ifFalse; } - return isConditionTrue ? evaluateVariable(ifTrue, this.em) : evaluateVariable(ifFalse, this.em); + return isConditionTrue ? resolveDynamicValue(ifTrue, this.em) : resolveDynamicValue(ifFalse, this.em); } - set onValueChange(newFunction: () => void) { - this._onValueChange = newFunction; + private listenToPropsChange() { + this.on('change:condition', this.handleConditionChange.bind(this)); + this.on('change:condition change:ifTrue change:ifFalse', () => { + this.listenToDataVariables(); + }); } - setCondition(newCondition: ConditionProps) { - const newConditionInstance = new DataConditionEvaluator({ condition: newCondition }, { em: this.em }); - this.set('condition', newConditionInstance); + private handleConditionChange() { + this.setCondition(this.get('condition')!); } - setIfTrue(newIfTrue: any) { - this.set('ifTrue', newIfTrue); - } + private listenToDataVariables() { + // Clear previous listeners to avoid memory leaks + this.cleanupListeners(); - setIfFalse(newIfFalse: any) { - this.set('ifFalse', newIfFalse); + this.setupConditionDataVariableListeners(); + this.setupOutputDataVariableListeners(); } - private listenToDataVariables() { - const { em } = this; - if (!em) return; + private setupConditionDataVariableListeners() { + this._conditionEvaluator.getDependentDataVariables().forEach((variable) => { + this.addListener(variable, () => { + this.emitConditionEvaluationChange(); + }); + }); + } - // Clear previous listeners to avoid memory leaks - this.cleanupListeners(); + private setupOutputDataVariableListeners() { + const isConditionTrue = this.isTrue(); - const dataVariables = this.getDependentDataVariables(); + this.setupOutputVariableListener(this.getIfTrue(), isConditionTrue); + this.setupOutputVariableListener(this.getIfFalse(), !isConditionTrue); + } - dataVariables.forEach((variable) => { - const listener = new DataResolverListener({ - em, - resolver: new DataVariable(variable, { em: this.em }), - onUpdate: (() => { - this._onValueChange?.(); - }).bind(this), + /** + * Sets up a listener for an output variable (ifTrue or ifFalse). + * @param outputVariable - The output variable to listen to. + * @param isConditionTrue - Whether the condition is currently true. + */ + private setupOutputVariableListener(outputVariable: any, isConditionTrue: boolean) { + if (isDataVariable(outputVariable)) { + this.addListener(outputVariable, () => { + if (isConditionTrue) { + this.trigger(DataConditionOutputChangedEvent, outputVariable); + } }); + } + } - this.resolverListeners.push(listener); + private addListener(variable: DataVariableProps, onUpdate: () => void) { + const listener = new DataResolverListener({ + em: this.em, + resolver: new DataVariable(variable, { em: this.em }), + onUpdate, }); + + this.resolverListeners.push(listener); } - getDependentDataVariables() { - const dataVariables: DataVariableProps[] = this.conditionEvaluator.getDependentDataVariables(); - const ifTrue = this.get('ifTrue'); - const ifFalse = this.get('ifFalse'); - if (isDataVariable(ifTrue)) dataVariables.push(ifTrue); - if (isDataVariable(ifFalse)) dataVariables.push(ifFalse); + private emitConditionEvaluationChange() { + const currentEvaluationResult = this.isTrue(); + if (this._previousEvaluationResult !== currentEvaluationResult) { + this._previousEvaluationResult = currentEvaluationResult; + this.trigger(DataConditionEvaluationChangedEvent, currentEvaluationResult); + this.emitOutputValueChange(); + } + } - return dataVariables; + private emitOutputValueChange() { + const currentOutputValue = this.getDataValue(); + this.trigger(DataConditionOutputChangedEvent, currentOutputValue); } private cleanupListeners() { @@ -154,13 +186,13 @@ export class DataCondition extends Model { this.resolverListeners = []; } - toJSON() { - const ifTrue = this.get('ifTrue'); - const ifFalse = this.get('ifFalse'); + toJSON(): DataConditionProps { + const ifTrue = this.getIfTrue(); + const ifFalse = this.getIfFalse(); return { type: DataConditionType, - condition: this.conditionEvaluator, + condition: this._conditionEvaluator.toJSON(), ifTrue, ifFalse, }; diff --git a/packages/core/src/data_sources/model/conditional_variables/DataConditionEvaluator.ts b/packages/core/src/data_sources/model/conditional_variables/DataConditionEvaluator.ts index b8f5aba9b..a51b666a7 100644 --- a/packages/core/src/data_sources/model/conditional_variables/DataConditionEvaluator.ts +++ b/packages/core/src/data_sources/model/conditional_variables/DataConditionEvaluator.ts @@ -1,6 +1,6 @@ import { DataVariableProps } from '../DataVariable'; import EditorModel from '../../../editor/model/Editor'; -import { evaluateVariable, isDataVariable } from '../utils'; +import { resolveDynamicValue, isDataVariable } from '../../utils'; import { ExpressionProps, LogicGroupProps } from './DataCondition'; import { LogicalGroupEvaluator } from './LogicalGroupEvaluator'; import { Operator } from './operators/BaseOperator'; @@ -39,9 +39,10 @@ export class DataConditionEvaluator extends Model { if (this.isExpression(condition)) { const { left, operator, right } = condition; - const evaluateLeft = evaluateVariable(left, this.em); - const evaluateRight = evaluateVariable(right, this.em); + const evaluateLeft = resolveDynamicValue(left, this.em); + const evaluateRight = resolveDynamicValue(right, this.em); const op = this.getOperator(evaluateLeft, operator); + if (!op) return false; const evaluated = op.evaluate(evaluateLeft, evaluateRight); return evaluated; @@ -54,7 +55,7 @@ export class DataConditionEvaluator extends Model { /** * Factory method for creating operators based on the data type. */ - private getOperator(left: any, operator: string): Operator { + private getOperator(left: any, operator: string | undefined): Operator | undefined { const em = this.em; if (this.isOperatorInEnum(operator, AnyTypeOperation)) { @@ -64,7 +65,9 @@ export class DataConditionEvaluator extends Model { } else if (typeof left === 'string') { return new StringOperator(operator as StringOperation, { em }); } - throw new Error(`Unsupported data type: ${typeof left}`); + + this.em?.logError(`Unsupported data type: ${typeof left}`); + return; } getDependentDataVariables(): DataVariableProps[] { @@ -95,7 +98,7 @@ export class DataConditionEvaluator extends Model { return condition && typeof condition.left !== 'undefined' && typeof condition.operator === 'string'; } - private isOperatorInEnum(operator: string, enumObject: any): boolean { + private isOperatorInEnum(operator: string | undefined, enumObject: any): boolean { return Object.values(enumObject).includes(operator); } diff --git a/packages/core/src/data_sources/model/conditional_variables/constants.ts b/packages/core/src/data_sources/model/conditional_variables/constants.ts new file mode 100644 index 000000000..618d7e425 --- /dev/null +++ b/packages/core/src/data_sources/model/conditional_variables/constants.ts @@ -0,0 +1,2 @@ +export const DataConditionIfTrueType = 'data-condition-true-content'; +export const DataConditionIfFalseType = 'data-condition-false-content'; diff --git a/packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts b/packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts index 1fa19bc3e..bfdc8ff6d 100644 --- a/packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts +++ b/packages/core/src/data_sources/model/data_collection/ComponentDataCollection.ts @@ -7,7 +7,7 @@ import { isObject, serialize, toLowerCase } from '../../../utils/mixins'; import DataResolverListener from '../DataResolverListener'; import DataSource from '../DataSource'; import DataVariable, { DataVariableProps, DataVariableType } from '../DataVariable'; -import { isDataVariable } from '../utils'; +import { ensureComponentInstance, isDataVariable } from '../../utils'; import { DataCollectionType, keyCollectionDefinition, keyCollectionsStateMap, keyIsCollectionItem } from './constants'; import { ComponentDataCollectionProps, @@ -200,12 +200,9 @@ export default class ComponentDataCollection extends Component { }; if (isFirstItem) { - const componentType = (componentDef?.type as string) || 'default'; - let type = this.em.Components.getType(componentType) || this.em.Components.getType('default'); - const Model = type.model; - symbolMain = new Model( + symbolMain = ensureComponentInstance( { - ...serialize(componentDef), + ...componentDef, draggable: false, removable: false, }, diff --git a/packages/core/src/data_sources/model/utils.ts b/packages/core/src/data_sources/model/utils.ts deleted file mode 100644 index ae2130ef0..000000000 --- a/packages/core/src/data_sources/model/utils.ts +++ /dev/null @@ -1,67 +0,0 @@ -import EditorModel from '../../editor/model/Editor'; -import { DataResolver, DataResolverProps } from '../types'; -import { DataCollectionStateMap } from './data_collection/types'; -import DataCollectionVariable from './data_collection/DataCollectionVariable'; -import { DataCollectionVariableType } from './data_collection/constants'; -import { DataConditionType, DataCondition } from './conditional_variables/DataCondition'; -import DataVariable, { DataVariableProps, DataVariableType } from './DataVariable'; - -export function isDataResolverProps(value: any): value is DataResolverProps { - return ( - typeof value === 'object' && [DataVariableType, DataConditionType, DataCollectionVariableType].includes(value?.type) - ); -} - -export function isDataResolver(value: any): value is DataResolver { - return value instanceof DataVariable || value instanceof DataCondition; -} - -export function isDataVariable(variable: any): variable is DataVariableProps { - return variable?.type === DataVariableType; -} - -export function isDataCondition(variable: any) { - return variable?.type === DataConditionType; -} - -export function evaluateVariable(variable: any, em: EditorModel) { - return isDataVariable(variable) ? new DataVariable(variable, { em }).getDataValue() : variable; -} - -export function getDataResolverInstance( - resolverProps: DataResolverProps, - options: { em: EditorModel; collectionsStateMap?: DataCollectionStateMap }, -): DataResolver { - const { type } = resolverProps; - let resolver: DataResolver; - - switch (type) { - case DataVariableType: - resolver = new DataVariable(resolverProps, options); - break; - case DataConditionType: { - resolver = new DataCondition(resolverProps, options); - break; - } - case DataCollectionVariableType: { - resolver = new DataCollectionVariable(resolverProps, options); - break; - } - default: - throw new Error(`Unsupported dynamic type: ${type}`); - } - - return resolver; -} - -export function getDataResolverInstanceValue( - resolverProps: DataResolverProps, - options: { - em: EditorModel; - collectionsStateMap?: DataCollectionStateMap; - }, -) { - const resolver = getDataResolverInstance(resolverProps, options); - - return resolver.getDataValue(); -} diff --git a/packages/core/src/data_sources/utils.ts b/packages/core/src/data_sources/utils.ts new file mode 100644 index 000000000..72a3bca60 --- /dev/null +++ b/packages/core/src/data_sources/utils.ts @@ -0,0 +1,91 @@ +import EditorModel from '../editor/model/Editor'; +import { DataResolver, DataResolverProps } from './types'; +import { DataConditionDisplayType } from './model/conditional_variables/ComponentDataCondition'; +import { DataCollectionStateMap } from './model/data_collection/types'; +import DataCollectionVariable from './model/data_collection/DataCollectionVariable'; +import { DataCollectionVariableType } from './model/data_collection/constants'; +import { DataConditionType, DataCondition } from './model/conditional_variables/DataCondition'; +import DataVariable, { DataVariableProps, DataVariableType } from './model/DataVariable'; +import Component from '../dom_components/model/Component'; +import { ComponentDefinition, ComponentOptions } from '../dom_components/model/types'; +import { serialize } from '../utils/mixins'; +import { DataConditionIfFalseType, DataConditionIfTrueType } from './model/conditional_variables/constants'; + +export function isDataResolverProps(value: any): value is DataResolverProps { + return ( + typeof value === 'object' && [DataVariableType, DataConditionType, DataCollectionVariableType].includes(value?.type) + ); +} + +export function isDataResolver(value: any): value is DataResolver { + return value instanceof DataVariable || value instanceof DataCondition; +} + +export function isDataVariable(variable: any): variable is DataVariableProps { + return variable?.type === DataVariableType; +} + +export function isDataCondition(variable: any) { + return variable?.type === DataConditionType; +} + +export function resolveDynamicValue(variable: any, em: EditorModel) { + return isDataResolverProps(variable) ? getDataResolverInstanceValue(variable, { em }) : variable; +} + +export function getDataResolverInstance( + resolverProps: DataResolverProps, + options: { em: EditorModel; collectionsStateMap?: DataCollectionStateMap }, +) { + const { type } = resolverProps; + let resolver: DataResolver; + + switch (type) { + case DataVariableType: + resolver = new DataVariable(resolverProps, options); + break; + case DataConditionType: { + resolver = new DataCondition(resolverProps, options); + break; + } + case DataCollectionVariableType: { + resolver = new DataCollectionVariable(resolverProps, options); + break; + } + default: + options.em?.logError(`Unsupported dynamic type: ${type}`); + return; + } + + return resolver; +} + +export function getDataResolverInstanceValue( + resolverProps: DataResolverProps, + options: { + em: EditorModel; + collectionsStateMap?: DataCollectionStateMap; + }, +) { + const resolver = getDataResolverInstance(resolverProps, options); + + return resolver?.getDataValue(); +} + +export const ensureComponentInstance = ( + cmp: Component | ComponentDefinition | undefined, + opt: ComponentOptions, +): Component => { + if (cmp instanceof Component) return cmp; + + const componentType = (cmp?.type as string) ?? 'default'; + const defaultModel = opt.em.Components.getType('default'); + const type = opt.em.Components.getType(componentType) ?? defaultModel; + const Model = type.model; + + return new Model(serialize(cmp ?? {}), opt); +}; + +export const isDataConditionDisplayType = (type: string | undefined): type is DataConditionDisplayType => { + return !!type && [DataConditionIfTrueType, DataConditionIfFalseType].includes(type); +}; diff --git a/packages/core/src/data_sources/view/ComponentDataConditionView.ts b/packages/core/src/data_sources/view/ComponentDataConditionView.ts index c8bf42438..6ec3f9316 100644 --- a/packages/core/src/data_sources/view/ComponentDataConditionView.ts +++ b/packages/core/src/data_sources/view/ComponentDataConditionView.ts @@ -1,4 +1,46 @@ import ComponentView from '../../dom_components/view/ComponentView'; import ComponentDataCondition from '../model/conditional_variables/ComponentDataCondition'; +import DataResolverListener from '../model/DataResolverListener'; -export default class ComponentDataConditionView extends ComponentView {} +export default class ComponentDataConditionView extends ComponentView { + dataResolverListener!: DataResolverListener; + + initialize(opt = {}) { + super.initialize(opt); + + this.postRender = this.postRender.bind(this); + this.listenTo(this.model.components(), 'reset', this.postRender); + this.dataResolverListener = new DataResolverListener({ + em: this.em, + resolver: this.model.dataResolver, + onUpdate: this.postRender, + }); + } + + renderDataResolver() { + const componentTrue = this.model.getIfTrueContent(); + const componentFalse = this.model.getIfFalseContent(); + + const elTrue = componentTrue?.getEl(); + const elFalse = componentFalse?.getEl(); + + const isTrue = this.model.isTrue(); + if (elTrue) { + elTrue.style.display = isTrue ? '' : 'none'; + } + if (elFalse) { + elFalse.style.display = isTrue ? 'none' : ''; + } + } + + postRender() { + this.renderDataResolver(); + super.postRender(); + } + + remove() { + this.stopListening(this.model.components(), 'reset', this.postRender); + this.dataResolverListener.destroy(); + return super.remove(); + } +} diff --git a/packages/core/src/dom_components/index.ts b/packages/core/src/dom_components/index.ts index 224dfc585..6de1385f8 100644 --- a/packages/core/src/dom_components/index.ts +++ b/packages/core/src/dom_components/index.ts @@ -126,13 +126,18 @@ import ComponentDataVariable from '../data_sources/model/ComponentDataVariable'; import ComponentDataVariableView from '../data_sources/view/ComponentDataVariableView'; import { DataVariableType } from '../data_sources/model/DataVariable'; import { DataConditionType } from '../data_sources/model/conditional_variables/DataCondition'; -import ComponentDataCondition from '../data_sources/model/conditional_variables/ComponentDataCondition'; import ComponentDataConditionView from '../data_sources/view/ComponentDataConditionView'; import ComponentDataCollection from '../data_sources/model/data_collection/ComponentDataCollection'; import { DataCollectionType, DataCollectionVariableType } from '../data_sources/model/data_collection/constants'; import ComponentDataCollectionVariable from '../data_sources/model/data_collection/ComponentDataCollectionVariable'; import ComponentDataCollectionVariableView from '../data_sources/view/ComponentDataCollectionVariableView'; import ComponentDataCollectionView from '../data_sources/view/ComponentDataCollectionView'; +import ComponentDataCondition from '../data_sources/model/conditional_variables/ComponentDataCondition'; +import { + DataConditionIfFalseType, + DataConditionIfTrueType, +} from '../data_sources/model/conditional_variables/constants'; +import ConditionalOutputBase from '../data_sources/model/conditional_variables/ConditionalOutputBase'; export type ComponentEvent = | 'component:create' @@ -198,6 +203,16 @@ export interface CanMoveResult { export default class ComponentManager extends ItemManagerModule { componentTypes: ComponentStackItem[] = [ + { + id: DataConditionIfTrueType, + model: ConditionalOutputBase, + view: ComponentView, + }, + { + id: DataConditionIfFalseType, + model: ConditionalOutputBase, + view: ComponentView, + }, { id: DataCollectionVariableType, model: ComponentDataCollectionVariable, diff --git a/packages/core/src/dom_components/model/Component.ts b/packages/core/src/dom_components/model/Component.ts index 1bd4e035c..c9f0cbf26 100644 --- a/packages/core/src/dom_components/model/Component.ts +++ b/packages/core/src/dom_components/model/Component.ts @@ -1378,8 +1378,9 @@ export default class Component extends StyleableModel { cloned.set(keySymbol, 0); cloned.set(keySymbols, 0); } else if (symbol) { + const mainSymbolInstances = getSymbolInstances(symbol) ?? []; // Contains already a reference to a symbol - symbol.set(keySymbols, [...getSymbolInstances(symbol)!, cloned]); + symbol.set(keySymbols, [...mainSymbolInstances!, cloned]); initSymbol(cloned); } else if (opt.symbol) { // Request to create a symbol diff --git a/packages/core/src/dom_components/model/ComponentResolverWatcher.ts b/packages/core/src/dom_components/model/ComponentResolverWatcher.ts index 11ca8ba74..ed6d4a851 100644 --- a/packages/core/src/dom_components/model/ComponentResolverWatcher.ts +++ b/packages/core/src/dom_components/model/ComponentResolverWatcher.ts @@ -2,11 +2,7 @@ import { ObjectAny } from '../../common'; import { DataCollectionVariableType } from '../../data_sources/model/data_collection/constants'; import { DataCollectionStateMap } from '../../data_sources/model/data_collection/types'; import DataResolverListener from '../../data_sources/model/DataResolverListener'; -import { - getDataResolverInstance, - getDataResolverInstanceValue, - isDataResolverProps, -} from '../../data_sources/model/utils'; +import { getDataResolverInstance, getDataResolverInstanceValue, isDataResolverProps } from '../../data_sources/utils'; import EditorModel from '../../editor/model/Editor'; import { DataResolverProps } from '../../data_sources/types'; import Component from './Component'; @@ -94,7 +90,7 @@ export class ComponentResolverWatcher { continue; } - const resolver = getDataResolverInstance(resolverProps, { em, collectionsStateMap }); + const resolver = getDataResolverInstance(resolverProps, { em, collectionsStateMap })!; this.resolverListeners[key] = new DataResolverListener({ em, resolver, diff --git a/packages/core/src/domain_abstract/model/StyleableModel.ts b/packages/core/src/domain_abstract/model/StyleableModel.ts index 4aa41e892..e70550a12 100644 --- a/packages/core/src/domain_abstract/model/StyleableModel.ts +++ b/packages/core/src/domain_abstract/model/StyleableModel.ts @@ -15,7 +15,7 @@ import { getDataResolverInstanceValue, isDataResolver, isDataResolverProps, -} from '../../data_sources/model/utils'; +} from '../../data_sources/utils'; import { DataResolver } from '../../data_sources/types'; export type StyleProps = Record; diff --git a/packages/core/src/utils/Dragger.ts b/packages/core/src/utils/Dragger.ts index 23c661cd0..c43afdf56 100644 --- a/packages/core/src/utils/Dragger.ts +++ b/packages/core/src/utils/Dragger.ts @@ -13,7 +13,7 @@ type Guide = { active?: boolean; }; -interface DraggerOptions { +export interface DraggerOptions { /** * Element on which the drag will be executed. By default, the document will be used */ diff --git a/packages/core/test/common.ts b/packages/core/test/common.ts index 58b754ffe..e14d11cf1 100644 --- a/packages/core/test/common.ts +++ b/packages/core/test/common.ts @@ -1,4 +1,11 @@ +import { DataSourceManager } from '../src'; import CanvasEvents from '../src/canvas/types'; +import { ObjectAny } from '../src/common'; +import { + DataConditionIfFalseType, + DataConditionIfTrueType, +} from '../src/data_sources/model/conditional_variables/constants'; +import { NumberOperation } from '../src/data_sources/model/conditional_variables/operators/NumberOperator'; import Editor from '../src/editor'; import { EditorConfig } from '../src/editor/config/config'; import EditorModel from '../src/editor/model/Editor'; @@ -97,3 +104,56 @@ export function filterObjectForSnapshot(obj: any, parentKey: string = ''): any { return result; } + +const baseComponent = { + type: 'text', + tagName: 'h1', +}; + +const createContent = (content: string) => ({ + ...baseComponent, + content, +}); + +/** + * Creates a component definition for a conditional component (ifTrue or ifFalse). + * @param type - The component type (e.g., DataConditionIfTrueType). + * @param content - The text content. + * @returns The component definition. + */ +const createConditionalComponentDef = (type: string, content: string) => ({ + type, + components: [createContent(content)], +}); + +export const ifTrueText = 'true text'; +export const newIfTrueText = 'new true text'; +export const ifFalseText = 'false text'; +export const newIfFalseText = 'new false text'; + +export const ifTrueComponentDef = createConditionalComponentDef(DataConditionIfTrueType, ifTrueText); +export const newIfTrueComponentDef = createConditionalComponentDef(DataConditionIfTrueType, newIfTrueText); +export const ifFalseComponentDef = createConditionalComponentDef(DataConditionIfFalseType, ifFalseText); +export const newIfFalseComponentDef = createConditionalComponentDef(DataConditionIfFalseType, newIfFalseText); + +export function isObjectContained(received: ObjectAny, expected: ObjectAny): boolean { + return Object.keys(expected).every((key) => { + if (typeof expected[key] === 'object' && expected[key] !== null) { + return isObjectContained(received[key], expected[key]); + } + + return received?.[key] === expected?.[key]; + }); +} + +export const TRUE_CONDITION = { + left: 1, + operator: NumberOperation.greaterThan, + right: 0, +}; + +export const FALSE_CONDITION = { + left: 0, + operator: NumberOperation.lessThan, + right: -1, +}; diff --git a/packages/core/test/specs/commands/index.ts b/packages/core/test/specs/commands/index.ts index 310369afa..14651266c 100644 --- a/packages/core/test/specs/commands/index.ts +++ b/packages/core/test/specs/commands/index.ts @@ -1,6 +1,6 @@ -import Commands from '../../../src/commands'; import EditorModel from '../../../src/editor/model/Editor'; -import { Command, CommandFunction } from '../../../src/commands/view/CommandAbstract'; +import type Commands from '../../../src/commands'; +import type { Command, CommandFunction, CommandOptions } from '../../../src/commands/view/CommandAbstract'; describe('Commands', () => { describe('Main', () => { @@ -94,5 +94,35 @@ describe('Commands', () => { expect(obj.isActive(commName)).toBe(false); expect(Object.keys(obj.getActive()).length).toBe(0); }); + + test('Run command and check if none, custom, and default options are passed', () => { + const customOptions = { customValue: 'customValue' }; + const defaultOptions = { defaultValue: 'defaultValue' }; + + // Create a function that returns the options + const runFn = (_editor: any, _sender: any, options: any) => options; + + // Add the command + obj.add(commName, { run: runFn }); + + // Run the command without custom options + let result = obj.run(commName); + expect(result).toEqual({}); + + // Run the command with custom options + result = obj.run(commName, customOptions); + expect(result).toEqual(customOptions); + + // Set default options for the command + obj.config.defaultOptions = { + [commName]: { + run: (options: CommandOptions) => ({ ...options, ...defaultOptions }), + }, + }; + + // Run the command with default options + result = obj.run(commName, customOptions); + expect(result).toEqual({ ...customOptions, ...defaultOptions }); + }); }); }); diff --git a/packages/core/test/specs/data_sources/__snapshots__/serialization.ts.snap b/packages/core/test/specs/data_sources/__snapshots__/serialization.ts.snap index 6e141da55..bbd79c1c5 100644 --- a/packages/core/test/specs/data_sources/__snapshots__/serialization.ts.snap +++ b/packages/core/test/specs/data_sources/__snapshots__/serialization.ts.snap @@ -13,8 +13,10 @@ exports[`DataSource Serialization .getProjectData ComponentDataVariable 1`] = ` { "components": [ { - "defaultValue": "default", - "path": "component-serialization.id1.content", + "dataResolver": { + "defaultValue": "default", + "path": "component-serialization.id1.content", + }, "type": "data-variable", }, ], diff --git a/packages/core/test/specs/data_sources/__snapshots__/storage.ts.snap b/packages/core/test/specs/data_sources/__snapshots__/storage.ts.snap index 4c29ba791..e1f65681d 100644 --- a/packages/core/test/specs/data_sources/__snapshots__/storage.ts.snap +++ b/packages/core/test/specs/data_sources/__snapshots__/storage.ts.snap @@ -23,8 +23,10 @@ exports[`DataSource Storage .getProjectData ComponentDataVariable 1`] = ` { "components": [ { - "defaultValue": "default", - "path": "component-storage.id1.content", + "dataResolver": { + "defaultValue": "default", + "path": "component-storage.id1.content", + }, "type": "data-variable", }, ], @@ -84,8 +86,10 @@ exports[`DataSource Storage .loadProjectData ComponentDataVariable 1`] = ` { "components": [ { - "defaultValue": "default", - "path": "component-storage.id1.content", + "dataResolver": { + "defaultValue": "default", + "path": "component-storage.id1.content", + }, "type": "data-variable", }, ], diff --git a/packages/core/test/specs/data_sources/jsonplaceholder.ts b/packages/core/test/specs/data_sources/jsonplaceholder.ts index 139113e45..b33468868 100644 --- a/packages/core/test/specs/data_sources/jsonplaceholder.ts +++ b/packages/core/test/specs/data_sources/jsonplaceholder.ts @@ -89,8 +89,7 @@ describe('JsonPlaceholder Usage', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `comments.${record?.id}.name`, + dataResolver: { defaultValue: 'default', path: `comments.${record?.id}.name` }, }, ], }, @@ -99,8 +98,7 @@ describe('JsonPlaceholder Usage', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `comments.${record?.id}.id`, + dataResolver: { defaultValue: 'default', path: `comments.${record?.id}.id` }, }, ], }, @@ -109,8 +107,7 @@ describe('JsonPlaceholder Usage', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `comments.${record?.id}.body`, + dataResolver: { defaultValue: 'default', path: `comments.${record?.id}.body` }, }, ], }, diff --git a/packages/core/test/specs/data_sources/model/ComponentDataVariable.getters-setters.ts b/packages/core/test/specs/data_sources/model/ComponentDataVariable.getters-setters.ts index de8cfd768..84a90fb59 100644 --- a/packages/core/test/specs/data_sources/model/ComponentDataVariable.getters-setters.ts +++ b/packages/core/test/specs/data_sources/model/ComponentDataVariable.getters-setters.ts @@ -30,8 +30,10 @@ describe('ComponentDataVariable - setPath and setDefaultValue', () => { test('component updates when path is changed using setPath', () => { const cmp = cmpRoot.append({ type: DataVariableType, - defaultValue: 'default', - path: 'ds_id.id1.name', + dataResolver: { + defaultValue: 'default', + path: 'ds_id.id1.name', + }, })[0] as ComponentDataVariable; expect(cmp.getEl()?.innerHTML).toContain('Name1'); @@ -45,8 +47,7 @@ describe('ComponentDataVariable - setPath and setDefaultValue', () => { test('component updates when default value is changed using setDefaultValue', () => { const cmp = cmpRoot.append({ type: DataVariableType, - defaultValue: 'default', - path: 'unknown.id1.name', + dataResolver: { defaultValue: 'default', path: 'unknown.id1.name' }, })[0] as ComponentDataVariable; expect(cmp.getEl()?.innerHTML).toContain('default'); @@ -60,8 +61,7 @@ describe('ComponentDataVariable - setPath and setDefaultValue', () => { test('component updates correctly after path and default value are changed', () => { const cmp = cmpRoot.append({ type: DataVariableType, - defaultValue: 'default', - path: 'ds_id.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds_id.id1.name' }, })[0] as ComponentDataVariable; expect(cmp.getEl()?.innerHTML).toContain('Name1'); @@ -78,8 +78,7 @@ describe('ComponentDataVariable - setPath and setDefaultValue', () => { test('component updates correctly after path is changed and data is updated', () => { const cmp = cmpRoot.append({ type: DataVariableType, - defaultValue: 'default', - path: 'ds_id.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds_id.id1.name' }, })[0] as ComponentDataVariable; expect(cmp.getEl()?.innerHTML).toContain('Name1'); diff --git a/packages/core/test/specs/data_sources/model/ComponentDataVariable.ts b/packages/core/test/specs/data_sources/model/ComponentDataVariable.ts index 6dcbee46b..8844ad155 100644 --- a/packages/core/test/specs/data_sources/model/ComponentDataVariable.ts +++ b/packages/core/test/specs/data_sources/model/ComponentDataVariable.ts @@ -1,7 +1,6 @@ import DataSourceManager from '../../../../src/data_sources'; import ComponentWrapper from '../../../../src/dom_components/model/ComponentWrapper'; import { DataVariableType } from '../../../../src/data_sources/model/DataVariable'; -import { DataSourceProps } from '../../../../src/data_sources/types'; import { setupTestEditor } from '../../../common'; import EditorModel from '../../../../src/editor/model/Editor'; @@ -31,8 +30,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'ds1.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds1.id1.name' }, }, ], })[0]; @@ -54,8 +52,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'ds2.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds2.id1.name' }, }, ], })[0]; @@ -77,8 +74,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'unknown.id1.name', + dataResolver: { defaultValue: 'default', path: 'unknown.id1.name' }, }, ], })[0]; @@ -99,8 +95,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'ds3.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds3.id1.name' }, }, ], })[0]; @@ -126,8 +121,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `${dataSource.id}.id1.name`, + dataResolver: { defaultValue: 'default', path: `${dataSource.id}.id1.name` }, }, ], })[0]; @@ -155,8 +149,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'ds4.id1.name', + dataResolver: { defaultValue: 'default', path: 'ds4.id1.name' }, }, ], })[0]; @@ -191,8 +184,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'dsNestedObject.id1.nestedObject.name', + dataResolver: { defaultValue: 'default', path: 'dsNestedObject.id1.nestedObject.name' }, }, ], })[0]; @@ -232,8 +224,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'dsNestedArray.id1.items.0.nestedObject.name', + dataResolver: { defaultValue: 'default', path: 'dsNestedArray.id1.items.0.nestedObject.name' }, }, ], })[0]; @@ -268,8 +259,7 @@ describe('ComponentDataVariable', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `${dataSource.id}.id1.content`, + dataResolver: { defaultValue: 'default', path: `${dataSource.id}.id1.content` }, }, ], style: { diff --git a/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.getters-setters.ts b/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.getters-setters.ts index 96eab39ff..e5af18d5c 100644 --- a/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.getters-setters.ts +++ b/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.getters-setters.ts @@ -1,22 +1,32 @@ -import { Component, DataSourceManager, Editor } from '../../../../../src'; +import { DataSourceManager } from '../../../../../src'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import ComponentDataCondition from '../../../../../src/data_sources/model/conditional_variables/ComponentDataCondition'; import { DataConditionType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; import { AnyTypeOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/AnyTypeOperator'; -import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import ComponentDataConditionView from '../../../../../src/data_sources/view/ComponentDataConditionView'; import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; import EditorModel from '../../../../../src/editor/model/Editor'; -import { setupTestEditor } from '../../../../common'; +import { + ifFalseText, + setupTestEditor, + ifTrueComponentDef, + ifFalseComponentDef, + newIfTrueText, + ifTrueText, + FALSE_CONDITION, + TRUE_CONDITION, + newIfFalseText, + newIfTrueComponentDef, + newIfFalseComponentDef, +} from '../../../../common'; describe('ComponentDataCondition Setters', () => { - let editor: Editor; let em: EditorModel; let dsm: DataSourceManager; let cmpRoot: ComponentWrapper; beforeEach(() => { - ({ editor, em, dsm, cmpRoot } = setupTestEditor()); + ({ em, dsm, cmpRoot } = setupTestEditor()); }); afterEach(() => { @@ -26,66 +36,42 @@ describe('ComponentDataCondition Setters', () => { it('should update the condition using setCondition', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: '

some text

', - ifFalse: '

false text

', + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], })[0] as ComponentDataCondition; - const newCondition = { - left: 1, - operator: NumberOperation.lessThan, - right: 0, - }; - - component.setCondition(newCondition); - expect(component.getCondition()).toEqual(newCondition); - expect(component.getInnerHTML()).toBe('

false text

'); + component.setCondition(FALSE_CONDITION); + expect(component.getCondition()).toEqual(FALSE_CONDITION); + expect(component.getInnerHTML()).toContain(ifFalseText); + expect(component.getEl()?.innerHTML).toContain(ifFalseText); }); - it('should update the ifTrue value using setIfTrue', () => { + it('should update the ifTrue value using setIfTrueComponents', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: '

some text

', - ifFalse: '

false text

', + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], })[0] as ComponentDataCondition; - const newIfTrue = '

new true text

'; - component.setIfTrue(newIfTrue); - expect(component.getIfTrue()).toEqual(newIfTrue); - expect(component.getInnerHTML()).toBe(newIfTrue); + component.setIfTrueComponents(newIfTrueComponentDef.components); + expect(JSON.parse(JSON.stringify(component.getIfTrueContent()))).toEqual(newIfTrueComponentDef); + expect(component.getInnerHTML()).toContain(newIfTrueText); + expect(component.getEl()?.innerHTML).toContain(newIfTrueText); }); - it('should update the ifFalse value using setIfFalse', () => { + it('should update the ifFalse value using setIfFalseComponents', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: '

some text

', - ifFalse: '

false text

', + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], })[0] as ComponentDataCondition; - const newIfFalse = '

new false text

'; - component.setIfFalse(newIfFalse); - expect(component.getIfFalse()).toEqual(newIfFalse); + component.setIfFalseComponents(newIfFalseComponentDef.components); + expect(JSON.parse(JSON.stringify(component.getIfFalseContent()))).toEqual(newIfFalseComponentDef); - component.setCondition({ - left: 0, - operator: NumberOperation.lessThan, - right: -1, - }); - expect(component.getInnerHTML()).toBe(newIfFalse); + component.setCondition(FALSE_CONDITION); + expect(component.getInnerHTML()).toContain(newIfFalseText); + expect(component.getEl()?.innerHTML).toContain(newIfFalseText); }); it('should update the data sources and re-evaluate the condition', () => { @@ -100,57 +86,54 @@ describe('ComponentDataCondition Setters', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: { - type: DataVariableType, - path: 'ds1.left_id.left', - }, - operator: AnyTypeOperation.equals, - right: { - type: DataVariableType, - path: 'ds1.right_id.right', + dataResolver: { + condition: { + left: { + type: DataVariableType, + path: 'ds1.left_id.left', + }, + operator: AnyTypeOperation.equals, + right: { + type: DataVariableType, + path: 'ds1.right_id.right', + }, }, }, - ifTrue: '

True value

', - ifFalse: '

False value

', + components: [ifTrueComponentDef, ifFalseComponentDef], })[0] as ComponentDataCondition; - expect(component.getInnerHTML()).toBe('

True value

'); + expect(component.getInnerHTML()).toContain(ifTrueText); changeDataSourceValue(dsm, 'Different value'); - expect(component.getInnerHTML()).toBe('

False value

'); + expect(component.getInnerHTML()).toContain(ifFalseText); + expect(component.getEl()?.innerHTML).toContain(ifFalseText); changeDataSourceValue(dsm, 'Name1'); - expect(component.getInnerHTML()).toBe('

True value

'); + expect(component.getInnerHTML()).toContain(ifTrueText); + expect(component.getEl()?.innerHTML).toContain(ifTrueText); }); it('should re-render the component when condition, ifTrue, or ifFalse changes', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: '

some text

', - ifFalse: '

false text

', + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], })[0] as ComponentDataCondition; const componentView = component.getView() as ComponentDataConditionView; - component.setIfTrue('

new true text

'); - expect(componentView.el.innerHTML).toContain('new true text'); + component.setIfTrueComponents(newIfTrueComponentDef); + + expect(component.getInnerHTML()).toContain(newIfTrueText); + expect(componentView.el.innerHTML).toContain(newIfTrueText); - component.setIfFalse('

new false text

'); - component.setCondition({ - left: 0, - operator: NumberOperation.lessThan, - right: -1, - }); - expect(componentView.el.innerHTML).toContain('new false text'); + component.setIfFalseComponents(newIfFalseComponentDef); + component.setCondition(FALSE_CONDITION); + expect(component.getInnerHTML()).toContain(newIfFalseText); + expect(componentView.el.innerHTML).toContain(newIfFalseText); }); }); -function changeDataSourceValue(dsm: DataSourceManager, newValue: string) { +export const changeDataSourceValue = (dsm: DataSourceManager, newValue: string) => { dsm.get('ds1').getRecord('left_id')?.set('left', newValue); -} +}; diff --git a/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.ts b/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.ts index 222e1bcd7..f3b1987b4 100644 --- a/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.ts +++ b/packages/core/test/specs/data_sources/model/conditional_variables/ComponentDataCondition.ts @@ -1,14 +1,23 @@ -import { Component, DataSourceManager, Editor } from '../../../../../src'; +import { Component, Components, ComponentView, DataSourceManager, Editor } from '../../../../../src'; +import { DataConditionIfTrueType } from '../../../../../src/data_sources/model/conditional_variables/constants'; import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; import { DataConditionType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; import { AnyTypeOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/AnyTypeOperator'; import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; import ComponentDataConditionView from '../../../../../src/data_sources/view/ComponentDataConditionView'; import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; -import ComponentTableView from '../../../../../src/dom_components/view/ComponentTableView'; -import ComponentTextView from '../../../../../src/dom_components/view/ComponentTextView'; import EditorModel from '../../../../../src/editor/model/Editor'; -import { setupTestEditor } from '../../../../common'; +import { + FALSE_CONDITION, + ifFalseComponentDef, + ifFalseText, + ifTrueComponentDef, + ifTrueText, + isObjectContained, + setupTestEditor, + TRUE_CONDITION, +} from '../../../../common'; +import ComponentDataCondition from '../../../../../src/data_sources/model/conditional_variables/ComponentDataCondition'; describe('ComponentDataCondition', () => { let editor: Editor; @@ -24,60 +33,34 @@ describe('ComponentDataCondition', () => { em.destroy(); }); - it('should add a component with a condition that evaluates a component definition', () => { + it('should add a component with a condition', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: { - tagName: 'h1', - type: 'text', - content: 'some text', - }, - })[0]; + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef], + })[0] as ComponentDataCondition; expect(component).toBeDefined(); expect(component.get('type')).toBe(DataConditionType); - expect(component.getInnerHTML()).toBe('

some text

'); const componentView = component.getView(); expect(componentView).toBeInstanceOf(ComponentDataConditionView); - expect(componentView?.el.textContent).toBe('some text'); - - const childComponent = getFirstChild(component); - const childView = getFirstChildView(component); - expect(childComponent).toBeDefined(); - expect(childComponent.get('type')).toBe('text'); - expect(childComponent.getInnerHTML()).toBe('some text'); - expect(childView).toBeInstanceOf(ComponentTextView); - expect(childView?.el.innerHTML).toBe('some text'); + + expect(component.getInnerHTML()).toContain(ifTrueText); + expect(component.getEl()?.innerHTML).toContain(ifTrueText); + const ifTrueContent = component.getIfTrueContent()!; + expect(ifTrueContent.getInnerHTML()).toContain(ifTrueText); + expect(ifTrueContent.getEl()?.textContent).toBe(ifTrueText); + expect(ifTrueContent.getEl()?.style.display).toBe(''); }); - it('should add a component with a condition that evaluates a string', () => { + it('ComponentDataCondition getIfTrueContent and getIfFalseContent', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: '

some text

', - })[0]; - expect(component).toBeDefined(); - expect(component.get('type')).toBe(DataConditionType); - expect(component.getInnerHTML()).toBe('

some text

'); - const componentView = component.getView(); - expect(componentView).toBeInstanceOf(ComponentDataConditionView); - expect(componentView?.el.textContent).toBe('some text'); - - const childComponent = getFirstChild(component); - const childView = getFirstChildView(component); - expect(childComponent).toBeDefined(); - expect(childComponent.get('type')).toBe('text'); - expect(childComponent.getInnerHTML()).toBe('some text'); - expect(childView).toBeInstanceOf(ComponentTextView); - expect(childView?.el.innerHTML).toBe('some text'); + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], + })[0] as ComponentDataCondition; + + expect(JSON.parse(JSON.stringify(component.getIfTrueContent()!))).toEqual(ifTrueComponentDef); + expect(JSON.parse(JSON.stringify(component.getIfFalseContent()!))).toEqual(ifFalseComponentDef); }); it('should test component variable with data-source', () => { @@ -92,41 +75,49 @@ describe('ComponentDataCondition', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: { - type: DataVariableType, - path: 'ds1.left_id.left', - }, - operator: AnyTypeOperation.equals, - right: { - type: DataVariableType, - path: 'ds1.right_id.right', + dataResolver: { + condition: { + left: { + type: DataVariableType, + path: 'ds1.left_id.left', + }, + operator: AnyTypeOperation.equals, + right: { + type: DataVariableType, + path: 'ds1.right_id.right', + }, }, }, - ifTrue: { - tagName: 'h1', - type: 'text', - content: 'Some value', - }, - ifFalse: { - tagName: 'h1', - type: 'text', - content: 'False value', - }, - })[0]; + components: [ifTrueComponentDef, ifFalseComponentDef], + })[0] as ComponentDataCondition; + expect(component.getInnerHTML()).toContain(ifTrueText); + expect(component.getEl()?.innerHTML).toContain(ifTrueText); + const ifTrueContent = component.getIfTrueContent()!; + expect(ifTrueContent.getInnerHTML()).toContain(ifTrueText); + expect(ifTrueContent.getEl()?.textContent).toBe(ifTrueText); + expect(ifTrueContent.getEl()?.style.display).toBe(''); - const childComponent = getFirstChild(component); - expect(childComponent).toBeDefined(); - expect(childComponent.get('type')).toBe('text'); - expect(childComponent.getInnerHTML()).toBe('Some value'); + expect(component.getInnerHTML()).not.toContain(ifFalseText); + expect(component.getEl()?.innerHTML).toContain(ifFalseText); + const ifFalseContent = component.getIfFalseContent()!; + expect(ifFalseContent.getInnerHTML()).toContain(ifFalseText); + expect(ifFalseContent.getEl()?.textContent).toBe(ifFalseText); + expect(ifFalseContent.getEl()?.style.display).toBe('none'); /* Test changing datasources */ - changeDataSourceValue(dsm, 'Diffirent value'); - expect(getFirstChild(component).getInnerHTML()).toBe('False value'); - expect(getFirstChildView(component)?.el.innerHTML).toBe('False value'); - changeDataSourceValue(dsm, 'Name1'); - expect(getFirstChild(component).getInnerHTML()).toBe('Some value'); - expect(getFirstChildView(component)?.el.innerHTML).toBe('Some value'); + const WrongValue = 'Diffirent value'; + changeDataSourceValue(dsm, WrongValue); + expect(component.getEl()?.innerHTML).toContain(ifTrueText); + expect(component.getEl()?.innerHTML).toContain(ifFalseText); + expect(ifTrueContent.getEl()?.style.display).toBe('none'); + expect(ifFalseContent.getEl()?.style.display).toBe(''); + + const CorrectValue = 'Name1'; + changeDataSourceValue(dsm, CorrectValue); + expect(component.getEl()?.innerHTML).toContain(ifTrueText); + expect(component.getEl()?.innerHTML).toContain(ifFalseText); + expect(ifTrueContent.getEl()?.style.display).toBe(''); + expect(ifFalseContent.getEl()?.style.display).toBe('none'); }); it('should test a conditional component with a child that is also a conditional component', () => { @@ -141,65 +132,54 @@ describe('ComponentDataCondition', () => { const component = cmpRoot.append({ type: DataConditionType, - condition: { - left: { - type: DataVariableType, - path: 'ds1.left_id.left', - }, - operator: AnyTypeOperation.equals, - right: { - type: DataVariableType, - path: 'ds1.right_id.right', + dataResolver: { + condition: { + left: { + type: DataVariableType, + path: 'ds1.left_id.left', + }, + operator: AnyTypeOperation.equals, + right: { + type: DataVariableType, + path: 'ds1.right_id.right', + }, }, }, - ifTrue: { - tagName: 'div', - components: [ - { + components: [ + { + type: DataConditionIfTrueType, + components: { type: DataConditionType, - condition: { - left: { - type: DataVariableType, - path: 'ds1.left_id.left', - }, - operator: AnyTypeOperation.equals, - right: { - type: DataVariableType, - path: 'ds1.right_id.right', + dataResolver: { + condition: { + left: { + type: DataVariableType, + path: 'ds1.left_id.left', + }, + operator: AnyTypeOperation.equals, + right: { + type: DataVariableType, + path: 'ds1.right_id.right', + }, }, }, - ifTrue: { - tagName: 'table', - type: 'table', - }, + components: ifTrueComponentDef, }, - ], - }, - })[0]; - - const innerComponent = getFirstChild(getFirstChild(component)); - const innerComponentView = getFirstChildView(innerComponent); - const innerHTML = '
'; - expect(innerComponent.getInnerHTML()).toBe(innerHTML); - expect(innerComponentView).toBeInstanceOf(ComponentTableView); - expect(innerComponentView?.el.tagName).toBe('TABLE'); + }, + ifFalseComponentDef, + ], + })[0] as ComponentDataCondition; + const ifTrueContent = component.getIfTrueContent()!; + expect(ifTrueContent.getInnerHTML()).toContain(ifTrueText); + expect(ifTrueContent.getEl()?.textContent).toBe(ifTrueText); + expect(ifTrueContent.getEl()?.style.display).toBe(''); }); it('should store conditional components', () => { const conditionalCmptDef = { type: DataConditionType, - condition: { - left: 0, - operator: NumberOperation.greaterThan, - right: -1, - }, - ifTrue: [ - { - tagName: 'h1', - type: 'text', - content: 'some text', - }, - ], + dataResolver: { condition: FALSE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], }; cmpRoot.append(conditionalCmptDef)[0]; @@ -208,18 +188,84 @@ describe('ComponentDataCondition', () => { const page = projectData.pages[0]; const frame = page.frames[0]; const storageCmptDef = frame.component.components[0]; - expect(storageCmptDef).toEqual(conditionalCmptDef); + expect(isObjectContained(storageCmptDef, conditionalCmptDef)).toBe(true); }); -}); -function changeDataSourceValue(dsm: DataSourceManager, newValue: string) { - dsm.get('ds1').getRecord('left_id')?.set('left', newValue); -} + it('should dynamically display ifTrue, ifFalse components in the correct order', () => { + const component = cmpRoot.append({ + type: DataConditionType, + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], + })[0] as ComponentDataCondition; + const el = component.getEl()!; + const ifTrueEl = el.childNodes[0] as any; + const ifFalseEl = el.childNodes[1] as any; + expect(ifTrueEl.textContent).toContain(ifTrueText); + expect(ifTrueEl.style.display).toBe(''); + expect(ifFalseEl.textContent).toContain(ifFalseText); + expect(ifFalseEl.style.display).toBe('none'); -function getFirstChildView(component: Component) { - return getFirstChild(component).getView(); -} + component.setCondition(FALSE_CONDITION); + expect(ifTrueEl.style.display).toBe('none'); + expect(ifTrueEl.textContent).toContain(ifTrueText); + expect(ifFalseEl.style.display).toBe(''); + expect(ifFalseEl.textContent).toContain(ifFalseText); + }); + + it('should dynamically update display components when data source changes', () => { + const dataSource = { + id: 'ds1', + records: [{ id: 'left_id', left: 1 }], + }; + dsm.add(dataSource); + + const component = cmpRoot.append({ + type: DataConditionType, + dataResolver: { + condition: { + left: { + type: DataVariableType, + path: 'ds1.left_id.left', + }, + operator: NumberOperation.greaterThan, + right: 0, + }, + }, + components: [ifTrueComponentDef, ifFalseComponentDef], + })[0] as ComponentDataCondition; + + const el = component.view!.el!; + const falseValue = -1; + changeDataSourceValue(dsm, falseValue); + expect(el.innerHTML).toContain(ifTrueText); + expect(el.innerHTML).toContain(ifFalseText); + + const ifTrueEl = el.childNodes[0] as any; + const ifFalseEl = el.childNodes[1] as any; + expect(ifTrueEl!.style.display).toBe('none'); + expect(ifTrueEl.textContent).toContain(ifTrueText); + expect(ifFalseEl.style.display).toBe(''); + expect(ifFalseEl.textContent).toContain(ifFalseText); + }); -function getFirstChild(component: Component) { - return component.components().at(0); + it('should update content of ifTrue, ifFalse components when condition changes', () => { + const component = cmpRoot.append({ + type: DataConditionType, + dataResolver: { condition: TRUE_CONDITION }, + components: [ifTrueComponentDef, ifFalseComponentDef], + })[0] as ComponentDataCondition; + const el = component.view!.el; + + component.setCondition(FALSE_CONDITION); + const ifTrueEl = el.childNodes[0] as any; + const ifFalseEl = el.childNodes[1] as any; + expect(ifTrueEl!.style.display).toBe('none'); + expect(ifTrueEl.textContent).toContain(ifTrueText); + expect(ifFalseEl.style.display).toBe(''); + expect(ifFalseEl.textContent).toContain(ifFalseText); + }); +}); + +function changeDataSourceValue(dsm: DataSourceManager, newValue: string | number) { + dsm.get('ds1').getRecord('left_id')?.set('left', newValue); } diff --git a/packages/core/test/specs/data_sources/serialization.ts b/packages/core/test/specs/data_sources/serialization.ts index 57c88471e..2f67b17e8 100644 --- a/packages/core/test/specs/data_sources/serialization.ts +++ b/packages/core/test/specs/data_sources/serialization.ts @@ -53,8 +53,7 @@ describe('DataSource Serialization', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: `${componentDataSource.id}.id1.content`, + dataResolver: { defaultValue: 'default', path: `${componentDataSource.id}.id1.content` }, }, ], })[0]; @@ -118,8 +117,7 @@ describe('DataSource Serialization', () => { test('ComponentDataVariable', () => { const dataVariable = { type: DataVariableType, - defaultValue: 'default', - path: `${componentDataSource.id}.id1.content`, + dataResolver: { defaultValue: 'default', path: `${componentDataSource.id}.id1.content` }, }; cmpRoot.append({ @@ -309,9 +307,9 @@ describe('DataSource Serialization', () => { { components: [ { - path: 'component-serialization.id1.content', - type: 'data-variable', value: 'default', + type: DataVariableType, + dataResolver: { path: 'component-serialization.id1.content' }, }, ], tagName: 'h1', @@ -403,7 +401,7 @@ describe('DataSource Serialization', () => { style: { color: { path: 'colors-data.id1.color', - type: 'data-variable', + type: DataVariableType, defaultValue: 'black', }, }, diff --git a/packages/core/test/specs/data_sources/storage.ts b/packages/core/test/specs/data_sources/storage.ts index 47ed85165..9d9475814 100644 --- a/packages/core/test/specs/data_sources/storage.ts +++ b/packages/core/test/specs/data_sources/storage.ts @@ -39,8 +39,7 @@ describe('DataSource Storage', () => { test('ComponentDataVariable', () => { const dataVariable = { type: DataVariableType, - defaultValue: 'default', - path: `${storedDataSource.id}.id1.content`, + dataResolver: { defaultValue: 'default', path: `${storedDataSource.id}.id1.content` }, }; cmpRoot.append({ @@ -87,9 +86,8 @@ describe('DataSource Storage', () => { { components: [ { - defaultValue: 'default', - path: `${storedDataSource.id}.id1.content`, - type: 'data-variable', + type: DataVariableType, + dataResolver: { defaultValue: 'default', path: `${storedDataSource.id}.id1.content` }, }, ], tagName: 'h1', diff --git a/packages/core/test/specs/data_sources/transformers.ts b/packages/core/test/specs/data_sources/transformers.ts index 6dbec0c0f..eecb75ee8 100644 --- a/packages/core/test/specs/data_sources/transformers.ts +++ b/packages/core/test/specs/data_sources/transformers.ts @@ -41,8 +41,7 @@ describe('DataSource Transformers', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'test-data-source.id1.content', + dataResolver: { defaultValue: 'default', path: 'test-data-source.id1.content' }, }, ], })[0]; @@ -85,8 +84,7 @@ describe('DataSource Transformers', () => { components: [ { type: DataVariableType, - defaultValue: 'default', - path: 'test-data-source.id1.content', + dataResolver: { defaultValue: 'default', path: 'test-data-source.id1.content' }, }, ], })[0]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 98942357d..5ca31c54e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,7 +61,7 @@ importers: version: 9.1.0(eslint@8.57.0) eslint-config-standard-with-typescript: specifier: 43.0.1 - version: 43.0.1(@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.10.2(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.5.4) + version: 43.0.1(@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.17.0(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.5.4) eslint-plugin-import: specifier: 2.29.1 version: 2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0) @@ -69,8 +69,8 @@ importers: specifier: 28.8.3 version: 28.8.3(@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(jest@29.7.0(@types/node@22.4.1)(ts-node@10.9.2(@types/node@22.4.1)(typescript@5.5.4)))(typescript@5.5.4) eslint-plugin-n: - specifier: 17.10.2 - version: 17.10.2(eslint@8.57.0) + specifier: 17.17.0 + version: 17.17.0(eslint@8.57.0) eslint-plugin-prettier: specifier: 5.2.1 version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3) @@ -90,8 +90,8 @@ importers: specifier: 29.2.4 version: 29.2.4(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@22.4.1)(ts-node@10.9.2(@types/node@22.4.1)(typescript@5.5.4)))(typescript@5.5.4) ts-loader: - specifier: 9.5.1 - version: 9.5.1(typescript@5.5.4)(webpack@5.94.0) + specifier: 9.5.2 + version: 9.5.2(typescript@5.5.4)(webpack@5.94.0) ts-node: specifier: 10.9.2 version: 10.9.2(@types/node@22.4.1)(typescript@5.5.4) @@ -145,8 +145,8 @@ importers: specifier: 7.25.2 version: 7.25.2 '@babel/plugin-transform-runtime': - specifier: 7.25.4 - version: 7.25.4(@babel/core@7.25.2) + specifier: 7.26.10 + version: 7.26.10(@babel/core@7.25.2) '@babel/preset-env': specifier: 7.25.4 version: 7.25.4(@babel/core@7.25.2) @@ -287,10 +287,18 @@ packages: resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.25.8': resolution: {integrity: sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + '@babel/core@7.25.2': resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} @@ -299,6 +307,10 @@ packages: resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} engines: {node: '>=6.9.0'} + '@babel/generator@7.26.10': + resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.25.7': resolution: {integrity: sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==} engines: {node: '>=6.9.0'} @@ -311,6 +323,10 @@ packages: resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.25.7': resolution: {integrity: sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==} engines: {node: '>=6.9.0'} @@ -328,12 +344,17 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/helper-define-polyfill-provider@0.6.4': + resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/helper-member-expression-to-functions@7.25.7': resolution: {integrity: sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.7': - resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} '@babel/helper-module-transforms@7.25.7': @@ -350,6 +371,10 @@ packages: resolution: {integrity: sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==} engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + '@babel/helper-remap-async-to-generator@7.25.7': resolution: {integrity: sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==} engines: {node: '>=6.9.0'} @@ -374,14 +399,26 @@ packages: resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.7': resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.7': resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + '@babel/helper-wrap-function@7.25.7': resolution: {integrity: sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==} engines: {node: '>=6.9.0'} @@ -399,6 +436,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.26.10': + resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.7': resolution: {integrity: sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==} engines: {node: '>=6.9.0'} @@ -807,8 +849,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-runtime@7.25.4': - resolution: {integrity: sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==} + '@babel/plugin-transform-runtime@7.26.10': + resolution: {integrity: sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -898,14 +940,26 @@ packages: resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} engines: {node: '>=6.9.0'} + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.25.7': resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.26.10': + resolution: {integrity: sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==} + engines: {node: '>=6.9.0'} + '@babel/types@7.25.8': resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} engines: {node: '>=6.9.0'} + '@babel/types@7.26.10': + resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -923,10 +977,20 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.11.1': resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1030,6 +1094,10 @@ packages: resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -2135,16 +2203,31 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-polyfill-corejs2@0.4.13: + resolution: {integrity: sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-polyfill-corejs3@0.10.6: resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-polyfill-regenerator@0.6.2: resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-polyfill-regenerator@0.6.4: + resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-preset-current-node-syntax@1.1.0: resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} peerDependencies: @@ -2270,6 +2353,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bs-logger@0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} engines: {node: '>= 6'} @@ -2382,6 +2470,9 @@ packages: caniuse-lite@1.0.30001669: resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} + caniuse-lite@1.0.30001707: + resolution: {integrity: sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==} + caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -2850,6 +2941,9 @@ packages: core-js-compat@3.38.1: resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + core-js@3.38.1: resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} @@ -3076,6 +3170,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} @@ -3337,6 +3440,9 @@ packages: engines: {node: '>=0.10.0'} hasBin: true + electron-to-chromium@1.5.123: + resolution: {integrity: sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==} + electron-to-chromium@1.5.41: resolution: {integrity: sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==} @@ -3387,6 +3493,10 @@ packages: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + entities@1.1.2: resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} @@ -3655,8 +3765,8 @@ packages: jest: optional: true - eslint-plugin-n@17.10.2: - resolution: {integrity: sha512-e+s4eAf5NtJaxPhTNu3qMO0Iz40WANS93w9LQgYcvuljgvDmWi/a3rh+OrNyMHeng6aOWGJO0rCg5lH4zi8yTw==} + eslint-plugin-n@17.17.0: + resolution: {integrity: sha512-2VvPK7Mo73z1rDFb6pTvkH6kFibAmnTubFq5l83vePxu0WiY1s0LOtj2WHb6Sa40R3w4mnh8GFYbHBQyMlotKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' @@ -4075,8 +4185,8 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-tsconfig@4.8.1: - resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} get-value@2.0.6: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} @@ -4149,8 +4259,8 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} - globals@15.11.0: - resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==} + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} globalthis@1.0.4: @@ -4671,6 +4781,10 @@ packages: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-data-descriptor@1.0.1: resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} engines: {node: '>= 0.4'} @@ -5136,6 +5250,11 @@ packages: engines: {node: '>=6'} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.0: resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} @@ -5326,6 +5445,7 @@ packages: lodash.template@4.5.0: resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. lodash.templatesettings@4.2.0: resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} @@ -5829,6 +5949,9 @@ packages: node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + nopt@1.0.10: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true @@ -6785,6 +6908,11 @@ packages: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -6951,6 +7079,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -7549,8 +7682,8 @@ packages: esbuild: optional: true - ts-loader@9.5.1: - resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} + ts-loader@9.5.2: + resolution: {integrity: sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==} engines: {node: '>=12.0.0'} peerDependencies: typescript: '*' @@ -7769,6 +7902,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + update-notifier@4.1.3: resolution: {integrity: sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==} engines: {node: '>=8'} @@ -8326,8 +8465,16 @@ snapshots: '@babel/highlight': 7.25.7 picocolors: 1.1.1 + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.25.8': {} + '@babel/compat-data@7.26.8': {} + '@babel/core@7.25.2': dependencies: '@ampproject/remapping': 2.3.0 @@ -8355,14 +8502,22 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 + '@babel/generator@7.26.10': + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.25.7': dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.26.10 '@babel/helper-builder-binary-assignment-operator-visitor@7.25.7': dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 transitivePeerDependencies: - supports-color @@ -8374,6 +8529,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-create-class-features-plugin@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -8382,7 +8545,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.25.7 '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.2) '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 - '@babel/traverse': 7.25.7 + '@babel/traverse': 7.26.10 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8398,31 +8561,42 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 debug: 4.3.7(supports-color@6.1.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: - supports-color + '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0 + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + '@babel/helper-member-expression-to-functions@7.25.7': dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.25.7': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 transitivePeerDependencies: - supports-color '@babel/helper-module-transforms@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.25.7 + '@babel/helper-module-imports': 7.25.9 '@babel/helper-simple-access': 7.25.7 '@babel/helper-validator-identifier': 7.25.7 '@babel/traverse': 7.25.7 @@ -8431,16 +8605,18 @@ snapshots: '@babel/helper-optimise-call-expression@7.25.7': dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.26.10 '@babel/helper-plugin-utils@7.25.7': {} + '@babel/helper-plugin-utils@7.26.5': {} + '@babel/helper-remap-async-to-generator@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.25.7 '@babel/helper-wrap-function': 7.25.7 - '@babel/traverse': 7.25.7 + '@babel/traverse': 7.26.10 transitivePeerDependencies: - supports-color @@ -8449,7 +8625,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-member-expression-to-functions': 7.25.7 '@babel/helper-optimise-call-expression': 7.25.7 - '@babel/traverse': 7.25.7 + '@babel/traverse': 7.26.10 transitivePeerDependencies: - supports-color @@ -8462,22 +8638,28 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.25.7': dependencies: - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.25.7': {} + '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-validator-identifier@7.25.7': {} + '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-option@7.25.7': {} + '@babel/helper-validator-option@7.25.9': {} + '@babel/helper-wrap-function@7.25.7': dependencies: - '@babel/template': 7.25.7 - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 transitivePeerDependencies: - supports-color @@ -8497,10 +8679,14 @@ snapshots: dependencies: '@babel/types': 7.25.8 + '@babel/parser@7.26.10': + dependencies: + '@babel/types': 7.26.10 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/traverse': 7.25.7 transitivePeerDependencies: - supports-color @@ -8508,17 +8694,17 @@ snapshots: '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 '@babel/plugin-transform-optional-chaining': 7.25.8(@babel/core@7.25.2) transitivePeerDependencies: @@ -8527,7 +8713,7 @@ snapshots: '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/traverse': 7.25.7 transitivePeerDependencies: - supports-color @@ -8536,7 +8722,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8544,7 +8730,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-decorators': 7.25.7(@babel/core@7.25.2) transitivePeerDependencies: - supports-color @@ -8556,123 +8742,123 @@ snapshots: '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-decorators@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-import-assertions@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-import-attributes@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-jsx@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-typescript@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-arrow-functions@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-async-generator-functions@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-remap-async-to-generator': 7.25.7(@babel/core@7.25.2) '@babel/traverse': 7.25.7 transitivePeerDependencies: @@ -8681,8 +8867,8 @@ snapshots: '@babel/plugin-transform-async-to-generator@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-remap-async-to-generator': 7.25.7(@babel/core@7.25.2) transitivePeerDependencies: - supports-color @@ -8690,18 +8876,18 @@ snapshots: '@babel/plugin-transform-block-scoped-functions@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-block-scoping@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-class-properties@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8709,7 +8895,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8718,7 +8904,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.25.7 '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.2) '@babel/traverse': 7.25.7 globals: 11.12.0 @@ -8728,53 +8914,53 @@ snapshots: '@babel/plugin-transform-computed-properties@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/template': 7.25.7 '@babel/plugin-transform-destructuring@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-dotall-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-duplicate-keys@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-dynamic-import@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-exponentiation-operator@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color '@babel/plugin-transform-export-namespace-from@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-for-of@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 transitivePeerDependencies: - supports-color @@ -8783,7 +8969,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/traverse': 7.25.7 transitivePeerDependencies: - supports-color @@ -8791,28 +8977,28 @@ snapshots: '@babel/plugin-transform-json-strings@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-literals@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-logical-assignment-operators@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-member-expression-literals@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-modules-amd@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8820,7 +9006,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-simple-access': 7.25.7 transitivePeerDependencies: - supports-color @@ -8829,7 +9015,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-identifier': 7.25.7 '@babel/traverse': 7.25.7 transitivePeerDependencies: @@ -8839,7 +9025,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8847,34 +9033,34 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-new-target@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-nullish-coalescing-operator@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-numeric-separator@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-object-rest-spread@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-parameters': 7.25.7(@babel/core@7.25.2) '@babel/plugin-transform-object-super@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.2) transitivePeerDependencies: - supports-color @@ -8882,12 +9068,12 @@ snapshots: '@babel/plugin-transform-optional-catch-binding@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-optional-chaining@7.25.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 transitivePeerDependencies: - supports-color @@ -8895,13 +9081,13 @@ snapshots: '@babel/plugin-transform-parameters@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-private-methods@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -8910,34 +9096,34 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.25.7 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color '@babel/plugin-transform-property-literals@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-regenerator@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 regenerator-transform: 0.15.2 '@babel/plugin-transform-reserved-words@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-runtime@7.25.4(@babel/core@7.25.2)': + '@babel/plugin-transform-runtime@7.26.10(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.2) - babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.2) - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.2) + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.25.2) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.25.2) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.25.2) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8945,12 +9131,12 @@ snapshots: '@babel/plugin-transform-shorthand-properties@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-spread@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 transitivePeerDependencies: - supports-color @@ -8958,24 +9144,24 @@ snapshots: '@babel/plugin-transform-sticky-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-template-literals@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-typeof-symbol@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-typescript@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.25.7 '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 '@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.25.2) transitivePeerDependencies: @@ -8984,25 +9170,25 @@ snapshots: '@babel/plugin-transform-unicode-escapes@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-unicode-property-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-unicode-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-transform-unicode-sets-regex@7.25.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.2) - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/preset-env@7.25.4(@babel/core@7.25.2)': dependencies: @@ -9096,7 +9282,7 @@ snapshots: '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@babel/types': 7.25.8 esutils: 2.0.3 @@ -9121,6 +9307,12 @@ snapshots: '@babel/parser': 7.25.8 '@babel/types': 7.25.8 + '@babel/template@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + '@babel/traverse@7.25.7': dependencies: '@babel/code-frame': 7.25.7 @@ -9133,12 +9325,29 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.26.10': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/types@7.25.8': dependencies: '@babel/helper-string-parser': 7.25.7 '@babel/helper-validator-identifier': 7.25.7 to-fast-properties: 2.0.0 + '@babel/types@7.26.10': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@bcoe/v8-coverage@0.2.3': {} '@cspotcode/source-map-support@0.8.1': @@ -9152,8 +9361,15 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.5.1(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.11.1': {} + '@eslint-community/regexpp@4.12.1': {} + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -9369,6 +9585,12 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} @@ -9529,24 +9751,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.25.8 - '@babel/types': 7.25.8 + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.26.10 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.25.8 - '@babel/types': 7.25.8 + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.25.8 + '@babel/types': 7.26.10 '@types/backbone@1.4.15': dependencies: @@ -9879,7 +10101,7 @@ snapshots: globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.6.3 + semver: 7.7.1 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 @@ -9894,7 +10116,7 @@ snapshots: fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.3 + semver: 7.7.1 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 @@ -9903,7 +10125,7 @@ snapshots: '@typescript-eslint/utils@8.10.0(eslint@8.57.0)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.0) '@typescript-eslint/scope-manager': 8.10.0 '@typescript-eslint/types': 8.10.0 '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.5.4) @@ -9930,12 +10152,12 @@ snapshots: '@vue/babel-plugin-jsx@1.2.5(@babel/core@7.25.2)': dependencies: - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.2) '@babel/template': 7.25.7 - '@babel/traverse': 7.25.7 - '@babel/types': 7.25.8 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 '@vue/babel-helper-vue-transform-on': 1.2.5 '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.25.2) html-tags: 3.3.1 @@ -9947,11 +10169,11 @@ snapshots: '@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.25.2)': dependencies: - '@babel/code-frame': 7.25.7 + '@babel/code-frame': 7.26.2 '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.25.7 - '@babel/helper-plugin-utils': 7.25.7 - '@babel/parser': 7.25.8 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/parser': 7.26.10 '@vue/compiler-sfc': 3.5.12 transitivePeerDependencies: - supports-color @@ -9959,7 +10181,7 @@ snapshots: '@vue/babel-plugin-transform-vue-jsx@1.4.0(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.25.7 + '@babel/helper-module-imports': 7.25.9 '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.2) '@vue/babel-helper-vue-jsx-merge-props': 1.4.0 html-tags: 2.0.0 @@ -9972,12 +10194,12 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.7 - '@babel/helper-module-imports': 7.25.7 + '@babel/helper-module-imports': 7.25.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.25.2) '@babel/plugin-proposal-decorators': 7.25.7(@babel/core@7.25.2) '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.2) - '@babel/plugin-transform-runtime': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-runtime': 7.26.10(@babel/core@7.25.2) '@babel/preset-env': 7.25.4(@babel/core@7.25.2) '@babel/runtime': 7.25.6 '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.25.2) @@ -10584,7 +10806,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.7(supports-color@6.1.0) + debug: 4.4.0 transitivePeerDependencies: - supports-color @@ -10888,7 +11110,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-plugin-utils': 7.26.5 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -10898,8 +11120,8 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.25.7 - '@babel/types': 7.25.8 + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 @@ -10912,6 +11134,15 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.25.2): + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.25.2) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -10920,6 +11151,14 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.25.2) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -10927,6 +11166,13 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color + babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -11134,6 +11380,13 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.0) + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001707 + electron-to-chromium: 1.5.123 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + bs-logger@0.2.6: dependencies: fast-json-stable-stringify: 2.1.0 @@ -11281,13 +11534,15 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.24.0 - caniuse-lite: 1.0.30001669 + browserslist: 4.24.4 + caniuse-lite: 1.0.30001707 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 caniuse-lite@1.0.30001669: {} + caniuse-lite@1.0.30001707: {} + caseless@0.12.0: {} ccount@2.0.1: {} @@ -11625,6 +11880,10 @@ snapshots: dependencies: browserslist: 4.24.0 + core-js-compat@3.41.0: + dependencies: + browserslist: 4.24.4 + core-js@3.38.1: {} core-util-is@1.0.2: {} @@ -11927,6 +12186,10 @@ snapshots: optionalDependencies: supports-color: 6.1.0 + debug@4.4.0: + dependencies: + ms: 2.1.3 + decamelize@1.2.0: {} decimal.js@10.4.3: {} @@ -12219,7 +12482,7 @@ snapshots: '@one-ini/wasm': 0.1.1 commander: 10.0.1 minimatch: 9.0.1 - semver: 7.6.3 + semver: 7.7.1 ee-first@1.1.1: {} @@ -12227,6 +12490,8 @@ snapshots: dependencies: jake: 10.9.2 + electron-to-chromium@1.5.123: {} + electron-to-chromium@1.5.41: {} elegant-spinner@1.0.1: {} @@ -12272,6 +12537,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.1 + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + entities@1.1.2: {} entities@2.2.0: {} @@ -12470,30 +12740,30 @@ snapshots: eslint-compat-utils@0.5.1(eslint@8.57.0): dependencies: eslint: 8.57.0 - semver: 7.6.3 + semver: 7.7.1 eslint-config-prettier@9.1.0(eslint@8.57.0): dependencies: eslint: 8.57.0 - eslint-config-standard-with-typescript@43.0.1(@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.10.2(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.5.4): + eslint-config-standard-with-typescript@43.0.1(@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.17.0(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.5.4): dependencies: '@typescript-eslint/eslint-plugin': 8.10.0(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 - eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.10.2(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0) + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.17.0(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0) - eslint-plugin-n: 17.10.2(eslint@8.57.0) + eslint-plugin-n: 17.17.0(eslint@8.57.0) eslint-plugin-promise: 7.1.0(eslint@8.57.0) typescript: 5.5.4 transitivePeerDependencies: - supports-color - eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.10.2(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0): + eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0))(eslint-plugin-n@17.17.0(eslint@8.57.0))(eslint-plugin-promise@7.1.0(eslint@8.57.0))(eslint@8.57.0): dependencies: eslint: 8.57.0 eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.10.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0) - eslint-plugin-n: 17.10.2(eslint@8.57.0) + eslint-plugin-n: 17.17.0(eslint@8.57.0) eslint-plugin-promise: 7.1.0(eslint@8.57.0) eslint-import-resolver-node@0.3.9: @@ -12516,8 +12786,8 @@ snapshots: eslint-plugin-es-x@7.8.0(eslint@8.57.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.11.1 + '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.0) + '@eslint-community/regexpp': 4.12.1 eslint: 8.57.0 eslint-compat-utils: 0.5.1(eslint@8.57.0) @@ -12559,17 +12829,17 @@ snapshots: - supports-color - typescript - eslint-plugin-n@17.10.2(eslint@8.57.0): + eslint-plugin-n@17.17.0(eslint@8.57.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - enhanced-resolve: 5.17.1 + '@eslint-community/eslint-utils': 4.5.1(eslint@8.57.0) + enhanced-resolve: 5.18.1 eslint: 8.57.0 eslint-plugin-es-x: 7.8.0(eslint@8.57.0) - get-tsconfig: 4.8.1 - globals: 15.11.0 + get-tsconfig: 4.10.0 + globals: 15.15.0 ignore: 5.3.2 minimatch: 9.0.5 - semver: 7.6.3 + semver: 7.7.1 eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3): dependencies: @@ -13099,7 +13369,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-tsconfig@4.8.1: + get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -13189,7 +13459,7 @@ snapshots: dependencies: type-fest: 0.20.2 - globals@15.11.0: {} + globals@15.15.0: {} globalthis@1.0.4: dependencies: @@ -13803,6 +14073,10 @@ snapshots: dependencies: hasown: 2.0.2 + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-data-descriptor@1.0.1: dependencies: hasown: 2.0.2 @@ -13992,7 +14266,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.25.2 - '@babel/parser': 7.25.8 + '@babel/parser': 7.26.10 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -14002,10 +14276,10 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.25.2 - '@babel/parser': 7.25.8 + '@babel/parser': 7.26.10 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -14017,7 +14291,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.7(supports-color@6.1.0) + debug: 4.4.0 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -14302,7 +14576,7 @@ snapshots: '@babel/generator': 7.25.7 '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.2) '@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.25.2) - '@babel/types': 7.25.8 + '@babel/types': 7.26.10 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -14317,7 +14591,7 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -14461,6 +14735,8 @@ snapshots: jsesc@3.0.2: {} + jsesc@3.1.0: {} + json-buffer@3.0.0: {} json-buffer@3.0.1: {} @@ -14740,7 +15016,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 make-error@1.3.6: {} @@ -15121,7 +15397,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.7(supports-color@6.1.0) + debug: 4.4.0 decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -15376,6 +15652,8 @@ snapshots: node-releases@2.0.18: {} + node-releases@2.0.19: {} + nopt@1.0.10: dependencies: abbrev: 1.1.1 @@ -15395,7 +15673,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.15.1 - semver: 7.6.3 + semver: 7.7.1 validate-npm-package-license: 3.0.4 normalize-path@2.1.1: @@ -15824,7 +16102,7 @@ snapshots: postcss-colormin@4.0.3: dependencies: - browserslist: 4.24.0 + browserslist: 4.24.4 color: 3.2.1 has: 1.0.4 postcss: 7.0.39 @@ -15872,7 +16150,7 @@ snapshots: postcss-merge-rules@4.0.3: dependencies: - browserslist: 4.24.0 + browserslist: 4.24.4 caniuse-api: 3.0.0 cssnano-util-same-parent: 4.0.1 postcss: 7.0.39 @@ -15894,7 +16172,7 @@ snapshots: postcss-minify-params@4.0.2: dependencies: alphanum-sort: 1.0.2 - browserslist: 4.24.0 + browserslist: 4.24.4 cssnano-util-get-arguments: 4.0.0 postcss: 7.0.39 postcss-value-parser: 3.3.1 @@ -15986,7 +16264,7 @@ snapshots: postcss-normalize-unicode@4.0.1: dependencies: - browserslist: 4.24.0 + browserslist: 4.24.4 postcss: 7.0.39 postcss-value-parser: 3.3.1 @@ -16010,7 +16288,7 @@ snapshots: postcss-reduce-initial@4.0.3: dependencies: - browserslist: 4.24.0 + browserslist: 4.24.4 caniuse-api: 3.0.0 has: 1.0.4 postcss: 7.0.39 @@ -16448,6 +16726,12 @@ snapshots: resolve.exports@2.0.2: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + resolve@1.22.8: dependencies: is-core-module: 2.15.1 @@ -16615,6 +16899,8 @@ snapshots: semver@7.6.3: {} + semver@7.7.1: {} + send@0.19.0(supports-color@6.1.0): dependencies: debug: 2.6.9(supports-color@6.1.0) @@ -17043,7 +17329,7 @@ snapshots: stylehacks@4.0.3: dependencies: - browserslist: 4.24.0 + browserslist: 4.24.4 postcss: 7.0.39 postcss-selector-parser: 3.1.2 @@ -17285,12 +17571,12 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.25.2) - ts-loader@9.5.1(typescript@5.5.4)(webpack@5.94.0): + ts-loader@9.5.2(typescript@5.5.4)(webpack@5.94.0): dependencies: chalk: 4.1.2 - enhanced-resolve: 5.17.1 + enhanced-resolve: 5.18.1 micromatch: 4.0.8 - semver: 7.6.3 + semver: 7.7.1 source-map: 0.7.4 typescript: 5.5.4 webpack: 5.94.0 @@ -17524,6 +17810,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + update-notifier@4.1.3: dependencies: boxen: 4.2.0