mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat(editor): Change rename node keyboard shortcut to Space on new canvas (#11872)
This commit is contained in:
@@ -50,7 +50,7 @@
|
|||||||
"@vue-flow/minimap": "^1.5.2",
|
"@vue-flow/minimap": "^1.5.2",
|
||||||
"@vue-flow/node-resizer": "^1.4.0",
|
"@vue-flow/node-resizer": "^1.4.0",
|
||||||
"@vueuse/components": "^10.11.0",
|
"@vueuse/components": "^10.11.0",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "catalog:frontend",
|
||||||
"axios": "catalog:",
|
"axios": "catalog:",
|
||||||
"bowser": "2.11.0",
|
"bowser": "2.11.0",
|
||||||
"change-case": "^5.4.4",
|
"change-case": "^5.4.4",
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function createCanvasNodeData({
|
|||||||
|
|
||||||
export function createCanvasNodeElement({
|
export function createCanvasNodeElement({
|
||||||
id = '1',
|
id = '1',
|
||||||
type = 'node',
|
type = 'default',
|
||||||
label = 'Node',
|
label = 'Node',
|
||||||
position = { x: 100, y: 100 },
|
position = { x: 100, y: 100 },
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { CanvasConnection, CanvasNode } from '@/types';
|
|||||||
import { createCanvasConnection, createCanvasNodeElement } from '@/__tests__/data';
|
import { createCanvasConnection, createCanvasNodeElement } from '@/__tests__/data';
|
||||||
import { NodeConnectionType } from 'n8n-workflow';
|
import { NodeConnectionType } from 'n8n-workflow';
|
||||||
import type { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
import type { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
||||||
|
import { useVueFlow } from '@vue-flow/core';
|
||||||
|
|
||||||
const matchMedia = global.window.matchMedia;
|
const matchMedia = global.window.matchMedia;
|
||||||
// @ts-expect-error Initialize window object
|
// @ts-expect-error Initialize window object
|
||||||
@@ -18,12 +19,21 @@ vi.mock('n8n-design-system', async (importOriginal) => {
|
|||||||
return { ...actual, useDeviceSupport: vi.fn(() => ({ isCtrlKeyPressed: vi.fn() })) };
|
return { ...actual, useDeviceSupport: vi.fn(() => ({ isCtrlKeyPressed: vi.fn() })) };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const canvasId = 'canvas';
|
||||||
|
|
||||||
let renderComponent: ReturnType<typeof createComponentRenderer>;
|
let renderComponent: ReturnType<typeof createComponentRenderer>;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
setActivePinia(pinia);
|
setActivePinia(pinia);
|
||||||
|
|
||||||
renderComponent = createComponentRenderer(Canvas, { pinia });
|
renderComponent = createComponentRenderer(Canvas, {
|
||||||
|
pinia,
|
||||||
|
props: {
|
||||||
|
id: canvasId,
|
||||||
|
nodes: [],
|
||||||
|
connections: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -86,7 +96,7 @@ describe('Canvas', () => {
|
|||||||
expect(container.querySelector(`[data-id="${connections[0].id}"]`)).toBeInTheDocument();
|
expect(container.querySelector(`[data-id="${connections[0].id}"]`)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle `update:nodes:position` event', async () => {
|
it('should emit `update:nodes:position` event', async () => {
|
||||||
const nodes = [createCanvasNodeElement()];
|
const nodes = [createCanvasNodeElement()];
|
||||||
const { container, emitted } = renderComponent({
|
const { container, emitted } = renderComponent({
|
||||||
props: {
|
props: {
|
||||||
@@ -122,6 +132,55 @@ describe('Canvas', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit `update:node:name` event', async () => {
|
||||||
|
const nodes = [createCanvasNodeElement()];
|
||||||
|
const { container, emitted } = renderComponent({
|
||||||
|
props: {
|
||||||
|
nodes,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(1));
|
||||||
|
|
||||||
|
const node = container.querySelector(`[data-id="${nodes[0].id}"]`) as Element;
|
||||||
|
|
||||||
|
const { addSelectedNodes, nodes: graphNodes } = useVueFlow({ id: canvasId });
|
||||||
|
addSelectedNodes(graphNodes.value);
|
||||||
|
|
||||||
|
await waitFor(() => expect(container.querySelector('.selected')).toBeInTheDocument());
|
||||||
|
|
||||||
|
await fireEvent.keyDown(node, { key: ' ', view: window });
|
||||||
|
await fireEvent.keyUp(node, { key: ' ', view: window });
|
||||||
|
|
||||||
|
expect(emitted()['update:node:name']).toEqual([['1']]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not emit `update:node:name` event if long key press', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const nodes = [createCanvasNodeElement()];
|
||||||
|
const { container, emitted } = renderComponent({
|
||||||
|
props: {
|
||||||
|
nodes,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(1));
|
||||||
|
|
||||||
|
const node = container.querySelector(`[data-id="${nodes[0].id}"]`) as Element;
|
||||||
|
|
||||||
|
const { addSelectedNodes, nodes: graphNodes } = useVueFlow({ id: canvasId });
|
||||||
|
addSelectedNodes(graphNodes.value);
|
||||||
|
|
||||||
|
await waitFor(() => expect(container.querySelector('.selected')).toBeInTheDocument());
|
||||||
|
|
||||||
|
await fireEvent.keyDown(node, { key: ' ', view: window });
|
||||||
|
await vi.advanceTimersByTimeAsync(1000);
|
||||||
|
await fireEvent.keyUp(node, { key: ' ', view: window });
|
||||||
|
|
||||||
|
expect(emitted()['update:node:name']).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
describe('minimap', () => {
|
describe('minimap', () => {
|
||||||
const minimapVisibilityDelay = 1000;
|
const minimapVisibilityDelay = 1000;
|
||||||
const minimapTransitionDuration = 300;
|
const minimapTransitionDuration = 300;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { computed, onMounted, onUnmounted, provide, ref, toRef, useCssModule, wa
|
|||||||
import type { EventBus } from 'n8n-design-system';
|
import type { EventBus } from 'n8n-design-system';
|
||||||
import { createEventBus } from 'n8n-design-system';
|
import { createEventBus } from 'n8n-design-system';
|
||||||
import { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
import { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
||||||
|
import { useShortKeyPress } from '@n8n/composables/useShortKeyPress';
|
||||||
import { useContextMenu, type ContextMenuAction } from '@/composables/useContextMenu';
|
import { useContextMenu, type ContextMenuAction } from '@/composables/useContextMenu';
|
||||||
import { useKeybindings } from '@/composables/useKeybindings';
|
import { useKeybindings } from '@/composables/useKeybindings';
|
||||||
import ContextMenu from '@/components/ContextMenu/ContextMenu.vue';
|
import ContextMenu from '@/components/ContextMenu/ContextMenu.vue';
|
||||||
@@ -145,29 +146,55 @@ const classes = computed(() => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key bindings
|
* Panning and Selection key bindings
|
||||||
*/
|
|
||||||
|
|
||||||
const disableKeyBindings = computed(() => !props.keyBindings);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#whitespace_keys
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#whitespace_keys
|
||||||
const panningKeyCode = ref<string[] | true>(isMobileDevice ? true : [' ', controlKeyCode]);
|
const panningKeyCode = ref<string[] | true>(isMobileDevice ? true : [' ', controlKeyCode]);
|
||||||
const panningMouseButton = ref<number[] | true>(isMobileDevice ? true : [1]);
|
const panningMouseButton = ref<number[] | true>(isMobileDevice ? true : [1]);
|
||||||
const selectionKeyCode = ref<string | true | null>(isMobileDevice ? 'Shift' : true);
|
const selectionKeyCode = ref<string | true | null>(isMobileDevice ? 'Shift' : true);
|
||||||
|
|
||||||
onKeyDown(panningKeyCode.value, () => {
|
onKeyDown(
|
||||||
selectionKeyCode.value = null;
|
panningKeyCode.value,
|
||||||
panningMouseButton.value = [0, 1];
|
() => {
|
||||||
});
|
selectionKeyCode.value = null;
|
||||||
|
panningMouseButton.value = [0, 1];
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dedupe: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
onKeyUp(panningKeyCode.value, () => {
|
onKeyUp(panningKeyCode.value, () => {
|
||||||
selectionKeyCode.value = true;
|
selectionKeyCode.value = true;
|
||||||
panningMouseButton.value = [1];
|
panningMouseButton.value = [1];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename node key bindings
|
||||||
|
* We differentiate between short and long press because the space key is also used for activating panning
|
||||||
|
*/
|
||||||
|
|
||||||
|
const renameKeyCode = ' ';
|
||||||
|
|
||||||
|
useShortKeyPress(
|
||||||
|
renameKeyCode,
|
||||||
|
() => {
|
||||||
|
if (lastSelectedNode.value) {
|
||||||
|
emit('update:node:name', lastSelectedNode.value.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
disabled: toRef(props, 'readOnly'),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key bindings
|
||||||
|
*/
|
||||||
|
|
||||||
|
const disableKeyBindings = computed(() => !props.keyBindings);
|
||||||
|
|
||||||
function selectLeftNode(id: string) {
|
function selectLeftNode(id: string) {
|
||||||
const incomingNodes = getIncomingNodes(id);
|
const incomingNodes = getIncomingNodes(id);
|
||||||
const previousNode = incomingNodes[0];
|
const previousNode = incomingNodes[0];
|
||||||
|
|||||||
@@ -745,6 +745,9 @@ function onRenameNode(parameterData: IUpdateInformation) {
|
|||||||
|
|
||||||
async function onOpenRenameNodeModal(id: string) {
|
async function onOpenRenameNodeModal(id: string) {
|
||||||
const currentName = workflowsStore.getNodeById(id)?.name ?? '';
|
const currentName = workflowsStore.getNodeById(id)?.name ?? '';
|
||||||
|
|
||||||
|
if (!keyBindingsEnabled.value || document.querySelector('.rename-prompt')) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const promptResponsePromise = message.prompt(
|
const promptResponsePromise = message.prompt(
|
||||||
i18n.baseText('nodeView.prompt.newName') + ':',
|
i18n.baseText('nodeView.prompt.newName') + ':',
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
"format": "biome format --write . && prettier --write . --ignore-path ../../../../.prettierignore",
|
"format": "biome format --write . && prettier --write . --ignore-path ../../../../.prettierignore",
|
||||||
"format:check": "biome ci . && prettier --check . --ignore-path ../../../../.prettierignore"
|
"format:check": "biome ci . && prettier --check . --ignore-path ../../../../.prettierignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
|
||||||
"vue": "catalog:frontend"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@n8n/frontend-eslint-config": "workspace:*",
|
"@n8n/frontend-eslint-config": "workspace:*",
|
||||||
"@n8n/frontend-typescript-config": "workspace:*",
|
"@n8n/frontend-typescript-config": "workspace:*",
|
||||||
@@ -36,6 +33,8 @@
|
|||||||
"@testing-library/vue": "catalog:frontend",
|
"@testing-library/vue": "catalog:frontend",
|
||||||
"@vitejs/plugin-vue": "catalog:frontend",
|
"@vitejs/plugin-vue": "catalog:frontend",
|
||||||
"@vue/tsconfig": "catalog:frontend",
|
"@vue/tsconfig": "catalog:frontend",
|
||||||
|
"@vueuse/core": "catalog:frontend",
|
||||||
|
"vue": "catalog:frontend",
|
||||||
"tsup": "catalog:frontend",
|
"tsup": "catalog:frontend",
|
||||||
"typescript": "catalog:frontend",
|
"typescript": "catalog:frontend",
|
||||||
"vite": "catalog:frontend",
|
"vite": "catalog:frontend",
|
||||||
@@ -43,5 +42,9 @@
|
|||||||
"vitest": "catalog:frontend",
|
"vitest": "catalog:frontend",
|
||||||
"vue-tsc": "catalog:frontend"
|
"vue-tsc": "catalog:frontend"
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vueuse/core": "catalog:frontend",
|
||||||
|
"vue": "catalog:frontend"
|
||||||
|
},
|
||||||
"license": "See LICENSE.md file in the root of the repository"
|
"license": "See LICENSE.md file in the root of the repository"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { onKeyDown, onKeyUp } from '@vueuse/core';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { useShortKeyPress } from './useShortKeyPress';
|
||||||
|
|
||||||
|
vi.mock('@vueuse/core', () => ({
|
||||||
|
onKeyDown: vi.fn(),
|
||||||
|
onKeyUp: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('useShortKeyPress', () => {
|
||||||
|
it('should call the function on short key press', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const fn = vi.fn();
|
||||||
|
const key = 'a';
|
||||||
|
const threshold = 300;
|
||||||
|
const disabled = ref(false);
|
||||||
|
|
||||||
|
useShortKeyPress(key, fn, { threshold, disabled });
|
||||||
|
|
||||||
|
const keyDownHandler = vi.mocked(onKeyDown).mock.calls[0][1];
|
||||||
|
const keyUpHandler = vi.mocked(onKeyUp).mock.calls[0][1];
|
||||||
|
|
||||||
|
keyDownHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
await vi.advanceTimersByTimeAsync(100);
|
||||||
|
keyUpHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the function if key press duration exceeds threshold', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const fn = vi.fn();
|
||||||
|
const key = 'a';
|
||||||
|
const threshold = 300;
|
||||||
|
const disabled = ref(false);
|
||||||
|
|
||||||
|
useShortKeyPress(key, fn, { threshold, disabled });
|
||||||
|
|
||||||
|
const keyDownHandler = vi.mocked(onKeyDown).mock.calls[0][1];
|
||||||
|
const keyUpHandler = vi.mocked(onKeyUp).mock.calls[0][1];
|
||||||
|
|
||||||
|
keyDownHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
await vi.advanceTimersByTimeAsync(400);
|
||||||
|
keyUpHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call the function if disabled is true', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const fn = vi.fn();
|
||||||
|
const key = 'a';
|
||||||
|
const threshold = 300;
|
||||||
|
const disabled = ref(true);
|
||||||
|
|
||||||
|
useShortKeyPress(key, fn, { threshold, disabled });
|
||||||
|
|
||||||
|
const keyDownHandler = vi.mocked(onKeyDown).mock.calls[0][1];
|
||||||
|
const keyUpHandler = vi.mocked(onKeyUp).mock.calls[0][1];
|
||||||
|
|
||||||
|
keyDownHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
await vi.advanceTimersByTimeAsync(100);
|
||||||
|
keyUpHandler(new KeyboardEvent('keydown', { key }));
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
41
packages/frontend/@n8n/composables/src/useShortKeyPress.ts
Normal file
41
packages/frontend/@n8n/composables/src/useShortKeyPress.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { onKeyDown, onKeyUp } from '@vueuse/core';
|
||||||
|
import type { KeyFilter } from '@vueuse/core';
|
||||||
|
import { ref, unref } from 'vue';
|
||||||
|
import type { MaybeRefOrGetter } from 'vue';
|
||||||
|
|
||||||
|
export function useShortKeyPress(
|
||||||
|
key: KeyFilter,
|
||||||
|
fn: () => void,
|
||||||
|
{
|
||||||
|
dedupe = true,
|
||||||
|
threshold = 300,
|
||||||
|
disabled = false,
|
||||||
|
}: {
|
||||||
|
dedupe?: boolean;
|
||||||
|
threshold?: number;
|
||||||
|
disabled?: MaybeRefOrGetter<boolean>;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const keyDownTime = ref<number | null>(null);
|
||||||
|
|
||||||
|
onKeyDown(
|
||||||
|
key,
|
||||||
|
() => {
|
||||||
|
if (unref(disabled)) return;
|
||||||
|
|
||||||
|
keyDownTime.value = Date.now();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dedupe,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
onKeyUp(key, () => {
|
||||||
|
if (unref(disabled) || !keyDownTime.value) return;
|
||||||
|
|
||||||
|
const isShortPress = Date.now() - keyDownTime.value < threshold;
|
||||||
|
if (isShortPress) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@@ -97,6 +97,9 @@ catalogs:
|
|||||||
'@vue/tsconfig':
|
'@vue/tsconfig':
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
|
'@vueuse/core':
|
||||||
|
specifier: ^10.11.0
|
||||||
|
version: 10.11.0
|
||||||
highlight.js:
|
highlight.js:
|
||||||
specifier: ^11.8.0
|
specifier: ^11.8.0
|
||||||
version: 11.9.0
|
version: 11.9.0
|
||||||
@@ -1490,7 +1493,7 @@ importers:
|
|||||||
specifier: ^10.11.0
|
specifier: ^10.11.0
|
||||||
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vueuse/core':
|
'@vueuse/core':
|
||||||
specifier: ^10.11.0
|
specifier: catalog:frontend
|
||||||
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
||||||
axios:
|
axios:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
@@ -1702,10 +1705,6 @@ importers:
|
|||||||
version: 2.1.10(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.7.2)
|
version: 2.1.10(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.7.2)
|
||||||
|
|
||||||
packages/frontend/@n8n/composables:
|
packages/frontend/@n8n/composables:
|
||||||
dependencies:
|
|
||||||
vue:
|
|
||||||
specifier: catalog:frontend
|
|
||||||
version: 3.5.13(typescript@5.7.2)
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@n8n/frontend-eslint-config':
|
'@n8n/frontend-eslint-config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
@@ -1731,6 +1730,9 @@ importers:
|
|||||||
'@vue/tsconfig':
|
'@vue/tsconfig':
|
||||||
specifier: catalog:frontend
|
specifier: catalog:frontend
|
||||||
version: 0.7.0(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))
|
version: 0.7.0(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))
|
||||||
|
'@vueuse/core':
|
||||||
|
specifier: catalog:frontend
|
||||||
|
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
||||||
tsup:
|
tsup:
|
||||||
specifier: catalog:frontend
|
specifier: catalog:frontend
|
||||||
version: 8.3.6(@microsoft/api-extractor@7.48.0(@types/node@18.16.16))(jiti@1.21.0)(postcss@8.4.49)(typescript@5.7.2)
|
version: 8.3.6(@microsoft/api-extractor@7.48.0(@types/node@18.16.16))(jiti@1.21.0)(postcss@8.4.49)(typescript@5.7.2)
|
||||||
@@ -1746,6 +1748,9 @@ importers:
|
|||||||
vitest:
|
vitest:
|
||||||
specifier: catalog:frontend
|
specifier: catalog:frontend
|
||||||
version: 3.0.5(@types/debug@4.1.12)(@types/node@18.16.16)(jiti@1.21.0)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1)
|
version: 3.0.5(@types/debug@4.1.12)(@types/node@18.16.16)(jiti@1.21.0)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1)
|
||||||
|
vue:
|
||||||
|
specifier: catalog:frontend
|
||||||
|
version: 3.5.13(typescript@5.7.2)
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^2.1.10
|
specifier: ^2.1.10
|
||||||
version: 2.1.10(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.7.2)
|
version: 2.1.10(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.7.2)
|
||||||
@@ -13329,8 +13334,8 @@ packages:
|
|||||||
vue-component-type-helpers@2.1.10:
|
vue-component-type-helpers@2.1.10:
|
||||||
resolution: {integrity: sha512-lfgdSLQKrUmADiSV6PbBvYgQ33KF3Ztv6gP85MfGaGaSGMTXORVaHT1EHfsqCgzRNBstPKYDmvAV9Do5CmJ07A==}
|
resolution: {integrity: sha512-lfgdSLQKrUmADiSV6PbBvYgQ33KF3Ztv6gP85MfGaGaSGMTXORVaHT1EHfsqCgzRNBstPKYDmvAV9Do5CmJ07A==}
|
||||||
|
|
||||||
vue-component-type-helpers@2.2.0:
|
vue-component-type-helpers@2.2.2:
|
||||||
resolution: {integrity: sha512-cYrAnv2me7bPDcg9kIcGwjJiSB6Qyi08+jLDo9yuvoFQjzHiPTzML7RnkJB1+3P6KMsX/KbCD4QE3Tv/knEllw==}
|
resolution: {integrity: sha512-6lLY+n2xz2kCYshl59mL6gy8OUUTmkscmDFMO8i7Lj+QKwgnIFUZmM1i/iTYObtrczZVdw7UakPqDTGwVSGaRg==}
|
||||||
|
|
||||||
vue-demi@0.14.10:
|
vue-demi@0.14.10:
|
||||||
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||||
@@ -18482,7 +18487,7 @@ snapshots:
|
|||||||
ts-dedent: 2.2.0
|
ts-dedent: 2.2.0
|
||||||
type-fest: 2.19.0
|
type-fest: 2.19.0
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
vue-component-type-helpers: 2.2.0
|
vue-component-type-helpers: 2.2.2
|
||||||
|
|
||||||
'@supabase/auth-js@2.65.0':
|
'@supabase/auth-js@2.65.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -19509,7 +19514,7 @@ snapshots:
|
|||||||
'@vue/test-utils@2.4.6':
|
'@vue/test-utils@2.4.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
js-beautify: 1.14.9
|
js-beautify: 1.14.9
|
||||||
vue-component-type-helpers: 2.2.0
|
vue-component-type-helpers: 2.2.2
|
||||||
|
|
||||||
'@vue/tsconfig@0.7.0(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))':
|
'@vue/tsconfig@0.7.0(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -27795,7 +27800,7 @@ snapshots:
|
|||||||
|
|
||||||
vue-component-type-helpers@2.1.10: {}
|
vue-component-type-helpers@2.1.10: {}
|
||||||
|
|
||||||
vue-component-type-helpers@2.2.0: {}
|
vue-component-type-helpers@2.2.2: {}
|
||||||
|
|
||||||
vue-demi@0.14.10(vue@3.5.13(typescript@5.7.2)):
|
vue-demi@0.14.10(vue@3.5.13(typescript@5.7.2)):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ catalogs:
|
|||||||
'@testing-library/user-event': ^14.6.0
|
'@testing-library/user-event': ^14.6.0
|
||||||
'@testing-library/vue': ^8.1.0
|
'@testing-library/vue': ^8.1.0
|
||||||
'@vue/tsconfig': ^0.7.0
|
'@vue/tsconfig': ^0.7.0
|
||||||
|
'@vueuse/core': ^10.11.0
|
||||||
'@vitest/coverage-v8': ^3.0.5
|
'@vitest/coverage-v8': ^3.0.5
|
||||||
'@vitejs/plugin-vue': ^5.2.1
|
'@vitejs/plugin-vue': ^5.2.1
|
||||||
'@sentry/vue': ^8.33.1
|
'@sentry/vue': ^8.33.1
|
||||||
|
|||||||
Reference in New Issue
Block a user