@pygmalionjs/pygmalion 0.2.40 → 0.2.41

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.
@@ -1,4 +1,4 @@
1
- import { F as s, N as a, e as r, s as i, a as t } from "./App-CiVUoaTo.js";
1
+ import { F as s, N as a, e as r, s as i, a as t } from "./App-kzN-1Je6.js";
2
2
  export {
3
3
  s as FrozenRoutePreviewView,
4
4
  a as NodeModel,
@@ -29,6 +29,31 @@ const MAX_SOURCE_BYTES = 1024 * 1024;
29
29
  const MAX_ENVIRONMENT_BYTES = 16 * 1024;
30
30
  const MAX_EXECUTION_RESULTS_BYTES = 64 * 1024 * 1024;
31
31
 
32
+ function normalizeRoutePath(value) {
33
+ if (typeof value !== 'string' || !value.trim()) return null;
34
+ const pathname = value.trim().split(/[?#]/, 1)[0].replace(/\/{2,}/g, '/');
35
+ const rooted = pathname.startsWith('/') ? pathname : `/${pathname}`;
36
+ return rooted.length > 1 ? rooted.replace(/\/+$/, '') : rooted;
37
+ }
38
+
39
+ function routePatternMatches(pattern, concrete) {
40
+ const normalizedPattern = normalizeRoutePath(pattern);
41
+ const normalizedConcrete = normalizeRoutePath(concrete);
42
+ if (!normalizedPattern || !normalizedConcrete) return false;
43
+ const patternSegments = normalizedPattern.split('/').filter(Boolean);
44
+ const concreteSegments = normalizedConcrete.split('/').filter(Boolean);
45
+ let concreteIndex = 0;
46
+ for (const segment of patternSegments) {
47
+ if (segment === '*' || segment.startsWith('*')) return true;
48
+ const concreteSegment = concreteSegments[concreteIndex];
49
+ if (segment.endsWith('?') && concreteSegment == null) continue;
50
+ if (concreteSegment == null) return false;
51
+ if (!segment.startsWith(':') && segment !== concreteSegment) return false;
52
+ concreteIndex += 1;
53
+ }
54
+ return concreteIndex === concreteSegments.length;
55
+ }
56
+
32
57
  function normalizedRelativePath(root, file) {
33
58
  return path.relative(root, file).split(path.sep).join('/');
34
59
  }
@@ -1151,12 +1176,14 @@ function associateRouteCandidates(manifest, graph, fileDigests = new Map()) {
1151
1176
  };
1152
1177
  });
1153
1178
 
1154
- const knownRoutes = new Set(routes.map((route) => route.path));
1179
+ const knownRoutes = routes.map((route) => route.path);
1180
+ const targetIsKnown = (target) =>
1181
+ knownRoutes.some((route) => routePatternMatches(route, target));
1155
1182
  const uniqueEdges = [
1156
1183
  ...new Map(
1157
1184
  edges.map((edge) => [
1158
1185
  `${edge.from}:${edge.to}:${edge.kind}:${edge.evidence.sourcePath}:${edge.evidence.line}`,
1159
- { ...edge, unresolvedTarget: !knownRoutes.has(edge.to) },
1186
+ { ...edge, unresolvedTarget: !targetIsKnown(edge.to) },
1160
1187
  ]),
1161
1188
  ).values(),
1162
1189
  ].sort((a, b) => a.id.localeCompare(b.id));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pygmalionjs/pygmalion",
3
- "version": "0.2.40",
3
+ "version": "0.2.41",
4
4
  "description": "Code-backed DOM design sandbox and visual QA editor",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
package/types.d.ts CHANGED
@@ -1206,6 +1206,26 @@ export interface StoryboardGraphEdgeInput {
1206
1206
  label?: string;
1207
1207
  }
1208
1208
 
1209
+ export interface StoryboardPathInput {
1210
+ /** Stable author-owned identity used as the edge id prefix. */
1211
+ id: string;
1212
+ /** Ordered screen ids visited by this path. */
1213
+ screenIds: readonly string[];
1214
+ kind?: string;
1215
+ label?: string;
1216
+ }
1217
+
1218
+ export interface StoryboardDefinition {
1219
+ paths?: readonly StoryboardPathInput[];
1220
+ edges?: readonly StoryboardGraphEdgeInput[];
1221
+ startScreenIds?: readonly string[];
1222
+ nonVisualScenarioIds?: readonly string[];
1223
+ }
1224
+
1225
+ export declare function createStoryboardPathEdges(
1226
+ paths: readonly StoryboardPathInput[],
1227
+ ): StoryboardGraphEdgeInput[];
1228
+
1209
1229
  export interface StoryboardGraphBuildOptions {
1210
1230
  screens: readonly DesignScreenCase[];
1211
1231
  assets?: readonly DesignImportAsset[];
@@ -1452,6 +1472,8 @@ export interface StoryboardDiscoveryGraphOptions {
1452
1472
  manifest: StoryboardDiscoveryManifest;
1453
1473
  pages: readonly StoryboardResolvedPage[];
1454
1474
  assets?: readonly DesignImportAsset[];
1475
+ /** Host-authored user journeys layered over source-inferred transitions. */
1476
+ storyboard?: StoryboardDefinition;
1455
1477
  }
1456
1478
 
1457
1479
  export interface StoryboardDiscoveryResult {
@@ -1488,6 +1510,7 @@ export declare function resolveStoryboardScreenCases(
1488
1510
  pages: readonly StoryboardResolvedPage[],
1489
1511
  manifest: StoryboardDiscoveryManifest,
1490
1512
  ): DesignScreenCase[];
1513
+ export declare function createStoryboardRouteScenarioId(route: string): string;
1491
1514
  export declare function getStoryboardDiscoveryBaselineEnvironment(
1492
1515
  manifest: StoryboardDiscoveryManifest,
1493
1516
  ): StoryboardEnvironment | undefined;
@@ -1993,6 +2016,8 @@ export declare function PygmalionEditor(props: {
1993
2016
  ) => Promise<InspectPreviewResult>;
1994
2017
  /** Check the reverse dependency closure of the changed source file. */
1995
2018
  onInspectImpact?: (componentFiles: string[]) => Promise<InspectImpactResult>;
2019
+ /** Authored screen paths and starts merged with source-discovered navigation. */
2020
+ storyboard?: StoryboardDefinition;
1996
2021
  /** Detect portable browser branches from source before route frames boot. Default true. */
1997
2022
  storyboardDiscovery?: boolean;
1998
2023
  /** Vite endpoint that returns the generated generic storyboard environment manifest. */