tempo-sdk 0.0.1 → 0.0.2

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { JSXElement } from 'oxc-parser';
2
2
  import { FilterPattern } from '@rollup/pluginutils';
3
3
  import { Plugin } from 'vite';
4
- import { ComponentType, ComponentProps, ReactElement } from 'react';
4
+ import { ReactElement } from 'react';
5
5
 
6
6
  interface ElementInfo {
7
7
  element: JSXElement;
@@ -41,18 +41,15 @@ interface StoryboardLayout {
41
41
  height: number;
42
42
  zIndex?: number;
43
43
  }
44
- interface TempoStoryboard<C extends ComponentType<any>> {
45
- component: C;
44
+ interface TempoStoryboard {
45
+ render: () => ReactElement;
46
46
  name?: string;
47
- args?: Partial<ComponentProps<C>>;
48
47
  layout: StoryboardLayout;
49
- container?: (Story: ComponentType<any>) => ReactElement;
50
48
  }
51
49
  interface TempoRouteStoryboard {
52
50
  route: string;
53
51
  name?: string;
54
52
  layout: StoryboardLayout;
55
- container?: (Story: ComponentType<any>) => ReactElement;
56
53
  }
57
54
 
58
55
  type ComputeAnnotatedProps = (info: ElementInfo, filepath: string, modifiedtsMs: number) => Record<string, PropValue>;
package/dist/index.js CHANGED
@@ -86,7 +86,11 @@ function annotateFile(source, filename, computeAnnotatedProps) {
86
86
  lastPos = position;
87
87
  }
88
88
  chunks.push(source.slice(lastPos));
89
- return { annotatedSource: chunks.join(""), elementsAnnotated: insertions.length, parseResult };
89
+ return {
90
+ annotatedSource: chunks.join(""),
91
+ elementsAnnotated: insertions.length,
92
+ parseResult
93
+ };
90
94
  }
91
95
 
92
96
  // index.ts
@@ -145,10 +149,14 @@ function loadProject(descriptor) {
145
149
  path.dirname(tsconfigPath)
146
150
  );
147
151
  if (parsed.errors.length > 0) {
148
- const message = parsed.errors.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")).join("; ");
152
+ const message = parsed.errors.map(
153
+ (diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
154
+ ).join("; ");
149
155
  throw new Error(`Failed to parse tsconfig at ${tsconfigPath}: ${message}`);
150
156
  }
151
- const normalizedFiles = parsed.fileNames.map((fileName) => canonicalPath(fileName));
157
+ const normalizedFiles = parsed.fileNames.map(
158
+ (fileName) => canonicalPath(fileName)
159
+ );
152
160
  return {
153
161
  id,
154
162
  rootDir,
@@ -173,10 +181,14 @@ function getFileMtimeVersion(filePath) {
173
181
  }
174
182
  function createTsWorkspaceService(descriptor) {
175
183
  if (descriptor.projects.length === 0) {
176
- throw new Error("TsWorkspaceDescriptor.projects must include at least one project");
184
+ throw new Error(
185
+ "TsWorkspaceDescriptor.projects must include at least one project"
186
+ );
177
187
  }
178
188
  const workspaceRoot = canonicalPath(descriptor.workspaceRoot);
179
- const loadedProjects = descriptor.projects.map((project) => loadProject(project));
189
+ const loadedProjects = descriptor.projects.map(
190
+ (project) => loadProject(project)
191
+ );
180
192
  const projectsById = /* @__PURE__ */ new Map();
181
193
  for (const project of loadedProjects) {
182
194
  if (projectsById.has(project.id)) {
@@ -186,7 +198,9 @@ function createTsWorkspaceService(descriptor) {
186
198
  }
187
199
  const primaryProject = (descriptor.primaryProjectId ? projectsById.get(descriptor.primaryProjectId) : null) ?? loadedProjects[0];
188
200
  if (descriptor.primaryProjectId && !projectsById.has(descriptor.primaryProjectId)) {
189
- throw new Error(`Primary project id not found: ${descriptor.primaryProjectId}`);
201
+ throw new Error(
202
+ `Primary project id not found: ${descriptor.primaryProjectId}`
203
+ );
190
204
  }
191
205
  const orderedProjects = [...loadedProjects].sort(compareProjectPriority);
192
206
  const rootFileNames = /* @__PURE__ */ new Set();
@@ -272,7 +286,10 @@ function createTsWorkspaceService(descriptor) {
272
286
  });
273
287
  }
274
288
  };
275
- const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());
289
+ const languageService = ts.createLanguageService(
290
+ host,
291
+ ts.createDocumentRegistry()
292
+ );
276
293
  return {
277
294
  updateFile(filePath, content) {
278
295
  const canonicalFilePath = canonicalPath(filePath);
@@ -300,7 +317,10 @@ function createTsWorkspaceService(descriptor) {
300
317
  },
301
318
  getDefinition(filePath, position) {
302
319
  const canonicalFilePath = canonicalPath(filePath);
303
- return languageService.getDefinitionAtPosition(canonicalFilePath, position);
320
+ return languageService.getDefinitionAtPosition(
321
+ canonicalFilePath,
322
+ position
323
+ );
304
324
  },
305
325
  dispose() {
306
326
  languageService.dispose();
@@ -333,7 +353,9 @@ function parseManagedTsconfigPaths(rawConfig) {
333
353
  if (!Array.isArray(managedPaths)) {
334
354
  return [];
335
355
  }
336
- return managedPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
356
+ return managedPaths.filter(
357
+ (entry) => typeof entry === "string" && entry.trim().length > 0
358
+ );
337
359
  }
338
360
  function parseProjectReferenceTsconfigPaths(references, configDir) {
339
361
  if (!references || references.length === 0) {
@@ -362,11 +384,17 @@ function buildWorkspaceProjects(root, configPath, parsedConfig, rawConfig) {
362
384
  }
363
385
  ];
364
386
  const seenTsconfigPaths = /* @__PURE__ */ new Set([canonicalPath2(configPath)]);
365
- const referencedTsconfigPaths = parseProjectReferenceTsconfigPaths(parsedConfig.projectReferences, configDir);
387
+ const referencedTsconfigPaths = parseProjectReferenceTsconfigPaths(
388
+ parsedConfig.projectReferences,
389
+ configDir
390
+ );
366
391
  const managedTsconfigPaths = parseManagedTsconfigPaths(rawConfig).map(
367
392
  (entry) => path2.resolve(configDir, entry)
368
393
  );
369
- const candidateTsconfigPaths = [...managedTsconfigPaths, ...referencedTsconfigPaths];
394
+ const candidateTsconfigPaths = [
395
+ ...managedTsconfigPaths,
396
+ ...referencedTsconfigPaths
397
+ ];
370
398
  for (const candidatePath of candidateTsconfigPaths) {
371
399
  const normalizedPath = canonicalPath2(candidatePath);
372
400
  if (seenTsconfigPaths.has(normalizedPath)) {
@@ -386,7 +414,11 @@ function buildWorkspaceProjects(root, configPath, parsedConfig, rawConfig) {
386
414
  return projects;
387
415
  }
388
416
  function createTypeAnalyzer(root) {
389
- const configPath = ts2.findConfigFile(root, ts2.sys.fileExists, "tsconfig.json");
417
+ const configPath = ts2.findConfigFile(
418
+ root,
419
+ ts2.sys.fileExists,
420
+ "tsconfig.json"
421
+ );
390
422
  if (!configPath) return null;
391
423
  const configFile = ts2.readConfigFile(configPath, ts2.sys.readFile);
392
424
  if (configFile.error) return null;
@@ -395,8 +427,15 @@ function createTypeAnalyzer(root) {
395
427
  ts2.sys,
396
428
  root
397
429
  );
398
- const workspaceProjects = buildWorkspaceProjects(root, configPath, parsedConfig, configFile.config);
399
- const workspaceProjectRoots = workspaceProjects.map((project) => canonicalPath2(project.rootDir));
430
+ const workspaceProjects = buildWorkspaceProjects(
431
+ root,
432
+ configPath,
433
+ parsedConfig,
434
+ configFile.config
435
+ );
436
+ const workspaceProjectRoots = workspaceProjects.map(
437
+ (project) => canonicalPath2(project.rootDir)
438
+ );
400
439
  const workspaceService = createTsWorkspaceService({
401
440
  workspaceRoot: root,
402
441
  primaryProjectId: "root",
@@ -524,6 +563,7 @@ function defaultComputeAnnotatedProps(info, filepath, modifiedtsMs) {
524
563
  };
525
564
  }
526
565
  function tempoAnnotate(options = {}) {
566
+ const enabled = !!process.env.TEMPO;
527
567
  const include = options.include === void 0 ? DEFAULT_INCLUDE : options.include;
528
568
  const exclude = options.exclude === void 0 ? DEFAULT_EXCLUDE : options.exclude;
529
569
  const filter = createFilter(include, exclude);
@@ -535,6 +575,7 @@ function tempoAnnotate(options = {}) {
535
575
  name: "tempo-annotate",
536
576
  enforce: "pre",
537
577
  configResolved(resolvedConfig) {
578
+ if (!enabled) return;
538
579
  command = resolvedConfig.command;
539
580
  canonicalRoot = resolveCanonicalRoot(resolvedConfig.root);
540
581
  if (command === "serve") {
@@ -542,7 +583,7 @@ function tempoAnnotate(options = {}) {
542
583
  }
543
584
  },
544
585
  transformIndexHtml(html) {
545
- if (command !== "serve") {
586
+ if (!enabled || command !== "serve") {
546
587
  return;
547
588
  }
548
589
  if (hasRootMetaTag(html)) {
@@ -560,7 +601,7 @@ function tempoAnnotate(options = {}) {
560
601
  ];
561
602
  },
562
603
  transform(source, id) {
563
- if (command === "build") {
604
+ if (!enabled || command === "build") {
564
605
  return null;
565
606
  }
566
607
  if (id.startsWith("\0")) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../../../modules/annotation/annotate-file.ts","../../../modules/file-parser/utils.ts","../../../modules/file-parser/walk.ts","../type-analyzer.ts","../../../modules/typescript/workspace-service.ts"],"sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport { relative } from \"node:path\";\n\nimport {\n annotateFile,\n type ElementInfo,\n type PropValue,\n} from \"../../modules/annotation/annotate-file.ts\";\nimport { createFilter, type FilterPattern } from \"@rollup/pluginutils\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\nimport { createTypeAnalyzer, type TypeAnalyzer } from \"./type-analyzer.ts\";\n\nconst DEFAULT_INCLUDE: FilterPattern = [\"**/*.tsx\", \"**/*.jsx\"];\nconst DEFAULT_EXCLUDE: FilterPattern = [\"**/node_modules/**\"];\nconst ROOT_META_NAME = \"tempo-project-root\";\n\nfunction cleanModuleId(id: string): string {\n return id.replace(/[?#].*$/, \"\");\n}\n\nfunction resolveCanonicalRoot(root: string): string {\n try {\n return realpathSync.native(root);\n } catch {\n return root;\n }\n}\n\nfunction hasRootMetaTag(html: string): boolean {\n return /<meta[^>]+name=[\"']tempo-project-root[\"'][^>]*>/i.test(html);\n}\n\nfunction isIntrinsicElement(tagName: string): boolean {\n return tagName.length > 0 && tagName[0] === tagName[0]!.toLowerCase();\n}\n\nfunction defaultComputeAnnotatedProps(\n info: ElementInfo,\n filepath: string,\n modifiedtsMs: number,\n): Record<string, PropValue> {\n return {\n \"data-tempo-filepath\": filepath,\n \"data-tempo-position\": info.element.openingElement.start,\n \"data-tempo-modifiedts\": modifiedtsMs,\n };\n}\n\nexport type ComputeAnnotatedProps = (\n info: ElementInfo,\n filepath: string,\n modifiedtsMs: number,\n) => Record<string, PropValue>;\n\nexport interface TempoAnnotateOptions {\n computeAnnotatedProps?: ComputeAnnotatedProps;\n include?: FilterPattern;\n exclude?: FilterPattern;\n}\n\nexport function tempoAnnotate(options: TempoAnnotateOptions = {}): Plugin {\n const include =\n options.include === undefined ? DEFAULT_INCLUDE : options.include;\n const exclude =\n options.exclude === undefined ? DEFAULT_EXCLUDE : options.exclude;\n const filter = createFilter(include, exclude);\n\n const computeAnnotatedProps =\n options.computeAnnotatedProps ?? defaultComputeAnnotatedProps;\n\n let canonicalRoot = process.cwd();\n let command: ResolvedConfig[\"command\"] = \"serve\";\n let typeAnalyzer: TypeAnalyzer | null = null;\n\n return {\n name: \"tempo-annotate\",\n enforce: \"pre\",\n configResolved(resolvedConfig) {\n command = resolvedConfig.command;\n canonicalRoot = resolveCanonicalRoot(resolvedConfig.root);\n\n if (command === \"serve\") {\n typeAnalyzer = createTypeAnalyzer(canonicalRoot);\n }\n },\n transformIndexHtml(html) {\n if (command !== \"serve\") {\n return;\n }\n\n if (hasRootMetaTag(html)) {\n return;\n }\n\n return [\n {\n tag: \"meta\",\n attrs: {\n name: ROOT_META_NAME,\n content: canonicalRoot,\n },\n injectTo: \"head\",\n },\n ];\n },\n transform(source, id) {\n if (command === \"build\") {\n return null;\n }\n\n if (id.startsWith(\"\\0\")) {\n return null;\n }\n\n const cleanId = cleanModuleId(id);\n if (!filter(cleanId)) {\n return null;\n }\n\n try {\n const filepath = relative(canonicalRoot, cleanId);\n const modifiedtsMs = Math.trunc(statSync(cleanId).mtimeMs);\n\n const typeInfo = typeAnalyzer?.analyzeFileTypes(cleanId, source);\n\n const result = annotateFile(source, cleanId, (info) => {\n const userProps = computeAnnotatedProps(info, filepath, modifiedtsMs);\n\n // Intrinsic HTML elements always support style and className — no annotation needed\n if (isIntrinsicElement(info.tagName)) {\n return userProps;\n }\n\n // Custom components: look up type support by position, default to false\n const support = typeInfo?.get(info.element.openingElement.start);\n return {\n ...userProps,\n \"data-tempo-supports-style\": support?.supportsStyle ?? false,\n \"data-tempo-supports-classname\": support?.supportsClassName ?? false,\n };\n });\n\n if (result.elementsAnnotated === 0) {\n return null;\n }\n\n return {\n code: result.annotatedSource,\n map: null,\n };\n } catch {\n return null;\n }\n },\n };\n}\n\nexport type { ElementInfo, PropValue };\n\nexport type { ElementTypeSupport, FileTypeInfo, TypeAnalyzer } from \"./type-analyzer.ts\";\nexport { createTypeAnalyzer } from \"./type-analyzer.ts\";\n\nexport type {\n TempoPage,\n StoryboardLayout,\n TempoStoryboard,\n TempoRouteStoryboard,\n} from \"./page.ts\";\n","import { parseSync, type JSXElement, type ParseResult } from 'oxc-parser';\nimport { getTagName } from '../file-parser/utils.ts';\nimport { walk } from '../file-parser/walk.ts';\n\nexport interface ElementInfo {\n element: JSXElement;\n /** e.g. \"div\", \"Button\", \"Foo.Bar\" */\n tagName: string;\n}\n\n/** Supported prop value types. `undefined` values are skipped. */\nexport type PropValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | ((...args: unknown[]) => unknown)\n | object;\n\nfunction formatPropValue(value: PropValue): string | null {\n if (value === undefined) return null;\n if (typeof value === 'function') return value.toString();\n return JSON.stringify(value);\n}\n\nfunction formatProps(props: Record<string, PropValue>): string {\n return Object.entries(props)\n .map(([key, value]) => {\n const formatted = formatPropValue(value);\n if (formatted === null) return null;\n return ` ${key}={${formatted}}`;\n })\n .filter((s): s is string => s !== null)\n .join('');\n}\n\nexport interface AnnotateFileResult {\n annotatedSource: string;\n elementsAnnotated: number;\n /** The oxc-parser result. Check `parseResult.errors` for any parse errors. */\n parseResult: ParseResult;\n}\n\n/** Tag names that represent React fragments and should not be annotated */\nconst FRAGMENT_TAG_NAMES = new Set(['Fragment', 'React.Fragment']);\n\n/**\n * Annotates JSX elements in a source file by inserting additional props.\n *\n * Visits every JSXElement in source order and calls the handler to compute\n * props to insert. Props are inserted at the end of each opening tag.\n *\n * Fragments are skipped since they don't render DOM elements:\n * - JSX shorthand fragments (`<>...</>`) are a separate AST node type\n * - `React.Fragment` and `Fragment` are skipped by tag name\n */\nexport function annotateFile(\n source: string,\n filename: string,\n computeAnnotatedProps: (info: ElementInfo) => Record<string, PropValue>\n): AnnotateFileResult {\n const parseResult = parseSync(filename, source);\n const insertions: { position: number; text: string }[] = [];\n\n // Walk the AST to find all JSXElement nodes\n // Uses our own walker instead of oxc-parser's Visitor (CJS/ESM interop issue in Electron)\n walk(parseResult.program, {\n JSXElement(node: unknown) {\n const element = node as JSXElement;\n const tagName = getTagName(element.openingElement.name);\n if (FRAGMENT_TAG_NAMES.has(tagName)) return;\n\n const props = computeAnnotatedProps({ element, tagName });\n if (Object.keys(props).length === 0) return;\n\n const openingElement = element.openingElement;\n\n // Insert before \">\" or \"/>\" at end of opening tag, skipping whitespace before \"/>\"\n let insertPos = openingElement.end - 1;\n if (openingElement.selfClosing) {\n insertPos--;\n while (insertPos > openingElement.start && /\\s/.test(source[insertPos - 1]!)) {\n insertPos--;\n }\n }\n\n insertions.push({ position: insertPos, text: formatProps(props) });\n },\n });\n\n // Build result in a single pass using chunks (O(n) instead of O(n*m))\n insertions.sort((a, b) => a.position - b.position);\n\n const chunks: string[] = [];\n let lastPos = 0;\n for (const { position, text } of insertions) {\n chunks.push(source.slice(lastPos, position));\n chunks.push(text);\n lastPos = position;\n }\n chunks.push(source.slice(lastPos));\n\n return { annotatedSource: chunks.join(''), elementsAnnotated: insertions.length, parseResult };\n}\n","\n/**\n * Annotation Utilities\n *\n * Helper functions for working with oxc-parser AST nodes.\n */\n\nimport type { JSXElementName, JSXMemberExpression } from 'oxc-parser';\n\n/**\n * Extracts the tag name string from any JSXElementName variant.\n *\n * JSXElementName is a union of three types representing different JSX tag syntaxes:\n * - JSXIdentifier: `<button>` → \"button\", `<Button>` → \"Button\"\n * - JSXNamespacedName: `<svg:rect>` → \"svg:rect\" (rare, used in SVG/XML)\n * - JSXMemberExpression: `<Foo.Bar>` → \"Foo.Bar\", `<UI.Button.Primary>` → \"UI.Button.Primary\"\n */\nexport function getTagName(name: JSXElementName): string {\n switch (name.type) {\n case 'JSXIdentifier':\n return name.name;\n case 'JSXNamespacedName':\n return `${name.namespace.name}:${name.name.name}`;\n case 'JSXMemberExpression':\n return getJSXMemberExpressionName(name);\n }\n}\n\n/**\n * Recursively builds the dotted name string from a JSXMemberExpression.\n *\n * JSXMemberExpression represents dotted component names like `<Foo.Bar.Baz>`:\n * - object: either a JSXIdentifier or another JSXMemberExpression (for chaining)\n * - property: always a JSXIdentifier (the rightmost part)\n */\nexport function getJSXMemberExpressionName(node: JSXMemberExpression): string {\n const object = node.object.type === 'JSXIdentifier' ? node.object.name : getJSXMemberExpressionName(node.object);\n return `${object}.${node.property.name}`;\n}\n","/**\n * AST Walker\n *\n * Simple recursive walker for oxc-parser ASTs. Visits every node in the tree\n * and calls type-specific callbacks. Drop-in replacement for oxc-parser's\n * Visitor class, which has CJS/ESM interop issues in Electron.\n *\n * Once oxc-parser's Visitor works in Electron, this can be swapped back.\n */\n\n/**\n * Callbacks for specific AST node types.\n * Add more node types here as needed.\n */\nexport interface WalkCallbacks {\n JSXElement?: (node: any) => void;\n}\n\n/**\n * Recursively walks an oxc-parser AST, calling callbacks for matching node types.\n * Traverses all object properties and array elements depth-first.\n */\nexport function walk(node: unknown, callbacks: WalkCallbacks): void {\n if (node === null || node === undefined || typeof node !== \"object\") return;\n\n if (Array.isArray(node)) {\n for (const child of node) {\n walk(child, callbacks);\n }\n return;\n }\n\n const record = node as Record<string, unknown>;\n const type = record.type;\n\n if (typeof type === \"string\" && type in callbacks) {\n (callbacks as Record<string, (node: unknown) => void>)[type]!(node);\n }\n\n for (const value of Object.values(record)) {\n if (value !== null && typeof value === \"object\") {\n walk(value, callbacks);\n }\n }\n}\n","/**\n * TypeScript type analyzer for JSX element prop support.\n *\n * Uses a TypeScript Language Service to determine whether each custom React\n * component supports `style` (CSSProperties-compatible) and `className`\n * (string-compatible) props. Correlation between OXC and TypeScript ASTs is\n * position-based — both use UTF-16 string indices, so element positions can\n * be compared directly.\n *\n * Intrinsic HTML elements are excluded from the analysis entirely — the\n * consumer already knows they support both from the HTML standard.\n */\nimport ts from \"typescript\";\nimport path from \"node:path\";\nimport { realpathSync } from \"node:fs\";\nimport {\n createTsWorkspaceService,\n type TsProjectDescriptor,\n type TsWorkspaceService,\n} from \"@modules/typescript\";\n\nexport interface ElementTypeSupport {\n supportsStyle: boolean;\n supportsClassName: boolean;\n}\n\n/** Position → type support for custom components only */\nexport type FileTypeInfo = Map<number, ElementTypeSupport>;\n\nexport interface TypeAnalyzer {\n analyzeFileTypes(filePath: string, source: string): FileTypeInfo | null;\n}\n\n/** Custom component if first character is uppercase or it's a member expression */\nfunction isCustomComponent(node: ts.JsxTagNameExpression): boolean {\n const text = node.getText();\n return text.length > 0 && text[0] !== text[0]!.toLowerCase();\n}\n\ninterface TempobookTsMetadata {\n managedTsconfigPaths?: unknown;\n}\n\nfunction canonicalPath(value: string): string {\n const resolved = path.resolve(value);\n try {\n return realpathSync.native(resolved);\n } catch {\n return resolved;\n }\n}\n\nfunction parseManagedTsconfigPaths(rawConfig: unknown): string[] {\n if (!rawConfig || typeof rawConfig !== \"object\" || Array.isArray(rawConfig)) {\n return [];\n }\n\n const metadata = (rawConfig as { tempobook?: TempobookTsMetadata }).tempobook;\n if (!metadata || typeof metadata !== \"object\" || Array.isArray(metadata)) {\n return [];\n }\n\n const managedPaths = metadata.managedTsconfigPaths;\n if (!Array.isArray(managedPaths)) {\n return [];\n }\n\n return managedPaths.filter((entry): entry is string => typeof entry === \"string\" && entry.trim().length > 0);\n}\n\nfunction parseProjectReferenceTsconfigPaths(\n references: readonly ts.ProjectReference[] | undefined,\n configDir: string,\n): string[] {\n if (!references || references.length === 0) {\n return [];\n }\n\n const entries: string[] = [];\n for (const reference of references) {\n const referencePath = reference.path;\n if (!referencePath) {\n continue;\n }\n\n const resolvedPath = path.resolve(configDir, referencePath);\n const tsconfigPath = resolvedPath.endsWith(\".json\")\n ? resolvedPath\n : path.join(resolvedPath, \"tsconfig.json\");\n\n entries.push(tsconfigPath);\n }\n\n return entries;\n}\n\nfunction buildWorkspaceProjects(\n root: string,\n configPath: string,\n parsedConfig: ts.ParsedCommandLine,\n rawConfig: unknown,\n): TsProjectDescriptor[] {\n const configDir = path.dirname(configPath);\n const projects: TsProjectDescriptor[] = [\n {\n id: \"root\",\n rootDir: root,\n tsconfigPath: configPath,\n priority: 0,\n },\n ];\n\n const seenTsconfigPaths = new Set<string>([canonicalPath(configPath)]);\n const referencedTsconfigPaths = parseProjectReferenceTsconfigPaths(parsedConfig.projectReferences, configDir);\n const managedTsconfigPaths = parseManagedTsconfigPaths(rawConfig).map((entry) =>\n path.resolve(configDir, entry),\n );\n\n const candidateTsconfigPaths = [...managedTsconfigPaths, ...referencedTsconfigPaths];\n for (const candidatePath of candidateTsconfigPaths) {\n const normalizedPath = canonicalPath(candidatePath);\n if (seenTsconfigPaths.has(normalizedPath)) {\n continue;\n }\n if (!ts.sys.fileExists(normalizedPath)) {\n continue;\n }\n\n seenTsconfigPaths.add(normalizedPath);\n projects.push({\n id: `external-${projects.length}`,\n rootDir: path.dirname(normalizedPath),\n tsconfigPath: normalizedPath,\n priority: 0,\n });\n }\n\n return projects;\n}\n\n/**\n * Create a type analyzer backed by a TypeScript Language Service.\n *\n * The Language Service provides incremental updates — when a file changes,\n * we bump its version and provide the new content. The service lazily\n * recomputes only what's needed.\n *\n * Returns null if no tsconfig.json is found.\n */\nexport function createTypeAnalyzer(root: string): TypeAnalyzer | null {\n const configPath = ts.findConfigFile(root, ts.sys.fileExists, \"tsconfig.json\");\n if (!configPath) return null;\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n if (configFile.error) return null;\n\n const parsedConfig = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n root,\n );\n\n const workspaceProjects = buildWorkspaceProjects(root, configPath, parsedConfig, configFile.config);\n const workspaceProjectRoots = workspaceProjects.map((project) => canonicalPath(project.rootDir));\n\n const workspaceService: TsWorkspaceService = createTsWorkspaceService({\n workspaceRoot: root,\n primaryProjectId: \"root\",\n projects: workspaceProjects,\n });\n\n // Lazily resolved CSSProperties type for style compatibility checks.\n // Resolved from JSX.IntrinsicElements['div'].style, with the undefined\n // union member stripped to get the pure CSSProperties type.\n let cssPropertiesType: ts.Type | null | undefined;\n\n function resolveCSSPropertiesType(\n checker: ts.TypeChecker,\n sourceFile: ts.SourceFile,\n ): ts.Type | null {\n if (cssPropertiesType !== undefined) return cssPropertiesType;\n\n try {\n // JSX namespace → IntrinsicElements → div → style → unwrap undefined\n const jsxNs = (checker as any).resolveName(\n \"JSX\", sourceFile, ts.SymbolFlags.Namespace, false,\n );\n if (!jsxNs) { cssPropertiesType = null; return null; }\n\n const intrinsicSym = checker.getExportsOfModule(jsxNs)\n .find((s) => s.name === \"IntrinsicElements\");\n if (!intrinsicSym) { cssPropertiesType = null; return null; }\n\n const divSym = checker.getDeclaredTypeOfSymbol(intrinsicSym)\n .getProperty(\"div\");\n if (!divSym) { cssPropertiesType = null; return null; }\n\n const styleSym = checker.getTypeOfSymbol(divSym).getProperty(\"style\");\n if (!styleSym) { cssPropertiesType = null; return null; }\n\n const styleType = checker.getTypeOfSymbol(styleSym);\n\n // styleType is CSSProperties | undefined — extract the non-undefined member\n if (styleType.isUnion()) {\n const nonUndefined = styleType.types.find(\n (t) => !(t.flags & ts.TypeFlags.Undefined),\n );\n cssPropertiesType = nonUndefined ?? null;\n } else {\n cssPropertiesType = styleType;\n }\n } catch {\n cssPropertiesType = null;\n }\n\n return cssPropertiesType;\n }\n\n return {\n analyzeFileTypes(filePath: string, source: string): FileTypeInfo | null {\n const canonicalFilePath = canonicalPath(filePath);\n const belongsToWorkspace = workspaceProjectRoots.some(\n (projectRoot) =>\n canonicalFilePath === projectRoot ||\n canonicalFilePath.startsWith(`${projectRoot}${path.sep}`),\n );\n if (!belongsToWorkspace) {\n return null;\n }\n\n // Update the workspace service with current in-memory source.\n workspaceService.updateFile(filePath, source);\n\n const program = workspaceService.getProgram();\n if (!program) return null;\n\n const sourceFile = program.getSourceFile(filePath);\n if (!sourceFile) return null;\n\n const checker = program.getTypeChecker();\n const cssProps = resolveCSSPropertiesType(checker, sourceFile);\n const result: FileTypeInfo = new Map();\n\n function visit(node: ts.Node) {\n if (\n (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) &&\n isCustomComponent(node.tagName)\n ) {\n const position = node.getStart(sourceFile);\n const attrsType = checker.getContextualType(node.attributes);\n\n let supportsStyle = false;\n let supportsClassName = false;\n\n if (attrsType) {\n // className: check that `string` is assignable to the prop's type\n const classNameProp = attrsType.getProperty(\"className\");\n if (classNameProp) {\n const propType = checker.getTypeOfSymbol(classNameProp);\n supportsClassName = (checker as any).isTypeAssignableTo(\n checker.getStringType(), propType,\n );\n }\n\n // style: check that CSSProperties is assignable to the prop's type\n const styleProp = attrsType.getProperty(\"style\");\n if (styleProp && cssProps) {\n const propType = checker.getTypeOfSymbol(styleProp);\n supportsStyle = (checker as any).isTypeAssignableTo(\n cssProps, propType,\n );\n }\n }\n\n result.set(position, { supportsStyle, supportsClassName });\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return result;\n },\n };\n}\n","import { realpathSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport ts from \"typescript\";\n\nexport interface TsProjectDescriptor {\n id: string;\n rootDir: string;\n tsconfigPath: string;\n priority?: number;\n}\n\nexport interface TsWorkspaceDescriptor {\n workspaceRoot: string;\n projects: TsProjectDescriptor[];\n primaryProjectId?: string;\n}\n\nexport interface TsWorkspaceService {\n updateFile(filePath: string, content: string): void;\n closeFile(filePath: string): void;\n getProgram(): ts.Program | null;\n getSemanticDiagnostics(filePath: string): readonly ts.Diagnostic[];\n getDefinition(filePath: string, position: number): readonly ts.DefinitionInfo[] | undefined;\n dispose(): void;\n}\n\ninterface LoadedProject {\n id: string;\n rootDir: string;\n tsconfigPath: string;\n priority: number;\n options: ts.CompilerOptions;\n fileNames: string[];\n moduleResolutionCache: ts.ModuleResolutionCache;\n}\n\ninterface InMemoryFile {\n version: number;\n content: string;\n}\n\nfunction canonicalPath(input: string): string {\n const resolved = path.resolve(input);\n try {\n return realpathSync.native(resolved);\n } catch {\n return resolved;\n }\n}\n\nfunction compareProjectPriority(left: LoadedProject, right: LoadedProject): number {\n const depthDelta = right.rootDir.length - left.rootDir.length;\n if (depthDelta !== 0) {\n return depthDelta;\n }\n\n const priorityDelta = right.priority - left.priority;\n if (priorityDelta !== 0) {\n return priorityDelta;\n }\n\n return left.id.localeCompare(right.id);\n}\n\nfunction isWithinRoot(filePath: string, rootDir: string): boolean {\n return filePath === rootDir || filePath.startsWith(`${rootDir}${path.sep}`);\n}\n\nfunction loadProject(descriptor: TsProjectDescriptor): LoadedProject {\n const id = descriptor.id.trim();\n if (!id) {\n throw new Error(\"Project id must be a non-empty string\");\n }\n\n const tsconfigPath = canonicalPath(descriptor.tsconfigPath);\n const rootDir = canonicalPath(descriptor.rootDir);\n\n const readResult = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n if (readResult.error) {\n throw new Error(\n `Failed to read tsconfig at ${tsconfigPath}: ${ts.flattenDiagnosticMessageText(\n readResult.error.messageText,\n \"\\n\",\n )}`,\n );\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n readResult.config,\n ts.sys,\n path.dirname(tsconfigPath),\n );\n\n if (parsed.errors.length > 0) {\n const message = parsed.errors\n .map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, \"\\n\"))\n .join(\"; \");\n throw new Error(`Failed to parse tsconfig at ${tsconfigPath}: ${message}`);\n }\n\n const normalizedFiles = parsed.fileNames.map((fileName) => canonicalPath(fileName));\n return {\n id,\n rootDir,\n tsconfigPath,\n priority: descriptor.priority ?? 0,\n options: parsed.options,\n fileNames: normalizedFiles,\n moduleResolutionCache: ts.createModuleResolutionCache(\n rootDir,\n (value) => value,\n parsed.options,\n ),\n };\n}\n\nfunction getFileMtimeVersion(filePath: string): string {\n try {\n const stats = statSync(filePath);\n return String(stats.mtimeMs);\n } catch {\n return \"0\";\n }\n}\n\nexport function createTsWorkspaceService(\n descriptor: TsWorkspaceDescriptor,\n): TsWorkspaceService {\n if (descriptor.projects.length === 0) {\n throw new Error(\"TsWorkspaceDescriptor.projects must include at least one project\");\n }\n\n const workspaceRoot = canonicalPath(descriptor.workspaceRoot);\n const loadedProjects = descriptor.projects.map((project) => loadProject(project));\n\n const projectsById = new Map<string, LoadedProject>();\n for (const project of loadedProjects) {\n if (projectsById.has(project.id)) {\n throw new Error(`Duplicate project id: ${project.id}`);\n }\n projectsById.set(project.id, project);\n }\n\n const primaryProject =\n (descriptor.primaryProjectId ? projectsById.get(descriptor.primaryProjectId) : null) ??\n loadedProjects[0]!;\n if (descriptor.primaryProjectId && !projectsById.has(descriptor.primaryProjectId)) {\n throw new Error(`Primary project id not found: ${descriptor.primaryProjectId}`);\n }\n\n const orderedProjects = [...loadedProjects].sort(compareProjectPriority);\n const rootFileNames = new Set<string>();\n for (const project of loadedProjects) {\n for (const fileName of project.fileNames) {\n rootFileNames.add(fileName);\n }\n }\n\n const inMemoryFiles = new Map<string, InMemoryFile>();\n let projectVersion = 0;\n\n function getOwningProject(filePath: string): LoadedProject {\n const canonicalFilePath = canonicalPath(filePath);\n for (const project of orderedProjects) {\n if (isWithinRoot(canonicalFilePath, project.rootDir)) {\n return project;\n }\n }\n return primaryProject;\n }\n\n const moduleResolutionHost: ts.ModuleResolutionHost = {\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n realpath: ts.sys.realpath,\n directoryExists: ts.sys.directoryExists,\n getCurrentDirectory: () => workspaceRoot,\n getDirectories: ts.sys.getDirectories,\n };\n\n const host: ts.LanguageServiceHost = {\n getScriptFileNames: () => Array.from(rootFileNames),\n getScriptVersion: (filePath) => {\n const canonicalFilePath = canonicalPath(filePath);\n const inMemory = inMemoryFiles.get(canonicalFilePath);\n if (inMemory) {\n return String(inMemory.version);\n }\n return getFileMtimeVersion(canonicalFilePath);\n },\n getScriptSnapshot: (filePath) => {\n const canonicalFilePath = canonicalPath(filePath);\n const inMemory = inMemoryFiles.get(canonicalFilePath);\n if (inMemory) {\n return ts.ScriptSnapshot.fromString(inMemory.content);\n }\n\n const diskContent = ts.sys.readFile(canonicalFilePath);\n if (diskContent === undefined) {\n return undefined;\n }\n return ts.ScriptSnapshot.fromString(diskContent);\n },\n getCurrentDirectory: () => workspaceRoot,\n getCompilationSettings: () => primaryProject.options,\n getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getProjectVersion: () => String(projectVersion),\n resolveModuleNames: (moduleNames, containingFile) => {\n const owningProject = getOwningProject(containingFile);\n\n return moduleNames.map((moduleName) => {\n const ownerResolution = ts.resolveModuleName(\n moduleName,\n containingFile,\n owningProject.options,\n moduleResolutionHost,\n owningProject.moduleResolutionCache,\n ).resolvedModule;\n\n if (ownerResolution) {\n return ownerResolution;\n }\n\n if (owningProject.id === primaryProject.id) {\n return undefined;\n }\n\n return ts.resolveModuleName(\n moduleName,\n containingFile,\n primaryProject.options,\n moduleResolutionHost,\n primaryProject.moduleResolutionCache,\n ).resolvedModule;\n });\n },\n };\n\n const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());\n\n return {\n updateFile(filePath: string, content: string): void {\n const canonicalFilePath = canonicalPath(filePath);\n const currentVersion = inMemoryFiles.get(canonicalFilePath)?.version ?? 0;\n inMemoryFiles.set(canonicalFilePath, {\n version: currentVersion + 1,\n content,\n });\n\n if (!rootFileNames.has(canonicalFilePath)) {\n rootFileNames.add(canonicalFilePath);\n }\n\n projectVersion += 1;\n },\n closeFile(filePath: string): void {\n const canonicalFilePath = canonicalPath(filePath);\n inMemoryFiles.delete(canonicalFilePath);\n projectVersion += 1;\n },\n getProgram(): ts.Program | null {\n return languageService.getProgram() ?? null;\n },\n getSemanticDiagnostics(filePath: string): readonly ts.Diagnostic[] {\n const canonicalFilePath = canonicalPath(filePath);\n return languageService.getSemanticDiagnostics(canonicalFilePath);\n },\n getDefinition(\n filePath: string,\n position: number,\n ): readonly ts.DefinitionInfo[] | undefined {\n const canonicalFilePath = canonicalPath(filePath);\n return languageService.getDefinitionAtPosition(canonicalFilePath, position);\n },\n dispose(): void {\n languageService.dispose();\n },\n };\n}\n\n"],"mappings":"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","names":["realpathSync","statSync","ts","path","realpathSync","canonicalPath","path","realpathSync","ts","realpathSync","statSync"]}
1
+ {"version":3,"sources":["../index.ts","../../../modules/annotation/annotate-file.ts","../../../modules/file-parser/utils.ts","../../../modules/file-parser/walk.ts","../type-analyzer.ts","../../../modules/typescript/workspace-service.ts"],"sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport { relative } from \"node:path\";\n\nimport {\n annotateFile,\n type ElementInfo,\n type PropValue,\n} from \"../../modules/annotation/annotate-file.ts\";\nimport { createFilter, type FilterPattern } from \"@rollup/pluginutils\";\nimport type { Plugin, ResolvedConfig } from \"vite\";\nimport { createTypeAnalyzer, type TypeAnalyzer } from \"./type-analyzer.ts\";\n\nconst DEFAULT_INCLUDE: FilterPattern = [\"**/*.tsx\", \"**/*.jsx\"];\nconst DEFAULT_EXCLUDE: FilterPattern = [\"**/node_modules/**\"];\nconst ROOT_META_NAME = \"tempo-project-root\";\n\nfunction cleanModuleId(id: string): string {\n return id.replace(/[?#].*$/, \"\");\n}\n\nfunction resolveCanonicalRoot(root: string): string {\n try {\n return realpathSync.native(root);\n } catch {\n return root;\n }\n}\n\nfunction hasRootMetaTag(html: string): boolean {\n return /<meta[^>]+name=[\"']tempo-project-root[\"'][^>]*>/i.test(html);\n}\n\nfunction isIntrinsicElement(tagName: string): boolean {\n return tagName.length > 0 && tagName[0] === tagName[0]!.toLowerCase();\n}\n\nfunction defaultComputeAnnotatedProps(\n info: ElementInfo,\n filepath: string,\n modifiedtsMs: number,\n): Record<string, PropValue> {\n return {\n \"data-tempo-filepath\": filepath,\n \"data-tempo-position\": info.element.openingElement.start,\n \"data-tempo-modifiedts\": modifiedtsMs,\n };\n}\n\nexport type ComputeAnnotatedProps = (\n info: ElementInfo,\n filepath: string,\n modifiedtsMs: number,\n) => Record<string, PropValue>;\n\nexport interface TempoAnnotateOptions {\n computeAnnotatedProps?: ComputeAnnotatedProps;\n include?: FilterPattern;\n exclude?: FilterPattern;\n}\n\nexport function tempoAnnotate(options: TempoAnnotateOptions = {}): Plugin {\n // The plugin is a complete no-op unless the TEMPO env var is set.\n // This lets users keep tempoAnnotate() in their vite config permanently\n // while only paying for annotation when running via Tempo's start script\n // (which sets TEMPO=true).\n const enabled = !!process.env.TEMPO;\n\n const include =\n options.include === undefined ? DEFAULT_INCLUDE : options.include;\n const exclude =\n options.exclude === undefined ? DEFAULT_EXCLUDE : options.exclude;\n const filter = createFilter(include, exclude);\n\n const computeAnnotatedProps =\n options.computeAnnotatedProps ?? defaultComputeAnnotatedProps;\n\n let canonicalRoot = process.cwd();\n let command: ResolvedConfig[\"command\"] = \"serve\";\n let typeAnalyzer: TypeAnalyzer | null = null;\n\n return {\n name: \"tempo-annotate\",\n enforce: \"pre\",\n configResolved(resolvedConfig) {\n if (!enabled) return;\n\n command = resolvedConfig.command;\n canonicalRoot = resolveCanonicalRoot(resolvedConfig.root);\n\n if (command === \"serve\") {\n typeAnalyzer = createTypeAnalyzer(canonicalRoot);\n }\n },\n transformIndexHtml(html) {\n if (!enabled || command !== \"serve\") {\n return;\n }\n\n if (hasRootMetaTag(html)) {\n return;\n }\n\n return [\n {\n tag: \"meta\",\n attrs: {\n name: ROOT_META_NAME,\n content: canonicalRoot,\n },\n injectTo: \"head\",\n },\n ];\n },\n transform(source, id) {\n if (!enabled || command === \"build\") {\n return null;\n }\n\n if (id.startsWith(\"\\0\")) {\n return null;\n }\n\n const cleanId = cleanModuleId(id);\n if (!filter(cleanId)) {\n return null;\n }\n\n try {\n const filepath = relative(canonicalRoot, cleanId);\n const modifiedtsMs = Math.trunc(statSync(cleanId).mtimeMs);\n\n const typeInfo = typeAnalyzer?.analyzeFileTypes(cleanId, source);\n\n const result = annotateFile(source, cleanId, (info) => {\n const userProps = computeAnnotatedProps(info, filepath, modifiedtsMs);\n\n // Intrinsic HTML elements always support style and className — no annotation needed\n if (isIntrinsicElement(info.tagName)) {\n return userProps;\n }\n\n // Custom components: look up type support by position, default to false\n const support = typeInfo?.get(info.element.openingElement.start);\n return {\n ...userProps,\n \"data-tempo-supports-style\": support?.supportsStyle ?? false,\n \"data-tempo-supports-classname\":\n support?.supportsClassName ?? false,\n };\n });\n\n if (result.elementsAnnotated === 0) {\n return null;\n }\n\n return {\n code: result.annotatedSource,\n map: null,\n };\n } catch {\n return null;\n }\n },\n };\n}\n\nexport type { ElementInfo, PropValue };\n\nexport type {\n ElementTypeSupport,\n FileTypeInfo,\n TypeAnalyzer,\n} from \"./type-analyzer.ts\";\nexport { createTypeAnalyzer } from \"./type-analyzer.ts\";\n\nexport type {\n TempoPage,\n StoryboardLayout,\n TempoStoryboard,\n TempoRouteStoryboard,\n} from \"./page.ts\";\n","import { parseSync, type JSXElement, type ParseResult } from \"oxc-parser\";\nimport { getTagName } from \"../file-parser/utils.ts\";\nimport { walk } from \"../file-parser/walk.ts\";\n\nexport interface ElementInfo {\n element: JSXElement;\n /** e.g. \"div\", \"Button\", \"Foo.Bar\" */\n tagName: string;\n}\n\n/** Supported prop value types. `undefined` values are skipped. */\nexport type PropValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | ((...args: unknown[]) => unknown)\n | object;\n\nfunction formatPropValue(value: PropValue): string | null {\n if (value === undefined) return null;\n if (typeof value === \"function\") return value.toString();\n return JSON.stringify(value);\n}\n\nfunction formatProps(props: Record<string, PropValue>): string {\n return Object.entries(props)\n .map(([key, value]) => {\n const formatted = formatPropValue(value);\n if (formatted === null) return null;\n return ` ${key}={${formatted}}`;\n })\n .filter((s): s is string => s !== null)\n .join(\"\");\n}\n\nexport interface AnnotateFileResult {\n annotatedSource: string;\n elementsAnnotated: number;\n /** The oxc-parser result. Check `parseResult.errors` for any parse errors. */\n parseResult: ParseResult;\n}\n\n/** Tag names that represent React fragments and should not be annotated */\nconst FRAGMENT_TAG_NAMES = new Set([\"Fragment\", \"React.Fragment\"]);\n\n/**\n * Annotates JSX elements in a source file by inserting additional props.\n *\n * Visits every JSXElement in source order and calls the handler to compute\n * props to insert. Props are inserted at the end of each opening tag.\n *\n * Fragments are skipped since they don't render DOM elements:\n * - JSX shorthand fragments (`<>...</>`) are a separate AST node type\n * - `React.Fragment` and `Fragment` are skipped by tag name\n */\nexport function annotateFile(\n source: string,\n filename: string,\n computeAnnotatedProps: (info: ElementInfo) => Record<string, PropValue>,\n): AnnotateFileResult {\n const parseResult = parseSync(filename, source);\n const insertions: { position: number; text: string }[] = [];\n\n // Walk the AST to find all JSXElement nodes\n // Uses our own walker instead of oxc-parser's Visitor (CJS/ESM interop issue in Electron)\n walk(parseResult.program, {\n JSXElement(node: unknown) {\n const element = node as JSXElement;\n const tagName = getTagName(element.openingElement.name);\n if (FRAGMENT_TAG_NAMES.has(tagName)) return;\n\n const props = computeAnnotatedProps({ element, tagName });\n if (Object.keys(props).length === 0) return;\n\n const openingElement = element.openingElement;\n\n // Insert before \">\" or \"/>\" at end of opening tag, skipping whitespace before \"/>\"\n let insertPos = openingElement.end - 1;\n if (openingElement.selfClosing) {\n insertPos--;\n while (\n insertPos > openingElement.start &&\n /\\s/.test(source[insertPos - 1]!)\n ) {\n insertPos--;\n }\n }\n\n insertions.push({ position: insertPos, text: formatProps(props) });\n },\n });\n\n // Build result in a single pass using chunks (O(n) instead of O(n*m))\n insertions.sort((a, b) => a.position - b.position);\n\n const chunks: string[] = [];\n let lastPos = 0;\n for (const { position, text } of insertions) {\n chunks.push(source.slice(lastPos, position));\n chunks.push(text);\n lastPos = position;\n }\n chunks.push(source.slice(lastPos));\n\n return {\n annotatedSource: chunks.join(\"\"),\n elementsAnnotated: insertions.length,\n parseResult,\n };\n}\n","/**\n * Annotation Utilities\n *\n * Helper functions for working with oxc-parser AST nodes.\n */\n\nimport type { JSXElementName, JSXMemberExpression } from \"oxc-parser\";\n\n/**\n * Extracts the tag name string from any JSXElementName variant.\n *\n * JSXElementName is a union of three types representing different JSX tag syntaxes:\n * - JSXIdentifier: `<button>` → \"button\", `<Button>` → \"Button\"\n * - JSXNamespacedName: `<svg:rect>` → \"svg:rect\" (rare, used in SVG/XML)\n * - JSXMemberExpression: `<Foo.Bar>` → \"Foo.Bar\", `<UI.Button.Primary>` → \"UI.Button.Primary\"\n */\nexport function getTagName(name: JSXElementName): string {\n switch (name.type) {\n case \"JSXIdentifier\":\n return name.name;\n case \"JSXNamespacedName\":\n return `${name.namespace.name}:${name.name.name}`;\n case \"JSXMemberExpression\":\n return getJSXMemberExpressionName(name);\n }\n}\n\n/**\n * Recursively builds the dotted name string from a JSXMemberExpression.\n *\n * JSXMemberExpression represents dotted component names like `<Foo.Bar.Baz>`:\n * - object: either a JSXIdentifier or another JSXMemberExpression (for chaining)\n * - property: always a JSXIdentifier (the rightmost part)\n */\nexport function getJSXMemberExpressionName(node: JSXMemberExpression): string {\n const object =\n node.object.type === \"JSXIdentifier\"\n ? node.object.name\n : getJSXMemberExpressionName(node.object);\n return `${object}.${node.property.name}`;\n}\n","/**\n * AST Walker\n *\n * Simple recursive walker for oxc-parser ASTs. Visits every node in the tree\n * and calls type-specific callbacks. Drop-in replacement for oxc-parser's\n * Visitor class, which has CJS/ESM interop issues in Electron.\n *\n * Once oxc-parser's Visitor works in Electron, this can be swapped back.\n */\n\n/**\n * Callbacks for specific AST node types.\n * Add more node types here as needed.\n */\nexport interface WalkCallbacks {\n JSXElement?: (node: any) => void;\n}\n\n/**\n * Recursively walks an oxc-parser AST, calling callbacks for matching node types.\n * Traverses all object properties and array elements depth-first.\n */\nexport function walk(node: unknown, callbacks: WalkCallbacks): void {\n if (node === null || node === undefined || typeof node !== \"object\") return;\n\n if (Array.isArray(node)) {\n for (const child of node) {\n walk(child, callbacks);\n }\n return;\n }\n\n const record = node as Record<string, unknown>;\n const type = record.type;\n\n if (typeof type === \"string\" && type in callbacks) {\n (callbacks as Record<string, (node: unknown) => void>)[type]!(node);\n }\n\n for (const value of Object.values(record)) {\n if (value !== null && typeof value === \"object\") {\n walk(value, callbacks);\n }\n }\n}\n","/**\n * TypeScript type analyzer for JSX element prop support.\n *\n * Uses a TypeScript Language Service to determine whether each custom React\n * component supports `style` (CSSProperties-compatible) and `className`\n * (string-compatible) props. Correlation between OXC and TypeScript ASTs is\n * position-based — both use UTF-16 string indices, so element positions can\n * be compared directly.\n *\n * Intrinsic HTML elements are excluded from the analysis entirely — the\n * consumer already knows they support both from the HTML standard.\n */\nimport ts from \"typescript\";\nimport path from \"node:path\";\nimport { realpathSync } from \"node:fs\";\nimport {\n createTsWorkspaceService,\n type TsProjectDescriptor,\n type TsWorkspaceService,\n} from \"@modules/typescript\";\n\nexport interface ElementTypeSupport {\n supportsStyle: boolean;\n supportsClassName: boolean;\n}\n\n/** Position → type support for custom components only */\nexport type FileTypeInfo = Map<number, ElementTypeSupport>;\n\nexport interface TypeAnalyzer {\n analyzeFileTypes(filePath: string, source: string): FileTypeInfo | null;\n}\n\n/** Custom component if first character is uppercase or it's a member expression */\nfunction isCustomComponent(node: ts.JsxTagNameExpression): boolean {\n const text = node.getText();\n return text.length > 0 && text[0] !== text[0]!.toLowerCase();\n}\n\ninterface TempobookTsMetadata {\n managedTsconfigPaths?: unknown;\n}\n\nfunction canonicalPath(value: string): string {\n const resolved = path.resolve(value);\n try {\n return realpathSync.native(resolved);\n } catch {\n return resolved;\n }\n}\n\nfunction parseManagedTsconfigPaths(rawConfig: unknown): string[] {\n if (!rawConfig || typeof rawConfig !== \"object\" || Array.isArray(rawConfig)) {\n return [];\n }\n\n const metadata = (rawConfig as { tempobook?: TempobookTsMetadata }).tempobook;\n if (!metadata || typeof metadata !== \"object\" || Array.isArray(metadata)) {\n return [];\n }\n\n const managedPaths = metadata.managedTsconfigPaths;\n if (!Array.isArray(managedPaths)) {\n return [];\n }\n\n return managedPaths.filter(\n (entry): entry is string =>\n typeof entry === \"string\" && entry.trim().length > 0,\n );\n}\n\nfunction parseProjectReferenceTsconfigPaths(\n references: readonly ts.ProjectReference[] | undefined,\n configDir: string,\n): string[] {\n if (!references || references.length === 0) {\n return [];\n }\n\n const entries: string[] = [];\n for (const reference of references) {\n const referencePath = reference.path;\n if (!referencePath) {\n continue;\n }\n\n const resolvedPath = path.resolve(configDir, referencePath);\n const tsconfigPath = resolvedPath.endsWith(\".json\")\n ? resolvedPath\n : path.join(resolvedPath, \"tsconfig.json\");\n\n entries.push(tsconfigPath);\n }\n\n return entries;\n}\n\nfunction buildWorkspaceProjects(\n root: string,\n configPath: string,\n parsedConfig: ts.ParsedCommandLine,\n rawConfig: unknown,\n): TsProjectDescriptor[] {\n const configDir = path.dirname(configPath);\n const projects: TsProjectDescriptor[] = [\n {\n id: \"root\",\n rootDir: root,\n tsconfigPath: configPath,\n priority: 0,\n },\n ];\n\n const seenTsconfigPaths = new Set<string>([canonicalPath(configPath)]);\n const referencedTsconfigPaths = parseProjectReferenceTsconfigPaths(\n parsedConfig.projectReferences,\n configDir,\n );\n const managedTsconfigPaths = parseManagedTsconfigPaths(rawConfig).map(\n (entry) => path.resolve(configDir, entry),\n );\n\n const candidateTsconfigPaths = [\n ...managedTsconfigPaths,\n ...referencedTsconfigPaths,\n ];\n for (const candidatePath of candidateTsconfigPaths) {\n const normalizedPath = canonicalPath(candidatePath);\n if (seenTsconfigPaths.has(normalizedPath)) {\n continue;\n }\n if (!ts.sys.fileExists(normalizedPath)) {\n continue;\n }\n\n seenTsconfigPaths.add(normalizedPath);\n projects.push({\n id: `external-${projects.length}`,\n rootDir: path.dirname(normalizedPath),\n tsconfigPath: normalizedPath,\n priority: 0,\n });\n }\n\n return projects;\n}\n\n/**\n * Create a type analyzer backed by a TypeScript Language Service.\n *\n * The Language Service provides incremental updates — when a file changes,\n * we bump its version and provide the new content. The service lazily\n * recomputes only what's needed.\n *\n * Returns null if no tsconfig.json is found.\n */\nexport function createTypeAnalyzer(root: string): TypeAnalyzer | null {\n const configPath = ts.findConfigFile(\n root,\n ts.sys.fileExists,\n \"tsconfig.json\",\n );\n if (!configPath) return null;\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n if (configFile.error) return null;\n\n const parsedConfig = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n root,\n );\n\n const workspaceProjects = buildWorkspaceProjects(\n root,\n configPath,\n parsedConfig,\n configFile.config,\n );\n const workspaceProjectRoots = workspaceProjects.map((project) =>\n canonicalPath(project.rootDir),\n );\n\n const workspaceService: TsWorkspaceService = createTsWorkspaceService({\n workspaceRoot: root,\n primaryProjectId: \"root\",\n projects: workspaceProjects,\n });\n\n // Lazily resolved CSSProperties type for style compatibility checks.\n // Resolved from JSX.IntrinsicElements['div'].style, with the undefined\n // union member stripped to get the pure CSSProperties type.\n let cssPropertiesType: ts.Type | null | undefined;\n\n function resolveCSSPropertiesType(\n checker: ts.TypeChecker,\n sourceFile: ts.SourceFile,\n ): ts.Type | null {\n if (cssPropertiesType !== undefined) return cssPropertiesType;\n\n try {\n // JSX namespace → IntrinsicElements → div → style → unwrap undefined\n const jsxNs = (checker as any).resolveName(\n \"JSX\",\n sourceFile,\n ts.SymbolFlags.Namespace,\n false,\n );\n if (!jsxNs) {\n cssPropertiesType = null;\n return null;\n }\n\n const intrinsicSym = checker\n .getExportsOfModule(jsxNs)\n .find((s) => s.name === \"IntrinsicElements\");\n if (!intrinsicSym) {\n cssPropertiesType = null;\n return null;\n }\n\n const divSym = checker\n .getDeclaredTypeOfSymbol(intrinsicSym)\n .getProperty(\"div\");\n if (!divSym) {\n cssPropertiesType = null;\n return null;\n }\n\n const styleSym = checker.getTypeOfSymbol(divSym).getProperty(\"style\");\n if (!styleSym) {\n cssPropertiesType = null;\n return null;\n }\n\n const styleType = checker.getTypeOfSymbol(styleSym);\n\n // styleType is CSSProperties | undefined — extract the non-undefined member\n if (styleType.isUnion()) {\n const nonUndefined = styleType.types.find(\n (t) => !(t.flags & ts.TypeFlags.Undefined),\n );\n cssPropertiesType = nonUndefined ?? null;\n } else {\n cssPropertiesType = styleType;\n }\n } catch {\n cssPropertiesType = null;\n }\n\n return cssPropertiesType;\n }\n\n return {\n analyzeFileTypes(filePath: string, source: string): FileTypeInfo | null {\n const canonicalFilePath = canonicalPath(filePath);\n const belongsToWorkspace = workspaceProjectRoots.some(\n (projectRoot) =>\n canonicalFilePath === projectRoot ||\n canonicalFilePath.startsWith(`${projectRoot}${path.sep}`),\n );\n if (!belongsToWorkspace) {\n return null;\n }\n\n // Update the workspace service with current in-memory source.\n workspaceService.updateFile(filePath, source);\n\n const program = workspaceService.getProgram();\n if (!program) return null;\n\n const sourceFile = program.getSourceFile(filePath);\n if (!sourceFile) return null;\n\n const checker = program.getTypeChecker();\n const cssProps = resolveCSSPropertiesType(checker, sourceFile);\n const result: FileTypeInfo = new Map();\n\n function visit(node: ts.Node) {\n if (\n (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) &&\n isCustomComponent(node.tagName)\n ) {\n const position = node.getStart(sourceFile);\n const attrsType = checker.getContextualType(node.attributes);\n\n let supportsStyle = false;\n let supportsClassName = false;\n\n if (attrsType) {\n // className: check that `string` is assignable to the prop's type\n const classNameProp = attrsType.getProperty(\"className\");\n if (classNameProp) {\n const propType = checker.getTypeOfSymbol(classNameProp);\n supportsClassName = (checker as any).isTypeAssignableTo(\n checker.getStringType(),\n propType,\n );\n }\n\n // style: check that CSSProperties is assignable to the prop's type\n const styleProp = attrsType.getProperty(\"style\");\n if (styleProp && cssProps) {\n const propType = checker.getTypeOfSymbol(styleProp);\n supportsStyle = (checker as any).isTypeAssignableTo(\n cssProps,\n propType,\n );\n }\n }\n\n result.set(position, { supportsStyle, supportsClassName });\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return result;\n },\n };\n}\n","import { realpathSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport ts from \"typescript\";\n\nexport interface TsProjectDescriptor {\n id: string;\n rootDir: string;\n tsconfigPath: string;\n priority?: number;\n}\n\nexport interface TsWorkspaceDescriptor {\n workspaceRoot: string;\n projects: TsProjectDescriptor[];\n primaryProjectId?: string;\n}\n\nexport interface TsWorkspaceService {\n updateFile(filePath: string, content: string): void;\n closeFile(filePath: string): void;\n getProgram(): ts.Program | null;\n getSemanticDiagnostics(filePath: string): readonly ts.Diagnostic[];\n getDefinition(\n filePath: string,\n position: number,\n ): readonly ts.DefinitionInfo[] | undefined;\n dispose(): void;\n}\n\ninterface LoadedProject {\n id: string;\n rootDir: string;\n tsconfigPath: string;\n priority: number;\n options: ts.CompilerOptions;\n fileNames: string[];\n moduleResolutionCache: ts.ModuleResolutionCache;\n}\n\ninterface InMemoryFile {\n version: number;\n content: string;\n}\n\nfunction canonicalPath(input: string): string {\n const resolved = path.resolve(input);\n try {\n return realpathSync.native(resolved);\n } catch {\n return resolved;\n }\n}\n\nfunction compareProjectPriority(\n left: LoadedProject,\n right: LoadedProject,\n): number {\n const depthDelta = right.rootDir.length - left.rootDir.length;\n if (depthDelta !== 0) {\n return depthDelta;\n }\n\n const priorityDelta = right.priority - left.priority;\n if (priorityDelta !== 0) {\n return priorityDelta;\n }\n\n return left.id.localeCompare(right.id);\n}\n\nfunction isWithinRoot(filePath: string, rootDir: string): boolean {\n return filePath === rootDir || filePath.startsWith(`${rootDir}${path.sep}`);\n}\n\nfunction loadProject(descriptor: TsProjectDescriptor): LoadedProject {\n const id = descriptor.id.trim();\n if (!id) {\n throw new Error(\"Project id must be a non-empty string\");\n }\n\n const tsconfigPath = canonicalPath(descriptor.tsconfigPath);\n const rootDir = canonicalPath(descriptor.rootDir);\n\n const readResult = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n if (readResult.error) {\n throw new Error(\n `Failed to read tsconfig at ${tsconfigPath}: ${ts.flattenDiagnosticMessageText(\n readResult.error.messageText,\n \"\\n\",\n )}`,\n );\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n readResult.config,\n ts.sys,\n path.dirname(tsconfigPath),\n );\n\n if (parsed.errors.length > 0) {\n const message = parsed.errors\n .map((diagnostic) =>\n ts.flattenDiagnosticMessageText(diagnostic.messageText, \"\\n\"),\n )\n .join(\"; \");\n throw new Error(`Failed to parse tsconfig at ${tsconfigPath}: ${message}`);\n }\n\n const normalizedFiles = parsed.fileNames.map((fileName) =>\n canonicalPath(fileName),\n );\n return {\n id,\n rootDir,\n tsconfigPath,\n priority: descriptor.priority ?? 0,\n options: parsed.options,\n fileNames: normalizedFiles,\n moduleResolutionCache: ts.createModuleResolutionCache(\n rootDir,\n (value) => value,\n parsed.options,\n ),\n };\n}\n\nfunction getFileMtimeVersion(filePath: string): string {\n try {\n const stats = statSync(filePath);\n return String(stats.mtimeMs);\n } catch {\n return \"0\";\n }\n}\n\nexport function createTsWorkspaceService(\n descriptor: TsWorkspaceDescriptor,\n): TsWorkspaceService {\n if (descriptor.projects.length === 0) {\n throw new Error(\n \"TsWorkspaceDescriptor.projects must include at least one project\",\n );\n }\n\n const workspaceRoot = canonicalPath(descriptor.workspaceRoot);\n const loadedProjects = descriptor.projects.map((project) =>\n loadProject(project),\n );\n\n const projectsById = new Map<string, LoadedProject>();\n for (const project of loadedProjects) {\n if (projectsById.has(project.id)) {\n throw new Error(`Duplicate project id: ${project.id}`);\n }\n projectsById.set(project.id, project);\n }\n\n const primaryProject =\n (descriptor.primaryProjectId\n ? projectsById.get(descriptor.primaryProjectId)\n : null) ?? loadedProjects[0]!;\n if (\n descriptor.primaryProjectId &&\n !projectsById.has(descriptor.primaryProjectId)\n ) {\n throw new Error(\n `Primary project id not found: ${descriptor.primaryProjectId}`,\n );\n }\n\n const orderedProjects = [...loadedProjects].sort(compareProjectPriority);\n const rootFileNames = new Set<string>();\n for (const project of loadedProjects) {\n for (const fileName of project.fileNames) {\n rootFileNames.add(fileName);\n }\n }\n\n const inMemoryFiles = new Map<string, InMemoryFile>();\n let projectVersion = 0;\n\n function getOwningProject(filePath: string): LoadedProject {\n const canonicalFilePath = canonicalPath(filePath);\n for (const project of orderedProjects) {\n if (isWithinRoot(canonicalFilePath, project.rootDir)) {\n return project;\n }\n }\n return primaryProject;\n }\n\n const moduleResolutionHost: ts.ModuleResolutionHost = {\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n realpath: ts.sys.realpath,\n directoryExists: ts.sys.directoryExists,\n getCurrentDirectory: () => workspaceRoot,\n getDirectories: ts.sys.getDirectories,\n };\n\n const host: ts.LanguageServiceHost = {\n getScriptFileNames: () => Array.from(rootFileNames),\n getScriptVersion: (filePath) => {\n const canonicalFilePath = canonicalPath(filePath);\n const inMemory = inMemoryFiles.get(canonicalFilePath);\n if (inMemory) {\n return String(inMemory.version);\n }\n return getFileMtimeVersion(canonicalFilePath);\n },\n getScriptSnapshot: (filePath) => {\n const canonicalFilePath = canonicalPath(filePath);\n const inMemory = inMemoryFiles.get(canonicalFilePath);\n if (inMemory) {\n return ts.ScriptSnapshot.fromString(inMemory.content);\n }\n\n const diskContent = ts.sys.readFile(canonicalFilePath);\n if (diskContent === undefined) {\n return undefined;\n }\n return ts.ScriptSnapshot.fromString(diskContent);\n },\n getCurrentDirectory: () => workspaceRoot,\n getCompilationSettings: () => primaryProject.options,\n getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getProjectVersion: () => String(projectVersion),\n resolveModuleNames: (moduleNames, containingFile) => {\n const owningProject = getOwningProject(containingFile);\n\n return moduleNames.map((moduleName) => {\n const ownerResolution = ts.resolveModuleName(\n moduleName,\n containingFile,\n owningProject.options,\n moduleResolutionHost,\n owningProject.moduleResolutionCache,\n ).resolvedModule;\n\n if (ownerResolution) {\n return ownerResolution;\n }\n\n if (owningProject.id === primaryProject.id) {\n return undefined;\n }\n\n return ts.resolveModuleName(\n moduleName,\n containingFile,\n primaryProject.options,\n moduleResolutionHost,\n primaryProject.moduleResolutionCache,\n ).resolvedModule;\n });\n },\n };\n\n const languageService = ts.createLanguageService(\n host,\n ts.createDocumentRegistry(),\n );\n\n return {\n updateFile(filePath: string, content: string): void {\n const canonicalFilePath = canonicalPath(filePath);\n const currentVersion = inMemoryFiles.get(canonicalFilePath)?.version ?? 0;\n inMemoryFiles.set(canonicalFilePath, {\n version: currentVersion + 1,\n content,\n });\n\n if (!rootFileNames.has(canonicalFilePath)) {\n rootFileNames.add(canonicalFilePath);\n }\n\n projectVersion += 1;\n },\n closeFile(filePath: string): void {\n const canonicalFilePath = canonicalPath(filePath);\n inMemoryFiles.delete(canonicalFilePath);\n projectVersion += 1;\n },\n getProgram(): ts.Program | null {\n return languageService.getProgram() ?? null;\n },\n getSemanticDiagnostics(filePath: string): readonly ts.Diagnostic[] {\n const canonicalFilePath = canonicalPath(filePath);\n return languageService.getSemanticDiagnostics(canonicalFilePath);\n },\n getDefinition(\n filePath: string,\n position: number,\n ): readonly ts.DefinitionInfo[] | undefined {\n const canonicalFilePath = canonicalPath(filePath);\n return languageService.getDefinitionAtPosition(\n canonicalFilePath,\n position,\n );\n },\n dispose(): void {\n languageService.dispose();\n },\n };\n}\n"],"mappings":"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","names":["realpathSync","statSync","ts","path","realpathSync","canonicalPath","path","realpathSync","ts","realpathSync","statSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempo-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "description": "Tempo SDK — Vite plugin for JSX annotation and shared page/storyboard types",
6
6
  "exports": {
@@ -9,13 +9,9 @@
9
9
  "types": "./dist/index.d.ts"
10
10
  }
11
11
  },
12
- "files": ["dist"],
13
- "scripts": {
14
- "build": "tsup",
15
- "prepublishOnly": "pnpm build",
16
- "test": "vitest run",
17
- "test:watch": "vitest"
18
- },
12
+ "files": [
13
+ "dist"
14
+ ],
19
15
  "dependencies": {
20
16
  "@rollup/pluginutils": "^5.1.0",
21
17
  "oxc-parser": "^0.110.0"
@@ -26,14 +22,19 @@
26
22
  "vite": "^5 || ^6 || ^7"
27
23
  },
28
24
  "devDependencies": {
29
- "@modules/annotation": "workspace:*",
30
- "@modules/typescript": "workspace:*",
31
25
  "@types/node": "^25.0.8",
32
- "@types/react": "catalog:",
33
- "@vitejs/plugin-react": "catalog:",
26
+ "@types/react": "^18.3.17",
27
+ "@vitejs/plugin-react": "^5.1.2",
34
28
  "tsup": "^8.5.1",
35
- "typescript": "catalog:",
36
- "vite": "catalog:",
37
- "vitest": "catalog:"
29
+ "typescript": "^5.9.3",
30
+ "vite": "^7.3.1",
31
+ "vitest": "^4.0.18",
32
+ "@modules/annotation": "0.0.1",
33
+ "@modules/typescript": "0.0.1"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest"
38
39
  }
39
- }
40
+ }
package/dist/page.d.ts DELETED
@@ -1,27 +0,0 @@
1
- import { ComponentType, ComponentProps, ReactElement } from 'react';
2
-
3
- interface TempoPage {
4
- name: string;
5
- }
6
- interface StoryboardLayout {
7
- x: number;
8
- y: number;
9
- width: number;
10
- height: number;
11
- zIndex?: number;
12
- }
13
- interface TempoStoryboard<C extends ComponentType<any>> {
14
- component: C;
15
- name?: string;
16
- args?: Partial<ComponentProps<C>>;
17
- layout: StoryboardLayout;
18
- container?: (Story: ComponentType<any>) => ReactElement;
19
- }
20
- interface TempoRouteStoryboard {
21
- route: string;
22
- name?: string;
23
- layout: StoryboardLayout;
24
- container?: (Story: ComponentType<any>) => ReactElement;
25
- }
26
-
27
- export type { StoryboardLayout, TempoPage, TempoRouteStoryboard, TempoStoryboard };
package/dist/page.js DELETED
@@ -1 +0,0 @@
1
- //# sourceMappingURL=page.js.map
package/dist/page.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}