@gridland/web 0.2.13 → 0.2.16

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.
@@ -162,7 +162,11 @@ function gridlandWebPlugin() {
162
162
  aliases[path.resolve(coreRoot, "src", key)] = path.resolve(pkgRoot, shimPath);
163
163
  }
164
164
  for (const pkg of ["react-reconciler", "yoga-layout", "diff", "marked"]) {
165
- aliases[pkg] = path.resolve(pkgRoot, "node_modules", pkg);
165
+ try {
166
+ aliases[pkg] = path.dirname(_require.resolve(pkg + "/package.json"));
167
+ } catch {
168
+ aliases[pkg] = path.resolve(pkgRoot, "node_modules", pkg);
169
+ }
166
170
  }
167
171
  return {
168
172
  define: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vite-plugin.ts"],"sourcesContent":["import { type Plugin } from \"vite\"\nimport path from \"path\"\nimport { createRequire } from \"module\"\nimport { fileURLToPath } from \"url\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\n/**\n * Vite plugin that sets up module resolution for Gridland.\n * Handles:\n * - Redirecting Zig/FFI imports to browser shims\n * - Resolving @opentui/core, @opentui/react, @opentui/ui\n * - Shimming Node.js built-ins\n * - Breaking circular dependencies\n *\n * Requires @opentui/core, @opentui/react, and @opentui/ui as peer dependencies.\n */\nexport function gridlandWebPlugin(): Plugin[] {\n const pkgRoot = path.resolve(__dirname, \"..\")\n const _require = createRequire(path.resolve(pkgRoot, \"package.json\"))\n\n // Resolve opentui package roots — try installed packages first,\n // fall back to git submodule for monorepo development\n function resolvePackageRoot(pkg: string, fallbackRelative: string): string {\n try {\n const pkgJson = _require.resolve(`${pkg}/package.json`)\n return path.dirname(pkgJson)\n } catch {\n return path.resolve(pkgRoot, fallbackRelative)\n }\n }\n const coreRoot = resolvePackageRoot(\"@opentui/core\", \"../../opentui/packages/core\")\n const reactRoot = resolvePackageRoot(\"@opentui/react\", \"../../opentui/packages/react\")\n const uiRoot = resolvePackageRoot(\"@opentui/ui\", \"../../opentui/packages/ui\")\n\n const coreShims = path.resolve(pkgRoot, \"src/core-shims/index.ts\")\n const opentuiCoreBarrel = path.resolve(coreRoot, \"src/index.ts\")\n const sliderDeps = path.resolve(pkgRoot, \"src/shims/slider-deps.ts\")\n const sliderFile = path.resolve(coreRoot, \"src/renderables/Slider.ts\")\n\n // Map of opentui source files that need browser shims\n const coreFileShims: Record<string, string> = {\n zig: \"src/shims/zig-stub.ts\",\n buffer: \"src/browser-buffer.ts\",\n \"text-buffer\": \"src/shims/text-buffer-shim.ts\",\n \"text-buffer-view\": \"src/shims/text-buffer-view-shim.ts\",\n \"syntax-style\": \"src/shims/syntax-style-shim.ts\",\n renderer: \"src/shims/renderer-stub.ts\",\n console: \"src/shims/console-stub.ts\",\n \"edit-buffer\": \"src/shims/edit-buffer-stub.ts\",\n \"editor-view\": \"src/shims/editor-view-stub.ts\",\n NativeSpanFeed: \"src/shims/native-span-feed-stub.ts\",\n \"post/filters\": \"src/shims/filters-stub.ts\",\n \"animation/Timeline\": \"src/shims/timeline-stub.ts\",\n }\n\n const resolvedCoreShims = new Map<string, string>()\n for (const [key, shimPath] of Object.entries(coreFileShims)) {\n const absoluteTarget = path.resolve(coreRoot, \"src\", key + \".ts\")\n resolvedCoreShims.set(absoluteTarget, path.resolve(pkgRoot, shimPath))\n }\n\n const treeStub = path.resolve(pkgRoot, \"src/shims/tree-sitter-stub.ts\")\n const styledTextStub = path.resolve(pkgRoot, \"src/shims/tree-sitter-styled-text-stub.ts\")\n\n // Lookup tables hoisted out of resolveId to avoid per-call allocation\n const pkgRoots: Record<string, string> = { core: coreRoot, react: reactRoot, ui: uiRoot }\n\n const nodeShims: Record<string, string> = {\n \"node:buffer\": \"src/shims/node-buffer.ts\",\n \"node:path\": \"src/shims/node-path.ts\",\n path: \"src/shims/node-path.ts\",\n \"node:fs\": \"src/shims/node-fs.ts\",\n fs: \"src/shims/node-fs.ts\",\n \"fs/promises\": \"src/shims/node-fs.ts\",\n \"node:util\": \"src/shims/node-util.ts\",\n util: \"src/shims/node-util.ts\",\n os: \"src/shims/node-os.ts\",\n \"node:os\": \"src/shims/node-os.ts\",\n stream: \"src/shims/node-stream.ts\",\n \"node:stream\": \"src/shims/node-stream.ts\",\n url: \"src/shims/node-url.ts\",\n \"node:url\": \"src/shims/node-url.ts\",\n bun: \"src/shims/bun-ffi.ts\",\n }\n\n // Virtual module prefix for npm package redirects.\n // When external opentui code imports a bare npm package (e.g. \"react\"),\n // we can't return the raw file path because Vite would serve it via /@fs/\n // without CJS-to-ESM conversion. Instead, we return a virtual module that\n // re-exports from the bare package name, which Vite processes through its\n // normal pre-bundling pipeline (including CJS conversion).\n const NPM_REDIRECT = \"\\0npm-redirect:\"\n\n const shimPlugin: Plugin = {\n name: \"gridland-web-shims\",\n enforce: \"pre\",\n resolveId(source, importer) {\n if (!importer) return null\n\n // Virtual module redirects should not be re-intercepted\n if (importer.startsWith(NPM_REDIRECT)) return null\n\n // Check if importer is in an opentui package\n const isExternalOpentui =\n importer.startsWith(coreRoot + path.sep) ||\n importer.startsWith(reactRoot + path.sep) ||\n importer.startsWith(uiRoot + path.sep)\n\n // Slider circular dep fix\n if (source === \"../index\" && importer === sliderFile) {\n return sliderDeps\n }\n\n // Resolve @opentui packages\n if (source === \"@opentui/ui\") {\n return path.resolve(uiRoot, \"src/index.ts\")\n }\n if (source === \"@opentui/react\") {\n return path.resolve(reactRoot, \"src/index.ts\")\n }\n\n // @opentui/core routing\n if (source === \"@opentui/core\") {\n if (importer.startsWith(reactRoot + path.sep)) {\n return opentuiCoreBarrel\n }\n return coreShims\n }\n\n // @opentui/* subpath imports (e.g. @opentui/react/jsx-dev-runtime)\n if (source.startsWith(\"@opentui/\")) {\n const parts = source.split(\"/\")\n const pkgName = parts[1] // \"react\", \"core\", \"ui\"\n const subpath = parts.slice(2).join(\"/\") // \"jsx-dev-runtime\"\n if (subpath) {\n const root = pkgRoots[pkgName]\n if (root) return path.resolve(root, subpath + \".js\")\n }\n }\n\n // Relative imports from opentui tree → check shims\n if (source.startsWith(\".\") && isExternalOpentui) {\n const importerDir = path.dirname(importer)\n const resolved = path.resolve(importerDir, source)\n // Devtools polyfill stub (uses top-level await for ws import)\n if (resolved.endsWith(\"devtools-polyfill\")) {\n return path.resolve(pkgRoot, \"src/shims/devtools-polyfill-stub.ts\")\n }\n const shim = resolvedCoreShims.get(resolved) || resolvedCoreShims.get(resolved + \".ts\")\n if (shim) return shim\n const indexShim = resolvedCoreShims.get(resolved + \"/index.ts\")\n if (indexShim) return indexShim\n }\n\n // Tree-sitter stubs\n if (source.includes(\"tree-sitter\") && isExternalOpentui) {\n if (source.includes(\"tree-sitter-styled-text\")) return styledTextStub\n return treeStub\n }\n if (source.includes(\"hast-styled-text\") && isExternalOpentui) {\n return path.resolve(pkgRoot, \"src/shims/hast-stub.ts\")\n }\n\n // Events shim — applies to ALL importers (browser-compatible EventEmitter)\n if (source === \"events\") {\n return path.resolve(pkgRoot, \"src/shims/events-shim.ts\")\n }\n\n // Node.js built-in stubs (only for imports from the opentui monorepo,\n // since our own workspace code doesn't import these)\n if (nodeShims[source] && isExternalOpentui) {\n return path.resolve(pkgRoot, nodeShims[source])\n }\n\n // Redirect bare npm imports from external opentui to virtual modules.\n // The virtual module re-exports from the bare package name, which lets\n // Vite's normal resolver + pre-bundler handle CJS-to-ESM conversion.\n // Skip @opentui/* since those are resolved above to monorepo source files.\n if (!source.startsWith(\".\") && !source.startsWith(\"/\") && !source.startsWith(\"@opentui/\") && isExternalOpentui) {\n return NPM_REDIRECT + source\n }\n\n return null\n },\n load(id) {\n if (id.startsWith(NPM_REDIRECT)) {\n const pkg = id.slice(NPM_REDIRECT.length)\n // Discover export names by require()-ing the module at build time.\n // We use `import * as __ns` (namespace import) which works for both\n // ESM packages (named exports on namespace) and CJS packages\n // (pre-bundled with only a default export, properties on __ns.default).\n // Each property checks both locations with a fallback.\n // NOTE: We use bare specifiers (not resolved paths) so Vite routes\n // these through its pre-bundling pipeline for CJS-to-ESM conversion.\n try {\n const mod = _require(pkg)\n if (typeof mod === \"object\" && mod !== null) {\n const names = Object.keys(mod).filter(\n (k) => k !== \"default\" && k !== \"__esModule\" && /^[a-zA-Z_$][\\w$]*$/.test(k),\n )\n if (names.length > 0) {\n return [\n `import * as __ns from \"${pkg}\";`,\n `export default __ns.default ?? __ns;`,\n ...names.map(\n (n) => `export const ${n} = __ns[\"${n}\"] ?? __ns.default?.[\"${n}\"];`,\n ),\n ].join(\"\\n\")\n }\n }\n } catch {\n // Fall through to generic approach\n }\n // Fallback for packages we can't introspect\n return [\n `export * from \"${pkg}\";`,\n `import * as __ns from \"${pkg}\";`,\n `export default __ns.default ?? __ns;`,\n ].join(\"\\n\")\n }\n },\n }\n\n const aliasPlugin: Plugin = {\n name: \"gridland-web-aliases\",\n config() {\n const aliases: Record<string, string> = {}\n\n // FFI shims\n aliases[\"bun:ffi\"] = path.resolve(pkgRoot, \"src/shims/bun-ffi.ts\")\n aliases[\"bun-ffi-structs\"] = path.resolve(pkgRoot, \"src/shims/bun-ffi-structs.ts\")\n aliases[\"node:console\"] = path.resolve(pkgRoot, \"src/shims/console.ts\")\n\n // Core file shims as aliases too\n for (const [key, shimPath] of Object.entries(coreFileShims)) {\n aliases[path.resolve(coreRoot, \"src\", key)] = path.resolve(pkgRoot, shimPath)\n }\n\n // Resolve npm packages from gridland-web's node_modules so consuming\n // projects don't need them as direct dependencies. Directory aliases\n // let subpath imports (e.g. react-reconciler/constants) work via\n // Vite's prefix matching, and ensure CJS packages go through\n // Vite's pre-bundling for proper ESM conversion.\n for (const pkg of [\"react-reconciler\", \"yoga-layout\", \"diff\", \"marked\"]) {\n aliases[pkg] = path.resolve(pkgRoot, \"node_modules\", pkg)\n }\n\n return {\n define: {\n \"process.env\": JSON.stringify({}),\n },\n resolve: {\n alias: aliases,\n dedupe: [\"react\", \"react-dom\", \"react-reconciler\", \"yoga-layout\", \"events\"],\n },\n optimizeDeps: {\n // Pre-bundle npm packages imported by external opentui monorepo code.\n // These are resolved via virtual module redirects, so Vite's initial\n // crawl won't discover them — they must be listed explicitly.\n include: [\n \"react\",\n \"react-dom\",\n \"react-reconciler\",\n \"react-reconciler/constants\",\n \"diff\",\n \"yoga-layout\",\n \"marked\",\n ],\n },\n server: {\n fs: {\n // Allow serving from opentui source dirs (for dev-from-source).\n // Use strict: false so Vite's default allow list (project root) is preserved.\n strict: false,\n },\n },\n }\n },\n }\n\n return [shimPlugin, aliasPlugin]\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/vite-plugin.ts"],"sourcesContent":["import { type Plugin } from \"vite\"\nimport path from \"path\"\nimport { createRequire } from \"module\"\nimport { fileURLToPath } from \"url\"\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\n/**\n * Vite plugin that sets up module resolution for Gridland.\n * Handles:\n * - Redirecting Zig/FFI imports to browser shims\n * - Resolving @opentui/core, @opentui/react, @opentui/ui\n * - Shimming Node.js built-ins\n * - Breaking circular dependencies\n *\n * Requires @opentui/core, @opentui/react, and @opentui/ui as peer dependencies.\n */\nexport function gridlandWebPlugin(): Plugin[] {\n const pkgRoot = path.resolve(__dirname, \"..\")\n const _require = createRequire(path.resolve(pkgRoot, \"package.json\"))\n\n // Resolve opentui package roots — try installed packages first,\n // fall back to git submodule for monorepo development\n function resolvePackageRoot(pkg: string, fallbackRelative: string): string {\n try {\n const pkgJson = _require.resolve(`${pkg}/package.json`)\n return path.dirname(pkgJson)\n } catch {\n return path.resolve(pkgRoot, fallbackRelative)\n }\n }\n const coreRoot = resolvePackageRoot(\"@opentui/core\", \"../../opentui/packages/core\")\n const reactRoot = resolvePackageRoot(\"@opentui/react\", \"../../opentui/packages/react\")\n const uiRoot = resolvePackageRoot(\"@opentui/ui\", \"../../opentui/packages/ui\")\n\n const coreShims = path.resolve(pkgRoot, \"src/core-shims/index.ts\")\n const opentuiCoreBarrel = path.resolve(coreRoot, \"src/index.ts\")\n const sliderDeps = path.resolve(pkgRoot, \"src/shims/slider-deps.ts\")\n const sliderFile = path.resolve(coreRoot, \"src/renderables/Slider.ts\")\n\n // Map of opentui source files that need browser shims\n const coreFileShims: Record<string, string> = {\n zig: \"src/shims/zig-stub.ts\",\n buffer: \"src/browser-buffer.ts\",\n \"text-buffer\": \"src/shims/text-buffer-shim.ts\",\n \"text-buffer-view\": \"src/shims/text-buffer-view-shim.ts\",\n \"syntax-style\": \"src/shims/syntax-style-shim.ts\",\n renderer: \"src/shims/renderer-stub.ts\",\n console: \"src/shims/console-stub.ts\",\n \"edit-buffer\": \"src/shims/edit-buffer-stub.ts\",\n \"editor-view\": \"src/shims/editor-view-stub.ts\",\n NativeSpanFeed: \"src/shims/native-span-feed-stub.ts\",\n \"post/filters\": \"src/shims/filters-stub.ts\",\n \"animation/Timeline\": \"src/shims/timeline-stub.ts\",\n }\n\n const resolvedCoreShims = new Map<string, string>()\n for (const [key, shimPath] of Object.entries(coreFileShims)) {\n const absoluteTarget = path.resolve(coreRoot, \"src\", key + \".ts\")\n resolvedCoreShims.set(absoluteTarget, path.resolve(pkgRoot, shimPath))\n }\n\n const treeStub = path.resolve(pkgRoot, \"src/shims/tree-sitter-stub.ts\")\n const styledTextStub = path.resolve(pkgRoot, \"src/shims/tree-sitter-styled-text-stub.ts\")\n\n // Lookup tables hoisted out of resolveId to avoid per-call allocation\n const pkgRoots: Record<string, string> = { core: coreRoot, react: reactRoot, ui: uiRoot }\n\n const nodeShims: Record<string, string> = {\n \"node:buffer\": \"src/shims/node-buffer.ts\",\n \"node:path\": \"src/shims/node-path.ts\",\n path: \"src/shims/node-path.ts\",\n \"node:fs\": \"src/shims/node-fs.ts\",\n fs: \"src/shims/node-fs.ts\",\n \"fs/promises\": \"src/shims/node-fs.ts\",\n \"node:util\": \"src/shims/node-util.ts\",\n util: \"src/shims/node-util.ts\",\n os: \"src/shims/node-os.ts\",\n \"node:os\": \"src/shims/node-os.ts\",\n stream: \"src/shims/node-stream.ts\",\n \"node:stream\": \"src/shims/node-stream.ts\",\n url: \"src/shims/node-url.ts\",\n \"node:url\": \"src/shims/node-url.ts\",\n bun: \"src/shims/bun-ffi.ts\",\n }\n\n // Virtual module prefix for npm package redirects.\n // When external opentui code imports a bare npm package (e.g. \"react\"),\n // we can't return the raw file path because Vite would serve it via /@fs/\n // without CJS-to-ESM conversion. Instead, we return a virtual module that\n // re-exports from the bare package name, which Vite processes through its\n // normal pre-bundling pipeline (including CJS conversion).\n const NPM_REDIRECT = \"\\0npm-redirect:\"\n\n const shimPlugin: Plugin = {\n name: \"gridland-web-shims\",\n enforce: \"pre\",\n resolveId(source, importer) {\n if (!importer) return null\n\n // Virtual module redirects should not be re-intercepted\n if (importer.startsWith(NPM_REDIRECT)) return null\n\n // Check if importer is in an opentui package\n const isExternalOpentui =\n importer.startsWith(coreRoot + path.sep) ||\n importer.startsWith(reactRoot + path.sep) ||\n importer.startsWith(uiRoot + path.sep)\n\n // Slider circular dep fix\n if (source === \"../index\" && importer === sliderFile) {\n return sliderDeps\n }\n\n // Resolve @opentui packages\n if (source === \"@opentui/ui\") {\n return path.resolve(uiRoot, \"src/index.ts\")\n }\n if (source === \"@opentui/react\") {\n return path.resolve(reactRoot, \"src/index.ts\")\n }\n\n // @opentui/core routing\n if (source === \"@opentui/core\") {\n if (importer.startsWith(reactRoot + path.sep)) {\n return opentuiCoreBarrel\n }\n return coreShims\n }\n\n // @opentui/* subpath imports (e.g. @opentui/react/jsx-dev-runtime)\n if (source.startsWith(\"@opentui/\")) {\n const parts = source.split(\"/\")\n const pkgName = parts[1] // \"react\", \"core\", \"ui\"\n const subpath = parts.slice(2).join(\"/\") // \"jsx-dev-runtime\"\n if (subpath) {\n const root = pkgRoots[pkgName]\n if (root) return path.resolve(root, subpath + \".js\")\n }\n }\n\n // Relative imports from opentui tree → check shims\n if (source.startsWith(\".\") && isExternalOpentui) {\n const importerDir = path.dirname(importer)\n const resolved = path.resolve(importerDir, source)\n // Devtools polyfill stub (uses top-level await for ws import)\n if (resolved.endsWith(\"devtools-polyfill\")) {\n return path.resolve(pkgRoot, \"src/shims/devtools-polyfill-stub.ts\")\n }\n const shim = resolvedCoreShims.get(resolved) || resolvedCoreShims.get(resolved + \".ts\")\n if (shim) return shim\n const indexShim = resolvedCoreShims.get(resolved + \"/index.ts\")\n if (indexShim) return indexShim\n }\n\n // Tree-sitter stubs\n if (source.includes(\"tree-sitter\") && isExternalOpentui) {\n if (source.includes(\"tree-sitter-styled-text\")) return styledTextStub\n return treeStub\n }\n if (source.includes(\"hast-styled-text\") && isExternalOpentui) {\n return path.resolve(pkgRoot, \"src/shims/hast-stub.ts\")\n }\n\n // Events shim — applies to ALL importers (browser-compatible EventEmitter)\n if (source === \"events\") {\n return path.resolve(pkgRoot, \"src/shims/events-shim.ts\")\n }\n\n // Node.js built-in stubs (only for imports from the opentui monorepo,\n // since our own workspace code doesn't import these)\n if (nodeShims[source] && isExternalOpentui) {\n return path.resolve(pkgRoot, nodeShims[source])\n }\n\n // Redirect bare npm imports from external opentui to virtual modules.\n // The virtual module re-exports from the bare package name, which lets\n // Vite's normal resolver + pre-bundler handle CJS-to-ESM conversion.\n // Skip @opentui/* since those are resolved above to monorepo source files.\n if (!source.startsWith(\".\") && !source.startsWith(\"/\") && !source.startsWith(\"@opentui/\") && isExternalOpentui) {\n return NPM_REDIRECT + source\n }\n\n return null\n },\n load(id) {\n if (id.startsWith(NPM_REDIRECT)) {\n const pkg = id.slice(NPM_REDIRECT.length)\n // Discover export names by require()-ing the module at build time.\n // We use `import * as __ns` (namespace import) which works for both\n // ESM packages (named exports on namespace) and CJS packages\n // (pre-bundled with only a default export, properties on __ns.default).\n // Each property checks both locations with a fallback.\n // NOTE: We use bare specifiers (not resolved paths) so Vite routes\n // these through its pre-bundling pipeline for CJS-to-ESM conversion.\n try {\n const mod = _require(pkg)\n if (typeof mod === \"object\" && mod !== null) {\n const names = Object.keys(mod).filter(\n (k) => k !== \"default\" && k !== \"__esModule\" && /^[a-zA-Z_$][\\w$]*$/.test(k),\n )\n if (names.length > 0) {\n return [\n `import * as __ns from \"${pkg}\";`,\n `export default __ns.default ?? __ns;`,\n ...names.map(\n (n) => `export const ${n} = __ns[\"${n}\"] ?? __ns.default?.[\"${n}\"];`,\n ),\n ].join(\"\\n\")\n }\n }\n } catch {\n // Fall through to generic approach\n }\n // Fallback for packages we can't introspect\n return [\n `export * from \"${pkg}\";`,\n `import * as __ns from \"${pkg}\";`,\n `export default __ns.default ?? __ns;`,\n ].join(\"\\n\")\n }\n },\n }\n\n const aliasPlugin: Plugin = {\n name: \"gridland-web-aliases\",\n config() {\n const aliases: Record<string, string> = {}\n\n // FFI shims\n aliases[\"bun:ffi\"] = path.resolve(pkgRoot, \"src/shims/bun-ffi.ts\")\n aliases[\"bun-ffi-structs\"] = path.resolve(pkgRoot, \"src/shims/bun-ffi-structs.ts\")\n aliases[\"node:console\"] = path.resolve(pkgRoot, \"src/shims/console.ts\")\n\n // Core file shims as aliases too\n for (const [key, shimPath] of Object.entries(coreFileShims)) {\n aliases[path.resolve(coreRoot, \"src\", key)] = path.resolve(pkgRoot, shimPath)\n }\n\n // Resolve npm packages from @gridland/web's dependency tree so\n // consuming projects don't need them as direct dependencies.\n // Uses _require to find the actual installed location (handles\n // hoisted node_modules). Directory aliases let subpath imports\n // (e.g. react-reconciler/constants) work via Vite's prefix\n // matching, and ensure CJS packages go through pre-bundling.\n for (const pkg of [\"react-reconciler\", \"yoga-layout\", \"diff\", \"marked\"]) {\n try {\n aliases[pkg] = path.dirname(_require.resolve(pkg + \"/package.json\"))\n } catch {\n aliases[pkg] = path.resolve(pkgRoot, \"node_modules\", pkg)\n }\n }\n\n return {\n define: {\n \"process.env\": JSON.stringify({}),\n },\n resolve: {\n alias: aliases,\n dedupe: [\"react\", \"react-dom\", \"react-reconciler\", \"yoga-layout\", \"events\"],\n },\n optimizeDeps: {\n // Pre-bundle npm packages imported by external opentui monorepo code.\n // These are resolved via virtual module redirects, so Vite's initial\n // crawl won't discover them — they must be listed explicitly.\n include: [\n \"react\",\n \"react-dom\",\n \"react-reconciler\",\n \"react-reconciler/constants\",\n \"diff\",\n \"yoga-layout\",\n \"marked\",\n ],\n },\n server: {\n fs: {\n // Allow serving from opentui source dirs (for dev-from-source).\n // Use strict: false so Vite's default allow list (project root) is preserved.\n strict: false,\n },\n },\n }\n },\n }\n\n return [shimPlugin, aliasPlugin]\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridland/web",
3
- "version": "0.2.13",
3
+ "version": "0.2.16",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -37,6 +37,8 @@
37
37
  "test:ci": "bun test --preload ./test/preload.ts --randomize --rerun-each 3"
38
38
  },
39
39
  "dependencies": {
40
+ "@opentui/core": "^0.1.87",
41
+ "@opentui/react": "^0.1.87",
40
42
  "diff": "^8.0.3",
41
43
  "events": "^3.3.0",
42
44
  "marked": "^17.0.3",