@n8n/composables 1.29.2 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/useDeviceSupport.d.cts +2 -2
- package/dist/useElementOverflow.cjs +33 -0
- package/dist/useElementOverflow.cjs.map +1 -0
- package/dist/useElementOverflow.d.cts +11 -0
- package/dist/useElementOverflow.d.mts +11 -0
- package/dist/useElementOverflow.mjs +32 -0
- package/dist/useElementOverflow.mjs.map +1 -0
- package/dist/useToast.cjs.map +1 -1
- package/dist/useToast.mjs.map +1 -1
- package/package.json +8 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as vue3 from "vue";
|
|
2
2
|
|
|
3
3
|
//#region src/useDeviceSupport.d.ts
|
|
4
4
|
declare function useDeviceSupport(): {
|
|
@@ -9,7 +9,7 @@ declare function useDeviceSupport(): {
|
|
|
9
9
|
isMacOs: boolean;
|
|
10
10
|
isMobileDevice: boolean;
|
|
11
11
|
controlKeyCode: string;
|
|
12
|
-
controlKeyText:
|
|
12
|
+
controlKeyText: vue3.ComputedRef<"⌘" | "Ctrl">;
|
|
13
13
|
isCtrlKeyPressed: (e: MouseEvent | KeyboardEvent) => boolean;
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_useDebounce = require('./useDebounce.cjs');
|
|
2
|
+
let vue = require("vue");
|
|
3
|
+
|
|
4
|
+
//#region src/useElementOverflow.ts
|
|
5
|
+
/** Whether the content is clipped along one axis. Re-checks on resize and when `sources` change. */
|
|
6
|
+
function useElementOverflow(element, axis, sources = []) {
|
|
7
|
+
const isOverflowing = (0, vue.ref)(false);
|
|
8
|
+
let observer = null;
|
|
9
|
+
const update = () => {
|
|
10
|
+
const el = element.value;
|
|
11
|
+
if (!el) return;
|
|
12
|
+
isOverflowing.value = axis === "x" ? el.scrollWidth > el.clientWidth : el.scrollHeight > el.clientHeight;
|
|
13
|
+
};
|
|
14
|
+
(0, vue.onMounted)(() => {
|
|
15
|
+
update();
|
|
16
|
+
if (element.value && typeof ResizeObserver !== "undefined") {
|
|
17
|
+
observer = new ResizeObserver(update);
|
|
18
|
+
observer.observe(element.value);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
if (sources.length > 0) (0, vue.watch)(sources, update, { flush: "post" });
|
|
22
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
23
|
+
observer?.disconnect();
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
isOverflowing,
|
|
27
|
+
update
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.useElementOverflow = useElementOverflow;
|
|
33
|
+
//# sourceMappingURL=useElementOverflow.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useElementOverflow.cjs","names":["observer: ResizeObserver | null"],"sources":["../src/useElementOverflow.ts"],"sourcesContent":["import { onBeforeUnmount, onMounted, ref, watch, type Ref, type WatchSource } from 'vue';\n\nexport type OverflowAxis = 'x' | 'y';\n\n/** Whether the content is clipped along one axis. Re-checks on resize and when `sources` change. */\nexport function useElementOverflow(\n\telement: Ref<HTMLElement | null>,\n\taxis: OverflowAxis,\n\tsources: WatchSource[] = [],\n) {\n\tconst isOverflowing = ref(false);\n\n\tlet observer: ResizeObserver | null = null;\n\n\tconst update = () => {\n\t\tconst el = element.value;\n\t\tif (!el) return;\n\t\tisOverflowing.value =\n\t\t\taxis === 'x' ? el.scrollWidth > el.clientWidth : el.scrollHeight > el.clientHeight;\n\t};\n\n\tonMounted(() => {\n\t\tupdate();\n\t\tif (element.value && typeof ResizeObserver !== 'undefined') {\n\t\t\tobserver = new ResizeObserver(update);\n\t\t\tobserver.observe(element.value);\n\t\t}\n\t});\n\n\tif (sources.length > 0) {\n\t\twatch(sources, update, { flush: 'post' });\n\t}\n\n\tonBeforeUnmount(() => {\n\t\tobserver?.disconnect();\n\t});\n\n\treturn { isOverflowing, update };\n}\n"],"mappings":";;;;;AAKA,SAAgB,mBACf,SACA,MACA,UAAyB,EAAE,EAC1B;CACD,MAAM,6BAAoB,MAAM;CAEhC,IAAIA,WAAkC;CAEtC,MAAM,eAAe;EACpB,MAAM,KAAK,QAAQ;AACnB,MAAI,CAAC,GAAI;AACT,gBAAc,QACb,SAAS,MAAM,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,GAAG;;AAGxE,0BAAgB;AACf,UAAQ;AACR,MAAI,QAAQ,SAAS,OAAO,mBAAmB,aAAa;AAC3D,cAAW,IAAI,eAAe,OAAO;AACrC,YAAS,QAAQ,QAAQ,MAAM;;GAE/B;AAEF,KAAI,QAAQ,SAAS,EACpB,gBAAM,SAAS,QAAQ,EAAE,OAAO,QAAQ,CAAC;AAG1C,gCAAsB;AACrB,YAAU,YAAY;GACrB;AAEF,QAAO;EAAE;EAAe;EAAQ"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Ref, WatchSource } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/useElementOverflow.d.ts
|
|
4
|
+
type OverflowAxis = 'x' | 'y';
|
|
5
|
+
declare function useElementOverflow(element: Ref<HTMLElement | null>, axis: OverflowAxis, sources?: WatchSource[]): {
|
|
6
|
+
isOverflowing: Ref<boolean, boolean>;
|
|
7
|
+
update: () => void;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { OverflowAxis, useElementOverflow };
|
|
11
|
+
//# sourceMappingURL=useElementOverflow.d.cts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Ref, WatchSource } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/useElementOverflow.d.ts
|
|
4
|
+
type OverflowAxis = 'x' | 'y';
|
|
5
|
+
declare function useElementOverflow(element: Ref<HTMLElement | null>, axis: OverflowAxis, sources?: WatchSource[]): {
|
|
6
|
+
isOverflowing: Ref<boolean, boolean>;
|
|
7
|
+
update: () => void;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { OverflowAxis, useElementOverflow };
|
|
11
|
+
//# sourceMappingURL=useElementOverflow.d.mts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/useElementOverflow.ts
|
|
4
|
+
/** Whether the content is clipped along one axis. Re-checks on resize and when `sources` change. */
|
|
5
|
+
function useElementOverflow(element, axis, sources = []) {
|
|
6
|
+
const isOverflowing = ref(false);
|
|
7
|
+
let observer = null;
|
|
8
|
+
const update = () => {
|
|
9
|
+
const el = element.value;
|
|
10
|
+
if (!el) return;
|
|
11
|
+
isOverflowing.value = axis === "x" ? el.scrollWidth > el.clientWidth : el.scrollHeight > el.clientHeight;
|
|
12
|
+
};
|
|
13
|
+
onMounted(() => {
|
|
14
|
+
update();
|
|
15
|
+
if (element.value && typeof ResizeObserver !== "undefined") {
|
|
16
|
+
observer = new ResizeObserver(update);
|
|
17
|
+
observer.observe(element.value);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
if (sources.length > 0) watch(sources, update, { flush: "post" });
|
|
21
|
+
onBeforeUnmount(() => {
|
|
22
|
+
observer?.disconnect();
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
isOverflowing,
|
|
26
|
+
update
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { useElementOverflow };
|
|
32
|
+
//# sourceMappingURL=useElementOverflow.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useElementOverflow.mjs","names":["observer: ResizeObserver | null"],"sources":["../src/useElementOverflow.ts"],"sourcesContent":["import { onBeforeUnmount, onMounted, ref, watch, type Ref, type WatchSource } from 'vue';\n\nexport type OverflowAxis = 'x' | 'y';\n\n/** Whether the content is clipped along one axis. Re-checks on resize and when `sources` change. */\nexport function useElementOverflow(\n\telement: Ref<HTMLElement | null>,\n\taxis: OverflowAxis,\n\tsources: WatchSource[] = [],\n) {\n\tconst isOverflowing = ref(false);\n\n\tlet observer: ResizeObserver | null = null;\n\n\tconst update = () => {\n\t\tconst el = element.value;\n\t\tif (!el) return;\n\t\tisOverflowing.value =\n\t\t\taxis === 'x' ? el.scrollWidth > el.clientWidth : el.scrollHeight > el.clientHeight;\n\t};\n\n\tonMounted(() => {\n\t\tupdate();\n\t\tif (element.value && typeof ResizeObserver !== 'undefined') {\n\t\t\tobserver = new ResizeObserver(update);\n\t\t\tobserver.observe(element.value);\n\t\t}\n\t});\n\n\tif (sources.length > 0) {\n\t\twatch(sources, update, { flush: 'post' });\n\t}\n\n\tonBeforeUnmount(() => {\n\t\tobserver?.disconnect();\n\t});\n\n\treturn { isOverflowing, update };\n}\n"],"mappings":";;;;AAKA,SAAgB,mBACf,SACA,MACA,UAAyB,EAAE,EAC1B;CACD,MAAM,gBAAgB,IAAI,MAAM;CAEhC,IAAIA,WAAkC;CAEtC,MAAM,eAAe;EACpB,MAAM,KAAK,QAAQ;AACnB,MAAI,CAAC,GAAI;AACT,gBAAc,QACb,SAAS,MAAM,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,GAAG;;AAGxE,iBAAgB;AACf,UAAQ;AACR,MAAI,QAAQ,SAAS,OAAO,mBAAmB,aAAa;AAC3D,cAAW,IAAI,eAAe,OAAO;AACrC,YAAS,QAAQ,QAAQ,MAAM;;GAE/B;AAEF,KAAI,QAAQ,SAAS,EACpB,OAAM,SAAS,QAAQ,EAAE,OAAO,QAAQ,CAAC;AAG1C,uBAAsB;AACrB,YAAU,YAAY;GACrB;AAEF,QAAO;EAAE;EAAe;EAAQ"}
|
package/dist/useToast.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToast.cjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","useTelemetry","VIEWS","useExternalHooks","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","APP_Z_INDEXES","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useToast.cjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","useTelemetry","VIEWS","useExternalHooks","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","APP_Z_INDEXES","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
package/dist/useToast.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToast.mjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params as unknown as Record<string, unknown>);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useToast.mjs","names":["registeredNotify: NotifyFn | undefined","noopHandle: NotificationHandle","noopNotify: NotifyFn","stickyNotificationQueue: NotificationHandle[]","messageDefaults: Partial<Omit<NotificationOptions, 'message'>>","messageForTelemetry: string","notification: NotificationHandle"],"sources":["../src/useToast.ts"],"sourcesContent":["import { VIEWS } from '@n8n/frontend-constants/views';\nimport { APP_Z_INDEXES } from '@n8n/frontend-constants/z-indexes';\nimport { sanitizeHtml } from '@n8n/frontend-utils/htmlUtils';\nimport { useI18n } from '@n8n/i18n';\nimport { computed } from 'vue';\nimport { useRoute } from 'vue-router';\n\nimport type { NotificationOptions, NotificationType } from './types/notification';\nimport { useExternalHooks } from './useExternalHooks';\nimport { useTelemetry } from './useTelemetry';\n\nexport type {\n\tNotificationOptions,\n\tNotificationPosition,\n\tNotificationType,\n} from './types/notification';\n\n/**\n * Handle returned by the notification function. Declared locally so the DTS\n * build stays free of the full element-plus type graph.\n */\nexport interface NotificationHandle {\n\tclose: () => void;\n}\n\n/**\n * Notification function contract — the app's wrapper around `ElNotification`.\n * Registered at bootstrap via {@link setNotify}; this package owns only the\n * contract.\n *\n * Returning `undefined` means the app declined to show this notification — today\n * that is notification suppression, which lives at the registration site rather\n * than here. `showMessage` treats it as \"dropped\": no sticky-queue\n * entry, no error telemetry, and a no-op handle to the caller.\n */\ntype NotifyFn = (options: Record<string, unknown>) => NotificationHandle | undefined;\n\nlet registeredNotify: NotifyFn | undefined;\n\n/**\n * Register the notification function. Called once at bootstrap by\n * `editor-ui` (passing a suppression-aware wrapper around `ElNotification`) so\n * `useToast` can issue notifications without importing element-plus directly —\n * keeping the DTS build lightweight.\n *\n * This is the *only* toast dependency the app registers. Whether a notification\n * is actually shown is the notifier's decision, so if you are chasing a toast\n * that never appeared, look at the registration site, not here.\n */\nexport function setNotify(fn: NotifyFn): void {\n\tregisteredNotify = fn;\n}\n\nconst noopHandle: NotificationHandle = { close() {} };\nconst noopNotify: NotifyFn = () => noopHandle;\n\nlet warnedAboutMissingNotify = false;\n\nfunction resolveNotify(): NotifyFn {\n\tif (registeredNotify) return registeredNotify;\n\n\t// Falling back means bootstrap never registered. The toast is dropped rather\n\t// than shown, so warn once in dev instead of failing silent.\n\tif (import.meta.env.DEV && !warnedAboutMissingNotify) {\n\t\twarnedAboutMissingNotify = true;\n\t\tconsole.warn(\n\t\t\t'[useToast] No notification function registered; toasts will not render. Call setNotify() at app bootstrap.',\n\t\t);\n\t}\n\treturn noopNotify;\n}\n\nconst stickyNotificationQueue: NotificationHandle[] = [];\n\nexport function useToast() {\n\tconst telemetry = useTelemetry();\n\tconst route = useRoute();\n\tconst workflowId = computed(() => {\n\t\tif (route?.name === VIEWS.DEMO || route?.name === VIEWS.DEMO_DIFF) return 'demo';\n\t\tconst id = route?.params?.workflowId;\n\t\treturn (Array.isArray(id) ? id[0] : id) ?? '';\n\t});\n\tconst externalHooks = useExternalHooks();\n\tconst i18n = useI18n();\n\n\tfunction causedByCredential(message: string | undefined) {\n\t\tif (!message || typeof message !== 'string') return false;\n\n\t\treturn message.includes('Credentials for') && message.includes('are not set');\n\t}\n\n\tfunction showMessage(messageData: Partial<NotificationOptions>, track = true) {\n\t\t// Resolved per call, not once per `useToast()`: a composable captured before\n\t\t// bootstrap registers would otherwise stay bound to the no-op for its whole\n\t\t// lifetime, silently dropping toasts.\n\t\tconst notify = resolveNotify();\n\n\t\tconst messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {\n\t\t\tdangerouslyUseHTMLString: true,\n\t\t\tposition: 'bottom-right',\n\t\t\t// Layer above NDV and modal overlays, sourced from the shared scale.\n\t\t\tzIndex: APP_Z_INDEXES.TOASTS,\n\t\t\tappendTo: '#n8n-app',\n\t\t\tcustomClass: 'content-toast',\n\t\t};\n\t\tconst { message, title } = messageData;\n\t\tconst params = { ...messageDefaults, ...messageData };\n\n\t\tif (typeof message === 'string') {\n\t\t\tparams.message = sanitizeHtml(message);\n\t\t}\n\n\t\tif (typeof title === 'string') {\n\t\t\tparams.title = sanitizeHtml(title);\n\t\t}\n\n\t\tconst notification = notify(params);\n\n\t\t// The app declined to show it (suppression). Return before the sticky queue\n\t\t// and before error telemetry, so a dropped toast leaves no trace — exactly\n\t\t// what the removed in-package suppression branch did.\n\t\tif (!notification) return noopHandle;\n\n\t\tif (params.duration === 0) {\n\t\t\tstickyNotificationQueue.push(notification);\n\t\t}\n\n\t\tif (params.type === 'error' && track) {\n\t\t\t// Extract string message for telemetry - don't send VNode objects as they have circular refs\n\t\t\tlet messageForTelemetry: string;\n\t\t\tif (typeof params.message === 'string') {\n\t\t\t\tmessageForTelemetry = params.message;\n\t\t\t} else if (\n\t\t\t\tparams.message &&\n\t\t\t\ttypeof params.message === 'object' &&\n\t\t\t\t'props' in params.message &&\n\t\t\t\tparams.message.props\n\t\t\t) {\n\t\t\t\t// Extract error message from VNode props (e.g., NodeExecutionErrorMessage component)\n\t\t\t\tconst props = params.message.props;\n\t\t\t\tconst hasErrorMessage =\n\t\t\t\t\ttypeof props === 'object' && props !== null && 'errorMessage' in props;\n\t\t\t\tconst hasMessage = typeof props === 'object' && props !== null && 'message' in props;\n\n\t\t\t\tif (hasErrorMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.errorMessage);\n\t\t\t\t} else if (hasMessage) {\n\t\t\t\t\tmessageForTelemetry = String(props.message);\n\t\t\t\t} else {\n\t\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmessageForTelemetry = 'Unknown error';\n\t\t\t}\n\n\t\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\t\terror_title: params.title,\n\t\t\t\terror_message: messageForTelemetry,\n\t\t\t\tcaused_by_credential: causedByCredential(messageForTelemetry),\n\t\t\t\tworkflow_id: workflowId.value,\n\t\t\t});\n\t\t}\n\n\t\treturn notification;\n\t}\n\n\tfunction showToast(config: {\n\t\ttitle: string;\n\t\tmessage: NotificationOptions['message'];\n\t\tonClick?: (event?: MouseEvent) => void;\n\t\tonClose?: () => void;\n\t\tduration?: number;\n\t\tcustomClass?: string;\n\t\tcloseOnClick?: boolean;\n\t\ttype?: NotificationType;\n\t}) {\n\t\t// eslint-disable-next-line prefer-const\n\t\tlet notification: NotificationHandle;\n\t\tif (config.closeOnClick) {\n\t\t\tconst originalOnClick = config.onClick;\n\t\t\tconfig.onClick = () => {\n\t\t\t\tif (notification) {\n\t\t\t\t\tnotification.close();\n\t\t\t\t}\n\n\t\t\t\tif (originalOnClick) {\n\t\t\t\t\toriginalOnClick();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tnotification = showMessage({\n\t\t\ttitle: config.title,\n\t\t\tmessage: config.message,\n\t\t\tonClick: config.onClick,\n\t\t\tonClose: config.onClose,\n\t\t\tduration: config.duration,\n\t\t\tcustomClass: config.customClass,\n\t\t\ttype: config.type,\n\t\t});\n\n\t\treturn notification;\n\t}\n\n\tfunction collapsableDetails(description: string) {\n\t\tconst errorDescription =\n\t\t\tdescription.length > 500 ? `${description.slice(0, 500)}...` : description;\n\n\t\treturn `\n\t\t\t\t<br>\n\t\t\t\t<br>\n\t\t\t\t<details>\n\t\t\t\t\t<summary\n\t\t\t\t\t\tstyle=\"color: #ff6d5a; font-weight: bold; cursor: pointer;\"\n\t\t\t\t\t>\n\t\t\t\t\t\t${i18n.baseText('showMessage.showDetails')}\n\t\t\t\t\t</summary>\n\t\t\t\t\t<p>${errorDescription}</p>\n\t\t\t\t</details>\n\t\t\t`;\n\t}\n\n\tfunction showError(\n\t\te: unknown,\n\t\ttitle: string,\n\t\toptions?: { message?: string; description?: string },\n\t) {\n\t\tconst error = e as Error & { description?: string };\n\t\tconst message = options?.message;\n\t\tconst description = options?.description ?? error.description;\n\t\tconst messageLine = message ? `${message}<br/>` : '';\n\t\tshowMessage(\n\t\t\t{\n\t\t\t\ttitle,\n\t\t\t\tmessage: `\n\t\t\t\t\t${messageLine}\n\t\t\t\t\t<i>${error.message}</i>\n\t\t\t\t\t${description ? collapsableDetails(description) : ''}`,\n\t\t\t\ttype: 'error',\n\t\t\t\tduration: 0,\n\t\t\t},\n\t\t\tfalse,\n\t\t);\n\n\t\tvoid externalHooks.run('showMessage.showError', {\n\t\t\ttitle,\n\t\t\tmessage,\n\t\t\terrorMessage: error.message,\n\t\t});\n\n\t\ttelemetry.track('Instance FE emitted error', {\n\t\t\terror_title: title,\n\t\t\terror_description: message,\n\t\t\terror_message: error.message,\n\t\t\tcaused_by_credential: causedByCredential(error.message),\n\t\t\tworkflow_id: workflowId.value,\n\t\t});\n\t}\n\n\tfunction clearAllStickyNotifications() {\n\t\tstickyNotificationQueue.forEach((notification) => {\n\t\t\tif (notification) {\n\t\t\t\tnotification.close();\n\t\t\t}\n\t\t});\n\n\t\tstickyNotificationQueue.length = 0;\n\t}\n\n\treturn {\n\t\tshowMessage,\n\t\tshowToast,\n\t\tshowError,\n\t\tclearAllStickyNotifications,\n\t};\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n8n/composables",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.30.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"LICENSE.md",
|
|
@@ -15,30 +15,28 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@n8n/api-types": "1.
|
|
19
|
-
"@n8n/frontend-constants": "0.
|
|
18
|
+
"@n8n/api-types": "1.40.0",
|
|
19
|
+
"@n8n/frontend-constants": "0.7.0",
|
|
20
20
|
"@n8n/frontend-utils": "0.4.0",
|
|
21
|
-
"@n8n/i18n": "2.
|
|
21
|
+
"@n8n/i18n": "2.40.0",
|
|
22
22
|
"@vueuse/core": "^14.3.0",
|
|
23
23
|
"lodash": "4.18.1",
|
|
24
|
-
"n8n-workflow": "2.
|
|
24
|
+
"n8n-workflow": "2.40.0",
|
|
25
25
|
"vue": "^3.5.13",
|
|
26
26
|
"vue-router": "^4.5.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@n8n/eslint-config": "0.0.1",
|
|
30
30
|
"@n8n/playwright-janitor": "0.1.0",
|
|
31
|
-
"@n8n/telemetry": "1.
|
|
32
|
-
"@n8n/typescript-config": "1.
|
|
33
|
-
"@n8n/vitest-config": "1.
|
|
31
|
+
"@n8n/telemetry": "1.8.0",
|
|
32
|
+
"@n8n/typescript-config": "1.12.0",
|
|
33
|
+
"@n8n/vitest-config": "1.22.0",
|
|
34
34
|
"@pinia/testing": "^0.1.6",
|
|
35
35
|
"element-plus": "2.4.3",
|
|
36
36
|
"@testing-library/vue": "^8.1.0",
|
|
37
37
|
"@testing-library/jest-dom": "^6.6.3",
|
|
38
38
|
"@testing-library/user-event": "^14.6.1",
|
|
39
39
|
"@types/lodash": "4.17.17",
|
|
40
|
-
"@vitejs/plugin-vue": "^6.0.8",
|
|
41
|
-
"@vue/tsconfig": "^0.7.0",
|
|
42
40
|
"pinia": "^2.2.4",
|
|
43
41
|
"tsdown": "^0.16.5",
|
|
44
42
|
"typescript": "6.0.2",
|