@anfo/nuxt-dialogs-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/module.ts","../src/vite-plugin.ts"],"sourcesContent":["import {\n addImports,\n addPluginTemplate,\n addTypeTemplate,\n defineNuxtModule,\n} from \"@nuxt/kit\";\nimport type { Nuxt } from \"@nuxt/schema\";\nimport { dirname, resolve } from \"node:path\";\nimport {\n createDialogsVitePlugin,\n generateDialogsDts,\n scanDialogFiles,\n} from \"./vite-plugin\";\n\nexport interface ModuleOptions {\n /**\n * Directory that contains dialog components.\n * Relative paths are resolved against `srcDir`. Defaults to `dialogs`.\n */\n dir?: string;\n /**\n * RegExp used to identify dialog component files.\n * Defaults to files whose name ends with `Dialog.vue` or `Drawer.vue`.\n */\n pattern?: RegExp;\n /**\n * When true (default), every dialog app inherits the Nuxt app's context:\n * global components, directives and provides — Pinia, i18n, UI libraries,\n * the `nuxtApp` itself — are all available inside dialogs with no wiring.\n */\n inheritNuxtApp?: boolean;\n}\n\nconst RUNTIME_PKG = \"@anfo/nuxt-dialogs-plugin/runtime\";\nconst IMPORT_ALIAS = \"#dialogs-components\";\nconst TYPE_TEMPLATE = \"types/dialogs.d.ts\";\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name: \"@anfo/nuxt-dialogs-plugin\",\n configKey: \"dialogs\",\n version: \"1.0.0\",\n compatibility: { nuxt: \">=3.5.0\" },\n },\n defaults: {\n dir: \"dialogs\",\n pattern: /(Dialog|Drawer)\\.vue$/,\n inheritNuxtApp: true,\n },\n setup(options, nuxt: Nuxt) {\n const dialogsDir = resolve(nuxt.options.srcDir, options.dir ?? \"dialogs\");\n const pattern = options.pattern ?? /(Dialog|Drawer)\\.vue$/;\n const dtsPath = resolve(nuxt.options.buildDir, TYPE_TEMPLATE);\n\n if (String(nuxt.options.builder ?? \"\").includes(\"webpack\")) {\n console.warn(\n \"[@anfo/nuxt-dialogs-plugin] only the Vite builder is supported; `virtual:dialogs` will not resolve in webpack builds.\",\n );\n }\n\n // Let the generated virtual module import components through a stable\n // alias, so the dialogs directory can live anywhere.\n nuxt.options.alias[IMPORT_ALIAS] = dialogsDir;\n\n // Register the dialogs virtual module in every Vite build (client and\n // server bundles both need to resolve `virtual:dialogs` imports).\n const vitePlugin = createDialogsVitePlugin({\n dir: dialogsDir,\n pattern,\n importAlias: IMPORT_ALIAS,\n runtimePkg: RUNTIME_PKG,\n dtsPath,\n inheritNuxtApp: options.inheritNuxtApp ?? true,\n });\n nuxt.hook(\"vite:extendConfig\", (config) => {\n (config as { plugins: unknown[] }).plugins ??= [];\n (config.plugins as unknown[]).push(vitePlugin);\n });\n\n // Capture the Nuxt app so generated dialog mounts can inherit its\n // context (global components, directives, provides).\n if (options.inheritNuxtApp) {\n addPluginTemplate({\n filename: \"dialogs-context-plugin.mjs\",\n getContents: () =>\n `import { provideDialogsNuxtApp } from ${JSON.stringify(RUNTIME_PKG)};\\n` +\n `export default (nuxtApp) => { provideDialogsNuxtApp(nuxtApp.vueApp); };\\n`,\n });\n }\n\n // Auto-imports — explicit imports from the runtime keep working too.\n addImports([\n { name: \"dialogs\", from: \"virtual:dialogs\" },\n { name: \"useDialogContext\", from: RUNTIME_PKG },\n { name: \"createDialogExpose\", from: RUNTIME_PKG },\n { name: \"configureDialogs\", from: RUNTIME_PKG },\n ]);\n\n // Type declarations for `virtual:dialogs`, included in the generated\n // tsconfig automatically — no user tsconfig changes required. The Vite\n // plugin rewrites this same file when dialog files are added/removed.\n const files = scanDialogFiles(dialogsDir, pattern);\n addTypeTemplate({\n filename: TYPE_TEMPLATE,\n getContents: () =>\n generateDialogsDts({\n files,\n dtsDir: dirname(dtsPath),\n dialogsDir,\n runtimePkg: RUNTIME_PKG,\n }),\n });\n },\n});\n","import type { Plugin, ViteDevServer } from \"vite\";\nimport { mkdirSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, relative, resolve } from \"node:path\";\n\nexport interface DialogsVitePluginOptions {\n /** Absolute path to the directory that contains dialog components. */\n dir: string;\n /** RegExp used to identify dialog component files. */\n pattern: RegExp;\n /**\n * Alias registered on the Nuxt app (e.g. `#dialogs-components`) that maps\n * to `dir`. The virtual module imports components through it so the\n * generated code never depends on where the directory lives.\n */\n importAlias: string;\n /** Runtime package specifier, e.g. `@anfo/nuxt-dialogs-plugin/runtime`. */\n runtimePkg: string;\n /** Absolute path of the generated declaration file. */\n dtsPath: string;\n /**\n * When true, generated dialog apps inherit the Nuxt app's context\n * (global components, directives, provides — Pinia, i18n, UI libs…).\n */\n inheritNuxtApp: boolean;\n}\n\nconst VIRTUAL_ID = \"virtual:dialogs\";\nconst RESOLVED_VIRTUAL_ID = \"\\0virtual:dialogs\";\n\n// ── Scanning ──────────────────────────────────────────────────────────────────\n\nexport function scanDialogFiles(dir: string, pattern: RegExp): string[] {\n try {\n return readdirSync(dir)\n .filter((f: string) => pattern.test(f))\n .sort()\n .map((f: string) => resolve(dir, f));\n } catch {\n return [];\n }\n}\n\nfunction componentName(filePath: string): string {\n return basename(filePath, \".vue\");\n}\n\n// ── Virtual module code generation ────────────────────────────────────────────\n\nfunction generateModuleCode(\n files: string[],\n options: DialogsVitePluginOptions,\n): string {\n const { dir, importAlias, runtimePkg, inheritNuxtApp } = options;\n\n const runtimeImports = inheritNuxtApp\n ? \"applyDialogAppPlugins, dialogControllerKey, getDialogsNuxtVueApp\"\n : \"applyDialogAppPlugins, dialogControllerKey\";\n\n const lines: string[] = [\n `import { createApp } from \"vue\";`,\n `import { ${runtimeImports} } from ${JSON.stringify(runtimePkg)};`,\n ];\n for (let i = 0; i < files.length; i++) {\n lines.push(\n `import _D${i} from ${JSON.stringify(`${importAlias}/${basename(files[i])}`)};`,\n );\n }\n\n // Dialogs are DOM-only; calling one during SSR resolves as a rejection\n // instead of crashing the server render.\n const ssrGuard = ` if (typeof document === \"undefined\") {\n console.warn(\"[nuxt-dialogs] dialogs can only be opened in the browser; ignoring a dialog opened during SSR.\");\n return Object.assign(Promise.resolve({ type: \"reject\", reason: new Error(\"Dialogs are client-only (opened during SSR).\") }), {\n resolve() { return this; },\n reject() { return this; },\n });\n }\n`;\n\n // Shallow-clone the Nuxt app's context onto the dialog app. Every bucket\n // must be copied (not shared by reference) so the `provide()` below — and\n // any plugin install — cannot leak into the main Nuxt app.\n const contextInherit = inheritNuxtApp\n ? ` const nuxtVueApp = getDialogsNuxtVueApp();\n if (nuxtVueApp) {\n const base = app._context;\n const main = nuxtVueApp._context;\n app._context = {\n ...base,\n config: { ...base.config, ...main.config },\n components: { ...base.components, ...main.components },\n directives: { ...base.directives, ...main.directives },\n provides: { ...base.provides, ...main.provides },\n };\n }\n`\n : \"\";\n\n lines.push(`\nfunction mountDialog(component, props) {\n${ssrGuard} const result = new Promise((resolve) => {\n const host = document.createElement(\"div\");\n document.body.appendChild(host);\n let settled = false;\n function cleanup() { app.unmount(); host.remove(); }\n function finish(cb) {\n if (settled) return;\n settled = true;\n cb();\n cleanup();\n }\n function handleResolve(...args) {\n finish(() => {\n if (args.length === 0) { resolve({ type: \"resolve\" }); return; }\n resolve({ type: \"resolve\", value: args[0] });\n });\n }\n const controller = {\n resolve: handleResolve,\n reject: (reason) => { finish(() => resolve({ type: \"reject\", reason })); },\n };\n const app = createApp(component, props);\n${contextInherit} app.provide(dialogControllerKey, controller);\n applyDialogAppPlugins(app);\n app.mount(host);\n });\n return Object.assign(result, {\n resolve(callback) {\n result.then((value) => {\n if (value.type === \"resolve\") callback?.(value.value);\n });\n return this;\n },\n reject(callback) {\n result.then((value) => {\n if (value.type === \"reject\") callback(value.reason);\n });\n return this;\n },\n });\n}`);\n\n lines.push(\"\");\n lines.push(\"export const dialogs = {\");\n for (let i = 0; i < files.length; i++) {\n lines.push(\n `\\t${componentName(files[i])}: (props) => mountDialog(_D${i}, props),`,\n );\n }\n lines.push(\"};\");\n return lines.join(\"\\n\");\n}\n\n// ── Declaration file generation ───────────────────────────────────────────────\n\nexport function generateDialogsDts(options: {\n files: string[];\n /** Absolute path of the directory the .d.ts is written to. */\n dtsDir: string;\n /** Directory containing the dialog components (absolute). */\n dialogsDir: string;\n /** Runtime package specifier for type imports. */\n runtimePkg: string;\n}): string {\n const { files, dtsDir, dialogsDir, runtimePkg } = options;\n\n const lines: string[] = [\n \"// Auto-generated by @anfo/nuxt-dialogs-plugin — do not edit manually.\",\n \"\",\n `declare module \"${VIRTUAL_ID}\" {`,\n `\\ttype _C = import(\"vue\").Component;`,\n `\\ttype _CE<T extends _C> = import(\"vue-component-type-helpers\").ComponentExposed<T>;`,\n `\\ttype _CP<T extends _C> = import(\"vue-component-type-helpers\").ComponentProps<T>;`,\n `\\ttype _DE<T> = import(${JSON.stringify(runtimePkg)}).DialogExposed<T>;`,\n `\\ttype _DS<T> = import(${JSON.stringify(runtimePkg)}).DialogSettledResult<T>;`,\n `\\ttype _DR = import(${JSON.stringify(runtimePkg)}).DialogRejectedResult;`,\n `\\ttype _IK = \"key\" | \"ref\" | \"ref_for\" | \"ref_key\" | \"class\" | \"style\" | \\`on\\${string}\\`;`,\n `\\ttype _P<T extends _C> = Omit<_CP<T>, _IK>;`,\n `\\ttype _RK<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T];`,\n `\\ttype _A<T extends _C> = [_RK<_P<T>>] extends [never] ? [props?: _P<T>] : [props: _P<T>];`,\n `\\ttype _V<T extends _C> = _CE<T> extends _DE<infer R> ? R : void;`,\n `\\ttype _R<T extends _C> = _DS<_V<T>>;`,\n `\\ttype _RN = _DR[\"reason\"];`,\n `\\ttype _H<T extends _C> = Promise<_R<T>> & {`,\n `\\t\\tresolve(callback?: (value: _V<T> | undefined) => void): _H<T>;`,\n `\\t\\treject(callback: (reason: _RN) => void): _H<T>;`,\n `\\t};`,\n `\\texport const dialogs: {`,\n ];\n\n for (const filePath of files) {\n const name = componentName(filePath);\n let rel = relative(dtsDir, filePath).replace(/\\\\/g, \"/\");\n if (!rel.startsWith(\".\")) rel = `./${rel}`;\n const comp = `typeof import(${JSON.stringify(rel)})[\"default\"]`;\n lines.push(`\\t\\t${name}: (...args: _A<${comp}>) => _H<${comp}>;`);\n }\n\n lines.push(\"\\t};\", \"}\", \"\");\n return lines.join(\"\\n\");\n}\n\n// ── Plugin ────────────────────────────────────────────────────────────────────\n\nexport function createDialogsVitePlugin(\n options: DialogsVitePluginOptions,\n): Plugin {\n const { dir, pattern, dtsPath } = options;\n\n function writeDts(): void {\n const dtsDir = dirname(dtsPath);\n mkdirSync(dtsDir, { recursive: true });\n writeFileSync(\n dtsPath,\n generateDialogsDts({\n files: scanDialogFiles(dir, pattern),\n dtsDir,\n dialogsDir: dir,\n runtimePkg: options.runtimePkg,\n }),\n \"utf-8\",\n );\n }\n\n function invalidate(server: ViteDevServer): void {\n const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);\n if (mod) server.moduleGraph.invalidateModule(mod);\n writeDts();\n server.hot.send({ type: \"full-reload\" });\n }\n\n return {\n name: \"nuxt-dialogs-plugin\",\n\n buildStart() {\n writeDts();\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID;\n },\n\n load(id) {\n if (id !== RESOLVED_VIRTUAL_ID) return;\n const files = scanDialogFiles(dir, pattern);\n return {\n code: generateModuleCode(files, options),\n moduleType: \"js\",\n };\n },\n\n configureServer(server) {\n server.watcher.add(dir);\n\n server.watcher.on(\"add\", (file) => {\n if (pattern.test(file) && file.startsWith(dir)) {\n invalidate(server);\n }\n });\n\n server.watcher.on(\"unlink\", (file) => {\n if (pattern.test(file) && file.startsWith(dir)) {\n invalidate(server);\n }\n });\n },\n };\n}\n"],"mappings":"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","names":["dirname","resolve","resolve","dirname"]}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/runtime.ts
21
+ var runtime_exports = {};
22
+ __export(runtime_exports, {
23
+ applyDialogAppPlugins: () => applyDialogAppPlugins,
24
+ configureDialogs: () => configureDialogs,
25
+ createDialogExpose: () => createDialogExpose,
26
+ dialogControllerKey: () => dialogControllerKey,
27
+ getDialogsNuxtVueApp: () => getDialogsNuxtVueApp,
28
+ provideDialogsNuxtApp: () => provideDialogsNuxtApp,
29
+ useDialogContext: () => useDialogContext
30
+ });
31
+ module.exports = __toCommonJS(runtime_exports);
32
+ var import_vue = require("vue");
33
+ var dialogControllerKey = /* @__PURE__ */ Symbol("dialogController");
34
+ var dialogAppPlugins = [];
35
+ function configureDialogs(options = {}) {
36
+ const use = options.use;
37
+ dialogAppPlugins = use ? (Array.isArray(use) ? use.flat() : [use]).filter(
38
+ Boolean
39
+ ) : [];
40
+ }
41
+ function applyDialogAppPlugins(app) {
42
+ for (const plugin of dialogAppPlugins) app.use(plugin);
43
+ }
44
+ var nuxtVueApp;
45
+ function provideDialogsNuxtApp(app) {
46
+ nuxtVueApp = app;
47
+ }
48
+ function getDialogsNuxtVueApp() {
49
+ return nuxtVueApp;
50
+ }
51
+ function useDialogContext() {
52
+ const controller = (0, import_vue.inject)(dialogControllerKey, void 0);
53
+ if (!controller) {
54
+ throw new Error("useDialogContext must be used inside mountDialog().");
55
+ }
56
+ return {
57
+ resolve: controller.resolve,
58
+ reject: controller.reject
59
+ };
60
+ }
61
+ function createDialogExpose() {
62
+ return {};
63
+ }
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ applyDialogAppPlugins,
67
+ configureDialogs,
68
+ createDialogExpose,
69
+ dialogControllerKey,
70
+ getDialogsNuxtVueApp,
71
+ provideDialogsNuxtApp,
72
+ useDialogContext
73
+ });
74
+ //# sourceMappingURL=runtime.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["import { inject, type App, type InjectionKey, type Plugin } from \"vue\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DialogResolve<T = void> = [T] extends [void] ? () => void\n : (value: T) => void;\n\nexport type DialogReject = (reason?: unknown) => void;\n\nexport type DialogResolvedResult<T = void> = [T] extends [void]\n ? { type: \"resolve\" }\n : { type: \"resolve\"; value: T };\n\nexport type DialogRejectedResult = {\n type: \"reject\";\n reason?: unknown;\n};\n\nexport type DialogSettledResult<T = void> =\n | DialogResolvedResult<T>\n | DialogRejectedResult;\n\nexport type DialogController<T = void> = {\n resolve: DialogResolve<T>;\n reject: DialogReject;\n};\n\nexport type DialogExposed<T = void> = {\n __dialogResult?: T;\n};\n\n// ── Injection keys ────────────────────────────────────────────────────────────\n\nexport const dialogControllerKey = Symbol(\"dialogController\") as InjectionKey<\n DialogController<unknown>\n>;\n\nexport type DialogAppPlugin = Plugin;\n\nlet dialogAppPlugins: DialogAppPlugin[] = [];\n\nexport function configureDialogs(options: {\n use?: DialogAppPlugin | DialogAppPlugin[];\n} = {}): void {\n const use = options.use;\n dialogAppPlugins = use\n ? (Array.isArray(use) ? use.flat() : [use]).filter(\n Boolean,\n ) as DialogAppPlugin[]\n : [];\n}\n\nexport function applyDialogAppPlugins(app: App<Element>): void {\n for (const plugin of dialogAppPlugins) app.use(plugin);\n}\n\n// ── Nuxt app bridge ───────────────────────────────────────────────────────────\n// A tiny runtime plugin (registered by the Nuxt module) captures the main Nuxt\n// app so that generated dialog mounts can inherit its context — global\n// components, directives and `provide`s (Pinia, i18n, UI libraries, the\n// nuxtApp itself) all become available inside dialogs with zero wiring.\n\nlet nuxtVueApp: App<Element> | undefined;\n\nexport function provideDialogsNuxtApp(app: App<Element> | undefined): void {\n nuxtVueApp = app;\n}\n\nexport function getDialogsNuxtVueApp(): App<Element> | undefined {\n return nuxtVueApp;\n}\n\n// ── Composables ───────────────────────────────────────────────────────────────\n\nexport function useDialogContext<T = void>(): {\n resolve: DialogResolve<T>;\n reject: DialogReject;\n} {\n const controller = inject(dialogControllerKey, undefined) as\n | DialogController<T>\n | undefined;\n\n if (!controller) {\n throw new Error(\"useDialogContext must be used inside mountDialog().\");\n }\n\n return {\n resolve: controller.resolve,\n reject: controller.reject,\n };\n}\n\nexport function createDialogExpose<T = void>(): DialogExposed<T> {\n return {} as DialogExposed<T>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAiE;AAiC1D,IAAM,sBAAsB,uBAAO,kBAAkB;AAM5D,IAAI,mBAAsC,CAAC;AAEpC,SAAS,iBAAiB,UAE7B,CAAC,GAAS;AACV,QAAM,MAAM,QAAQ;AACpB,qBAAmB,OACZ,MAAM,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,GAAG;AAAA,IACtC;AAAA,EACJ,IACA,CAAC;AACX;AAEO,SAAS,sBAAsB,KAAyB;AAC3D,aAAW,UAAU,iBAAkB,KAAI,IAAI,MAAM;AACzD;AAQA,IAAI;AAEG,SAAS,sBAAsB,KAAqC;AACvE,eAAa;AACjB;AAEO,SAAS,uBAAiD;AAC7D,SAAO;AACX;AAIO,SAAS,mBAGd;AACE,QAAM,iBAAa,mBAAO,qBAAqB,MAAS;AAIxD,MAAI,CAAC,YAAY;AACb,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,SAAO;AAAA,IACH,SAAS,WAAW;AAAA,IACpB,QAAQ,WAAW;AAAA,EACvB;AACJ;AAEO,SAAS,qBAAiD;AAC7D,SAAO,CAAC;AACZ;","names":[]}
@@ -0,0 +1,37 @@
1
+ import { Plugin, App, InjectionKey } from 'vue';
2
+
3
+ type DialogResolve<T = void> = [T] extends [void] ? () => void : (value: T) => void;
4
+ type DialogReject = (reason?: unknown) => void;
5
+ type DialogResolvedResult<T = void> = [T] extends [void] ? {
6
+ type: "resolve";
7
+ } : {
8
+ type: "resolve";
9
+ value: T;
10
+ };
11
+ type DialogRejectedResult = {
12
+ type: "reject";
13
+ reason?: unknown;
14
+ };
15
+ type DialogSettledResult<T = void> = DialogResolvedResult<T> | DialogRejectedResult;
16
+ type DialogController<T = void> = {
17
+ resolve: DialogResolve<T>;
18
+ reject: DialogReject;
19
+ };
20
+ type DialogExposed<T = void> = {
21
+ __dialogResult?: T;
22
+ };
23
+ declare const dialogControllerKey: InjectionKey<DialogController<unknown>>;
24
+ type DialogAppPlugin = Plugin;
25
+ declare function configureDialogs(options?: {
26
+ use?: DialogAppPlugin | DialogAppPlugin[];
27
+ }): void;
28
+ declare function applyDialogAppPlugins(app: App<Element>): void;
29
+ declare function provideDialogsNuxtApp(app: App<Element> | undefined): void;
30
+ declare function getDialogsNuxtVueApp(): App<Element> | undefined;
31
+ declare function useDialogContext<T = void>(): {
32
+ resolve: DialogResolve<T>;
33
+ reject: DialogReject;
34
+ };
35
+ declare function createDialogExpose<T = void>(): DialogExposed<T>;
36
+
37
+ export { type DialogAppPlugin, type DialogController, type DialogExposed, type DialogReject, type DialogRejectedResult, type DialogResolve, type DialogResolvedResult, type DialogSettledResult, applyDialogAppPlugins, configureDialogs, createDialogExpose, dialogControllerKey, getDialogsNuxtVueApp, provideDialogsNuxtApp, useDialogContext };
@@ -0,0 +1,37 @@
1
+ import { Plugin, App, InjectionKey } from 'vue';
2
+
3
+ type DialogResolve<T = void> = [T] extends [void] ? () => void : (value: T) => void;
4
+ type DialogReject = (reason?: unknown) => void;
5
+ type DialogResolvedResult<T = void> = [T] extends [void] ? {
6
+ type: "resolve";
7
+ } : {
8
+ type: "resolve";
9
+ value: T;
10
+ };
11
+ type DialogRejectedResult = {
12
+ type: "reject";
13
+ reason?: unknown;
14
+ };
15
+ type DialogSettledResult<T = void> = DialogResolvedResult<T> | DialogRejectedResult;
16
+ type DialogController<T = void> = {
17
+ resolve: DialogResolve<T>;
18
+ reject: DialogReject;
19
+ };
20
+ type DialogExposed<T = void> = {
21
+ __dialogResult?: T;
22
+ };
23
+ declare const dialogControllerKey: InjectionKey<DialogController<unknown>>;
24
+ type DialogAppPlugin = Plugin;
25
+ declare function configureDialogs(options?: {
26
+ use?: DialogAppPlugin | DialogAppPlugin[];
27
+ }): void;
28
+ declare function applyDialogAppPlugins(app: App<Element>): void;
29
+ declare function provideDialogsNuxtApp(app: App<Element> | undefined): void;
30
+ declare function getDialogsNuxtVueApp(): App<Element> | undefined;
31
+ declare function useDialogContext<T = void>(): {
32
+ resolve: DialogResolve<T>;
33
+ reject: DialogReject;
34
+ };
35
+ declare function createDialogExpose<T = void>(): DialogExposed<T>;
36
+
37
+ export { type DialogAppPlugin, type DialogController, type DialogExposed, type DialogReject, type DialogRejectedResult, type DialogResolve, type DialogResolvedResult, type DialogSettledResult, applyDialogAppPlugins, configureDialogs, createDialogExpose, dialogControllerKey, getDialogsNuxtVueApp, provideDialogsNuxtApp, useDialogContext };
@@ -0,0 +1,43 @@
1
+ // src/runtime.ts
2
+ import { inject } from "vue";
3
+ var dialogControllerKey = /* @__PURE__ */ Symbol("dialogController");
4
+ var dialogAppPlugins = [];
5
+ function configureDialogs(options = {}) {
6
+ const use = options.use;
7
+ dialogAppPlugins = use ? (Array.isArray(use) ? use.flat() : [use]).filter(
8
+ Boolean
9
+ ) : [];
10
+ }
11
+ function applyDialogAppPlugins(app) {
12
+ for (const plugin of dialogAppPlugins) app.use(plugin);
13
+ }
14
+ var nuxtVueApp;
15
+ function provideDialogsNuxtApp(app) {
16
+ nuxtVueApp = app;
17
+ }
18
+ function getDialogsNuxtVueApp() {
19
+ return nuxtVueApp;
20
+ }
21
+ function useDialogContext() {
22
+ const controller = inject(dialogControllerKey, void 0);
23
+ if (!controller) {
24
+ throw new Error("useDialogContext must be used inside mountDialog().");
25
+ }
26
+ return {
27
+ resolve: controller.resolve,
28
+ reject: controller.reject
29
+ };
30
+ }
31
+ function createDialogExpose() {
32
+ return {};
33
+ }
34
+ export {
35
+ applyDialogAppPlugins,
36
+ configureDialogs,
37
+ createDialogExpose,
38
+ dialogControllerKey,
39
+ getDialogsNuxtVueApp,
40
+ provideDialogsNuxtApp,
41
+ useDialogContext
42
+ };
43
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["import { inject, type App, type InjectionKey, type Plugin } from \"vue\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DialogResolve<T = void> = [T] extends [void] ? () => void\n : (value: T) => void;\n\nexport type DialogReject = (reason?: unknown) => void;\n\nexport type DialogResolvedResult<T = void> = [T] extends [void]\n ? { type: \"resolve\" }\n : { type: \"resolve\"; value: T };\n\nexport type DialogRejectedResult = {\n type: \"reject\";\n reason?: unknown;\n};\n\nexport type DialogSettledResult<T = void> =\n | DialogResolvedResult<T>\n | DialogRejectedResult;\n\nexport type DialogController<T = void> = {\n resolve: DialogResolve<T>;\n reject: DialogReject;\n};\n\nexport type DialogExposed<T = void> = {\n __dialogResult?: T;\n};\n\n// ── Injection keys ────────────────────────────────────────────────────────────\n\nexport const dialogControllerKey = Symbol(\"dialogController\") as InjectionKey<\n DialogController<unknown>\n>;\n\nexport type DialogAppPlugin = Plugin;\n\nlet dialogAppPlugins: DialogAppPlugin[] = [];\n\nexport function configureDialogs(options: {\n use?: DialogAppPlugin | DialogAppPlugin[];\n} = {}): void {\n const use = options.use;\n dialogAppPlugins = use\n ? (Array.isArray(use) ? use.flat() : [use]).filter(\n Boolean,\n ) as DialogAppPlugin[]\n : [];\n}\n\nexport function applyDialogAppPlugins(app: App<Element>): void {\n for (const plugin of dialogAppPlugins) app.use(plugin);\n}\n\n// ── Nuxt app bridge ───────────────────────────────────────────────────────────\n// A tiny runtime plugin (registered by the Nuxt module) captures the main Nuxt\n// app so that generated dialog mounts can inherit its context — global\n// components, directives and `provide`s (Pinia, i18n, UI libraries, the\n// nuxtApp itself) all become available inside dialogs with zero wiring.\n\nlet nuxtVueApp: App<Element> | undefined;\n\nexport function provideDialogsNuxtApp(app: App<Element> | undefined): void {\n nuxtVueApp = app;\n}\n\nexport function getDialogsNuxtVueApp(): App<Element> | undefined {\n return nuxtVueApp;\n}\n\n// ── Composables ───────────────────────────────────────────────────────────────\n\nexport function useDialogContext<T = void>(): {\n resolve: DialogResolve<T>;\n reject: DialogReject;\n} {\n const controller = inject(dialogControllerKey, undefined) as\n | DialogController<T>\n | undefined;\n\n if (!controller) {\n throw new Error(\"useDialogContext must be used inside mountDialog().\");\n }\n\n return {\n resolve: controller.resolve,\n reject: controller.reject,\n };\n}\n\nexport function createDialogExpose<T = void>(): DialogExposed<T> {\n return {} as DialogExposed<T>;\n}\n"],"mappings":";AAAA,SAAS,cAAwD;AAiC1D,IAAM,sBAAsB,uBAAO,kBAAkB;AAM5D,IAAI,mBAAsC,CAAC;AAEpC,SAAS,iBAAiB,UAE7B,CAAC,GAAS;AACV,QAAM,MAAM,QAAQ;AACpB,qBAAmB,OACZ,MAAM,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,GAAG;AAAA,IACtC;AAAA,EACJ,IACA,CAAC;AACX;AAEO,SAAS,sBAAsB,KAAyB;AAC3D,aAAW,UAAU,iBAAkB,KAAI,IAAI,MAAM;AACzD;AAQA,IAAI;AAEG,SAAS,sBAAsB,KAAqC;AACvE,eAAa;AACjB;AAEO,SAAS,uBAAiD;AAC7D,SAAO;AACX;AAIO,SAAS,mBAGd;AACE,QAAM,aAAa,OAAO,qBAAqB,MAAS;AAIxD,MAAI,CAAC,YAAY;AACb,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE;AAEA,SAAO;AAAA,IACH,SAAS,WAAW;AAAA,IACpB,QAAQ,WAAW;AAAA,EACvB;AACJ;AAEO,SAAS,qBAAiD;AAC7D,SAAO,CAAC;AACZ;","names":[]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@anfo/nuxt-dialogs-plugin",
3
+ "version": "1.0.0",
4
+ "description": "Nuxt module that auto-scans a directory for Vue dialog/drawer components and exposes them through a fully type-safe virtual module (virtual:dialogs). Dialog apps automatically inherit the Nuxt app context (Pinia, i18n, UI libraries, global components).",
5
+ "keywords": [
6
+ "nuxt",
7
+ "nuxt-module",
8
+ "nuxt3",
9
+ "nuxt4",
10
+ "vue",
11
+ "vue3",
12
+ "dialog",
13
+ "dialogs",
14
+ "drawer"
15
+ ],
16
+ "author": "anfo",
17
+ "license": "MIT",
18
+ "type": "module",
19
+ "main": "./dist/module.cjs",
20
+ "module": "./dist/module.js",
21
+ "types": "./dist/module.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/module.d.ts",
25
+ "import": "./dist/module.js",
26
+ "require": "./dist/module.cjs"
27
+ },
28
+ "./runtime": {
29
+ "types": "./dist/runtime.d.ts",
30
+ "import": "./dist/runtime.js",
31
+ "require": "./dist/runtime.cjs"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "SKILL.md"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "prepublishOnly": "npm run build"
42
+ },
43
+ "dependencies": {
44
+ "@nuxt/kit": "^3.11.0 || ^4.0.0",
45
+ "vue-component-type-helpers": "^2.0.0 || ^3.0.0"
46
+ },
47
+ "peerDependencies": {
48
+ "nuxt": ">=3.5.0",
49
+ "vite": ">=4.0.0",
50
+ "vue": "^3.3.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^25.6.0",
54
+ "tsup": "^8.0.0",
55
+ "typescript": "^5.0.0",
56
+ "vite": "^6.0.0",
57
+ "vue": "^3.5.0"
58
+ }
59
+ }