@contentful/experience-design-system-cli 2.37.1-dev-build-c1d02862.0 → 2.37.1-dev-build-e5882940.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +3190 -317
- package/dist/index.js +3461 -316
- package/dist/package.json +1 -1
- package/dist/src/tui/import/steps/07-scope-gate/cache-check.d.ts +29 -0
- package/{legacy/dist/src/import/tui/scope-gate-columns.d.ts → dist/src/tui/import/steps/07-scope-gate/columns.d.ts} +22 -2
- package/dist/src/tui/import/steps/07-scope-gate/graph/composite-closure.d.ts +26 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/cycle-detection.d.ts +22 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/fuzzy-search.d.ts +3 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/index.d.ts +33 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/lineage.d.ts +29 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/search-neighborhood.d.ts +3 -0
- package/dist/src/tui/import/steps/07-scope-gate/graph/slot-graph.d.ts +11 -0
- package/dist/src/tui/import/steps/07-scope-gate/keymap.d.ts +84 -0
- package/dist/src/tui/import/steps/07-scope-gate/load.d.ts +8 -0
- package/dist/src/tui/import/steps/07-scope-gate/panels/added-column.d.ts +15 -0
- package/dist/src/tui/import/steps/07-scope-gate/panels/cycles-panel.d.ts +8 -0
- package/dist/src/tui/import/steps/07-scope-gate/panels/reject-prompt.d.ts +5 -0
- package/dist/src/tui/import/steps/07-scope-gate/screen.d.ts +9 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/autocomplete.d.ts +5 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.d.ts +4 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/GotoBanner.d.ts +32 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.d.ts +93 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.d.ts +21 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/LegendEntry.d.ts +2 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.d.ts +11 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/badge.d.ts +13 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/windowed-panel.d.ts +17 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/group-collapse.d.ts +2 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/sidebar-search-state.d.ts +17 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.d.ts +6 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/useImmediateInput.d.ts +20 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/useOverlayPanel.d.ts +13 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/lineage-layout.d.ts +68 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-help.d.ts +2 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-input.d.ts +13 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-navigation.d.ts +18 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/step-filters.d.ts +19 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/theme.d.ts +8 -0
- package/dist/src/tui/import/steps/07-scope-gate/sidebar/types.d.ts +7 -0
- package/dist/src/tui/import/steps/07-scope-gate/state.d.ts +19 -0
- package/dist/src/tui/import/steps/07-scope-gate/types.d.ts +24 -0
- package/dist/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.d.ts +31 -0
- package/dist/src/tui/import/steps/07-scope-gate/use-scope-gate.d.ts +76 -0
- package/legacy/dist/src/import/tui/handoff.d.ts +11 -0
- package/legacy/dist/src/index.js +1513 -2732
- package/legacy/package.json +1 -1
- package/package.json +4 -4
- package/legacy/dist/src/import/tui/steps/ScopeGateStep.d.ts +0 -48
- /package/{legacy/dist/src/analyze → dist/src/tui/import/steps/07-scope-gate/graph}/scope-gate-cascade.d.ts +0 -0
- /package/{legacy/dist/src/import/tui → dist/src/tui/import/steps/07-scope-gate/sidebar}/ai-flag.d.ts +0 -0
- /package/{legacy/dist/src/import/tui → dist/src/tui/import/steps/07-scope-gate/sidebar}/components/CounterStrip.d.ts +0 -0
package/dist/app.js
CHANGED
|
@@ -760,8 +760,8 @@ async function runAgent(options) {
|
|
|
760
760
|
const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
|
|
761
761
|
const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
|
|
762
762
|
const binary = resolveBinary(agent);
|
|
763
|
-
const
|
|
764
|
-
const args = buildArgs(agent, prompt, model,
|
|
763
|
+
const useStdin2 = !!promptViaStdin;
|
|
764
|
+
const args = buildArgs(agent, prompt, model, useStdin2, bedrock);
|
|
765
765
|
const startedAt = Date.now();
|
|
766
766
|
onDebugEvent?.("run.start", {
|
|
767
767
|
agent,
|
|
@@ -778,7 +778,7 @@ async function runAgent(options) {
|
|
|
778
778
|
stdio: ["pipe", "pipe", "pipe"],
|
|
779
779
|
...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
|
|
780
780
|
});
|
|
781
|
-
if (
|
|
781
|
+
if (useStdin2 && child.stdin) {
|
|
782
782
|
child.stdin.on("error", () => {
|
|
783
783
|
});
|
|
784
784
|
child.stdin.write(prompt, () => {
|
|
@@ -2001,7 +2001,7 @@ var init_cache_keys = __esm({
|
|
|
2001
2001
|
|
|
2002
2002
|
// packages/experience-design-system-cli/app.tsx
|
|
2003
2003
|
import { join as join13 } from "node:path";
|
|
2004
|
-
import { useEffect as
|
|
2004
|
+
import { useEffect as useEffect14, useState as useState20 } from "react";
|
|
2005
2005
|
|
|
2006
2006
|
// packages/experience-design-system-cli/src/tui/home/home.tsx
|
|
2007
2007
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
@@ -2071,8 +2071,8 @@ function readPackageVersion() {
|
|
|
2071
2071
|
return pkg.version ?? "unknown";
|
|
2072
2072
|
}
|
|
2073
2073
|
function parseVersionTag(tag) {
|
|
2074
|
-
const
|
|
2075
|
-
return
|
|
2074
|
+
const match2 = /^v(\d+\.\d+\.\d+)$/.exec(tag);
|
|
2075
|
+
return match2 ? match2[1] : void 0;
|
|
2076
2076
|
}
|
|
2077
2077
|
async function checkForUpgrade() {
|
|
2078
2078
|
const current = readPackageVersion();
|
|
@@ -3093,6 +3093,34 @@ function parseReviewReasons(raw) {
|
|
|
3093
3093
|
return [];
|
|
3094
3094
|
}
|
|
3095
3095
|
}
|
|
3096
|
+
function loadScopeComponents(db, sessionId) {
|
|
3097
|
+
const rows = db.prepare(`SELECT name, component_id, status, reject_reason, review_reasons, needs_review FROM raw_components
|
|
3098
|
+
WHERE session_id = ? AND status IN ('extracted', 'accepted', 'rejected')
|
|
3099
|
+
ORDER BY name`).all(sessionId);
|
|
3100
|
+
if (rows.length === 0)
|
|
3101
|
+
return [];
|
|
3102
|
+
const slotRows = db.prepare(`SELECT component_id, name, position
|
|
3103
|
+
FROM raw_slots WHERE session_id = ? ORDER BY component_id, position`).all(sessionId);
|
|
3104
|
+
const allowedRows = db.prepare(`SELECT component_id, slot_name, position, allowed_component
|
|
3105
|
+
FROM raw_slot_allowed_components WHERE session_id = ? ORDER BY component_id, slot_name, position`).all(sessionId);
|
|
3106
|
+
const slotsByComponent = indexRowsByKey(slotRows, (s) => s.component_id);
|
|
3107
|
+
const allowedBySlot = indexRowsByKey(allowedRows, (a) => `${a.component_id}::${a.slot_name}`);
|
|
3108
|
+
return rows.map((r) => {
|
|
3109
|
+
const reviewReasons = parseReviewReasons(r.review_reasons);
|
|
3110
|
+
const nonAuthorableReason = reviewReasons.find((reason) => reason.startsWith("non-authorable:"));
|
|
3111
|
+
return {
|
|
3112
|
+
name: r.name,
|
|
3113
|
+
componentId: r.component_id,
|
|
3114
|
+
aiDecision: r.status === "accepted" ? "accepted" : r.status === "rejected" ? "rejected" : null,
|
|
3115
|
+
aiReason: r.reject_reason ?? nonAuthorableReason?.slice("non-authorable:".length) ?? null,
|
|
3116
|
+
needsReview: Boolean(r.needs_review),
|
|
3117
|
+
slots: (slotsByComponent.get(r.component_id) ?? []).map((s) => ({
|
|
3118
|
+
name: s.name,
|
|
3119
|
+
allowedComponents: (allowedBySlot.get(`${r.component_id}::${s.name}`) ?? []).map((a) => a.allowed_component)
|
|
3120
|
+
}))
|
|
3121
|
+
};
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3096
3124
|
var _cliCacheVersionCache = null;
|
|
3097
3125
|
async function getCliCacheVersion() {
|
|
3098
3126
|
if (_cliCacheVersionCache)
|
|
@@ -3720,9 +3748,9 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
|
|
|
3720
3748
|
let url = _url;
|
|
3721
3749
|
const matches = _url.match(PATH_PARAM_RE);
|
|
3722
3750
|
if (matches) {
|
|
3723
|
-
for (const
|
|
3751
|
+
for (const match2 of matches) {
|
|
3724
3752
|
let explode = false;
|
|
3725
|
-
let name =
|
|
3753
|
+
let name = match2.substring(1, match2.length - 1);
|
|
3726
3754
|
let style = "simple";
|
|
3727
3755
|
if (name.endsWith("*")) {
|
|
3728
3756
|
explode = true;
|
|
@@ -3740,11 +3768,11 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
|
|
|
3740
3768
|
continue;
|
|
3741
3769
|
}
|
|
3742
3770
|
if (Array.isArray(value)) {
|
|
3743
|
-
url = url.replace(
|
|
3771
|
+
url = url.replace(match2, serializeArrayParam({ explode, name, style, value }));
|
|
3744
3772
|
continue;
|
|
3745
3773
|
}
|
|
3746
3774
|
if (typeof value === "object") {
|
|
3747
|
-
url = url.replace(
|
|
3775
|
+
url = url.replace(match2, serializeObjectParam({
|
|
3748
3776
|
explode,
|
|
3749
3777
|
name,
|
|
3750
3778
|
style,
|
|
@@ -3754,19 +3782,19 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
|
|
|
3754
3782
|
continue;
|
|
3755
3783
|
}
|
|
3756
3784
|
if (style === "matrix") {
|
|
3757
|
-
url = url.replace(
|
|
3785
|
+
url = url.replace(match2, `;${serializePrimitiveParam({
|
|
3758
3786
|
name,
|
|
3759
3787
|
value
|
|
3760
3788
|
})}`);
|
|
3761
3789
|
continue;
|
|
3762
3790
|
}
|
|
3763
3791
|
const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
|
|
3764
|
-
url = url.replace(
|
|
3792
|
+
url = url.replace(match2, replaceValue);
|
|
3765
3793
|
}
|
|
3766
3794
|
}
|
|
3767
3795
|
return url;
|
|
3768
3796
|
};
|
|
3769
|
-
var createQuerySerializer = ({ allowReserved, array:
|
|
3797
|
+
var createQuerySerializer = ({ allowReserved, array: array4, object: object2 } = {}) => {
|
|
3770
3798
|
const querySerializer = (queryParams) => {
|
|
3771
3799
|
const search = [];
|
|
3772
3800
|
if (queryParams && typeof queryParams === "object") {
|
|
@@ -3782,7 +3810,7 @@ var createQuerySerializer = ({ allowReserved, array: array3, object: object2 } =
|
|
|
3782
3810
|
name,
|
|
3783
3811
|
style: "form",
|
|
3784
3812
|
value,
|
|
3785
|
-
...
|
|
3813
|
+
...array4
|
|
3786
3814
|
});
|
|
3787
3815
|
if (serializedArray)
|
|
3788
3816
|
search.push(serializedArray);
|
|
@@ -5354,12 +5382,12 @@ function findSession(stdout) {
|
|
|
5354
5382
|
return null;
|
|
5355
5383
|
}
|
|
5356
5384
|
function parseExtractedCount(stderr) {
|
|
5357
|
-
const
|
|
5358
|
-
return
|
|
5385
|
+
const match2 = EXTRACTED.exec(stderr);
|
|
5386
|
+
return match2 ? Number(match2[1]) : 0;
|
|
5359
5387
|
}
|
|
5360
5388
|
function parsePrintTokensCount(stdout) {
|
|
5361
|
-
const
|
|
5362
|
-
return
|
|
5389
|
+
const match2 = PRINT_TOKENS_COUNT.exec(stdout);
|
|
5390
|
+
return match2 ? Number(match2[1]) : 0;
|
|
5363
5391
|
}
|
|
5364
5392
|
function initialProgress(input) {
|
|
5365
5393
|
return {
|
|
@@ -6140,8 +6168,8 @@ async function runAgent2(options) {
|
|
|
6140
6168
|
const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
|
|
6141
6169
|
const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
|
|
6142
6170
|
const binary = resolveAgentBinary(agent);
|
|
6143
|
-
const
|
|
6144
|
-
const args = buildAgentArgs(agent, prompt, model,
|
|
6171
|
+
const useStdin2 = !!promptViaStdin;
|
|
6172
|
+
const args = buildAgentArgs(agent, prompt, model, useStdin2, bedrock);
|
|
6145
6173
|
const startedAt = Date.now();
|
|
6146
6174
|
onDebugEvent?.("run.start", {
|
|
6147
6175
|
agent,
|
|
@@ -6158,7 +6186,7 @@ async function runAgent2(options) {
|
|
|
6158
6186
|
stdio: ["pipe", "pipe", "pipe"],
|
|
6159
6187
|
...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
|
|
6160
6188
|
});
|
|
6161
|
-
if (
|
|
6189
|
+
if (useStdin2 && child.stdin) {
|
|
6162
6190
|
child.stdin.on("error", () => {
|
|
6163
6191
|
});
|
|
6164
6192
|
child.stdin.write(prompt, () => {
|
|
@@ -6692,194 +6720,2988 @@ function useExtraction(input) {
|
|
|
6692
6720
|
return state;
|
|
6693
6721
|
}
|
|
6694
6722
|
|
|
6695
|
-
// packages/experience-design-system-cli/src/tui/import/
|
|
6696
|
-
import {
|
|
6723
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
|
|
6724
|
+
import { Box as Box20, Text as Text22 } from "ink";
|
|
6697
6725
|
|
|
6698
|
-
// packages/experience-design-system-cli/src/
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
...options.prompt.flatMap((value) => ["--prompt", value]),
|
|
6703
|
-
...options.cache ? [] : ["--no-cache"]
|
|
6704
|
-
];
|
|
6705
|
-
}
|
|
6726
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/added-column.tsx
|
|
6727
|
+
import React6 from "react";
|
|
6728
|
+
import { Box as Box11, Text as Text12 } from "ink";
|
|
6729
|
+
import figures from "figures";
|
|
6706
6730
|
|
|
6707
|
-
// packages/experience-design-system-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
strategy: z5.enum(["reuse", "regenerate", "generate"])
|
|
6717
|
-
});
|
|
6718
|
-
var ExtractionSchema = z5.object({
|
|
6719
|
-
sessionId: NonEmpty,
|
|
6720
|
-
outDir: NonEmpty,
|
|
6721
|
-
tokensPath: z5.string(),
|
|
6722
|
-
tokenSessionId: z5.nullable(z5.string()),
|
|
6723
|
-
tokenCount: z5.number(),
|
|
6724
|
-
existingEntitiesPath: z5.nullable(z5.string()),
|
|
6725
|
-
/** Never 'running': the wizard starts its background cache check only once this has settled. */
|
|
6726
|
-
existingEntitiesStatus: z5.enum(["idle", "complete", "failed"]),
|
|
6727
|
-
/** The only phases the scope gate can start from. */
|
|
6728
|
-
compositionPhase: z5.enum(["done", "cache-hit"])
|
|
6729
|
-
});
|
|
6730
|
-
var ImportHandoffSchema = z5.object({
|
|
6731
|
-
/** The user skipped the credentials screen, so nothing is fetched from or pushed to Contentful. */
|
|
6732
|
-
credentialsSkipped: z5.boolean(),
|
|
6733
|
-
tokens: TokensSchema,
|
|
6734
|
-
/** Present once the CLI has run the extraction stage; the wizard then starts at the scope gate. */
|
|
6735
|
-
extraction: z5.optional(ExtractionSchema)
|
|
6736
|
-
});
|
|
6737
|
-
function serializeHandoff(handoff) {
|
|
6738
|
-
return JSON.stringify(handoff);
|
|
6739
|
-
}
|
|
6731
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/theme.ts
|
|
6732
|
+
var PALETTE2 = {
|
|
6733
|
+
info: PALETTE.accent,
|
|
6734
|
+
success: PALETTE.success,
|
|
6735
|
+
error: PALETTE.error,
|
|
6736
|
+
warning: PALETTE.warning,
|
|
6737
|
+
muted: PALETTE.muted,
|
|
6738
|
+
border: PALETTE.border
|
|
6739
|
+
};
|
|
6740
6740
|
|
|
6741
|
-
// packages/experience-design-system-cli/src/tui/import/
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6741
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/columns.ts
|
|
6742
|
+
var TWO_COLUMN_MIN_WIDTH = 100;
|
|
6743
|
+
var SCOPE_GATE_MAIN_COLUMN_WIDTH = 54;
|
|
6744
|
+
var ACCEPTED_COMPONENTS_COLUMN_WIDTH = 36;
|
|
6745
|
+
var PANEL_BORDER_ROWS = 2;
|
|
6746
|
+
var PANEL_INDICATOR_ROWS = 2;
|
|
6747
|
+
var PANEL_HEADER_ROWS = 2;
|
|
6748
|
+
function computePanelLayout(mainVisibleCount) {
|
|
6749
|
+
const safeMainVisibleCount = Math.max(1, mainVisibleCount);
|
|
6750
|
+
const height = safeMainVisibleCount + PANEL_BORDER_ROWS + PANEL_INDICATOR_ROWS + PANEL_HEADER_ROWS;
|
|
6751
|
+
const sideVisibleCount = Math.max(1, height - PANEL_BORDER_ROWS - PANEL_INDICATOR_ROWS - PANEL_HEADER_ROWS);
|
|
6752
|
+
return { height, mainVisibleCount: safeMainVisibleCount, sideVisibleCount };
|
|
6753
|
+
}
|
|
6754
|
+
function computeColumnWidths(totalWidth) {
|
|
6755
|
+
if (totalWidth < TWO_COLUMN_MIN_WIDTH) {
|
|
6756
|
+
return { layout: "single", main: SCOPE_GATE_MAIN_COLUMN_WIDTH, added: 0 };
|
|
6757
|
+
}
|
|
6758
|
+
const main = SCOPE_GATE_MAIN_COLUMN_WIDTH;
|
|
6759
|
+
const added = ACCEPTED_COMPONENTS_COLUMN_WIDTH;
|
|
6760
|
+
return { layout: "two-column", main, added };
|
|
6761
|
+
}
|
|
6762
|
+
function sortTieredEntries(cycleTier, restTier) {
|
|
6763
|
+
cycleTier.sort((a, b) => a.name.localeCompare(b.name));
|
|
6764
|
+
restTier.sort((a, b) => a.name.localeCompare(b.name));
|
|
6765
|
+
return [...cycleTier, ...restTier];
|
|
6766
|
+
}
|
|
6767
|
+
function buildAddedComponentsList(components, stateByKey, cycleParticipants = /* @__PURE__ */ new Set()) {
|
|
6768
|
+
const cycleTier = [];
|
|
6769
|
+
const restTier = [];
|
|
6770
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6771
|
+
for (const c2 of components) {
|
|
6772
|
+
if (stateByKey.get(c2.name) !== "accepted") continue;
|
|
6773
|
+
if (seen.has(c2.name)) continue;
|
|
6774
|
+
seen.add(c2.name);
|
|
6775
|
+
if (cycleParticipants.has(c2.name)) cycleTier.push({ name: c2.name, isCycle: true });
|
|
6776
|
+
else restTier.push({ name: c2.name, isCycle: false });
|
|
6777
|
+
}
|
|
6778
|
+
return sortTieredEntries(cycleTier, restTier);
|
|
6779
|
+
}
|
|
6780
|
+
function computeCounters(components, closures, stateByKey) {
|
|
6781
|
+
let accepted = 0;
|
|
6782
|
+
let rejected = 0;
|
|
6783
|
+
let undecided = 0;
|
|
6784
|
+
for (const c2 of components) {
|
|
6785
|
+
const s = stateByKey.get(c2.name) ?? "undecided";
|
|
6786
|
+
if (s === "accepted") accepted++;
|
|
6787
|
+
else if (s === "rejected") rejected++;
|
|
6788
|
+
else undecided++;
|
|
6789
|
+
}
|
|
6790
|
+
let groups = 0;
|
|
6791
|
+
for (const [root, closure] of closures.entries()) {
|
|
6792
|
+
if (closure.nodes.length <= 1) continue;
|
|
6793
|
+
if (stateByKey.get(root) === "accepted") groups++;
|
|
6794
|
+
}
|
|
6795
|
+
return { accepted, rejected, undecided, groups, total: components.length };
|
|
6796
|
+
}
|
|
6797
|
+
function sideColumnLabelStyle(input) {
|
|
6798
|
+
const { isCycle, isSelected, focused } = input;
|
|
6799
|
+
const isCursor = isSelected && focused;
|
|
6800
|
+
if (isCursor) {
|
|
6801
|
+
return {
|
|
6802
|
+
nameColor: PALETTE2.info,
|
|
6803
|
+
nameBold: true,
|
|
6804
|
+
nameInverse: false,
|
|
6805
|
+
nameUnderline: false,
|
|
6806
|
+
suffixColor: PALETTE2.info,
|
|
6807
|
+
suffixDim: false,
|
|
6808
|
+
suffixInverse: false,
|
|
6809
|
+
suffixUnderline: false
|
|
6810
|
+
};
|
|
6746
6811
|
}
|
|
6747
|
-
|
|
6748
|
-
|
|
6812
|
+
const underline = isSelected && !focused;
|
|
6813
|
+
if (isCycle) {
|
|
6814
|
+
return {
|
|
6815
|
+
nameColor: PALETTE2.warning,
|
|
6816
|
+
nameBold: false,
|
|
6817
|
+
nameInverse: false,
|
|
6818
|
+
nameUnderline: underline,
|
|
6819
|
+
suffixColor: PALETTE2.warning,
|
|
6820
|
+
suffixDim: false,
|
|
6821
|
+
suffixInverse: false,
|
|
6822
|
+
suffixUnderline: underline
|
|
6823
|
+
};
|
|
6749
6824
|
}
|
|
6750
|
-
|
|
6751
|
-
|
|
6825
|
+
return {
|
|
6826
|
+
nameColor: PALETTE2.success,
|
|
6827
|
+
nameBold: false,
|
|
6828
|
+
nameInverse: false,
|
|
6829
|
+
nameUnderline: underline,
|
|
6830
|
+
suffixColor: PALETTE2.info,
|
|
6831
|
+
suffixDim: true,
|
|
6832
|
+
suffixInverse: false,
|
|
6833
|
+
suffixUnderline: underline
|
|
6834
|
+
};
|
|
6752
6835
|
}
|
|
6753
|
-
function
|
|
6754
|
-
|
|
6836
|
+
function computeColumnWindow(total, cursor, visibleCount) {
|
|
6837
|
+
if (total <= visibleCount) return { start: 0, end: total, above: 0, below: 0 };
|
|
6838
|
+
let start = Math.max(0, cursor - Math.floor(visibleCount / 2));
|
|
6839
|
+
start = Math.min(start, total - visibleCount);
|
|
6840
|
+
const end = start + visibleCount;
|
|
6841
|
+
return { start, end, above: start, below: total - end };
|
|
6842
|
+
}
|
|
6843
|
+
|
|
6844
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/windowed-panel.tsx
|
|
6845
|
+
import { Box as Box10, Text as Text11 } from "ink";
|
|
6846
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
6847
|
+
var MIN_TERMINAL_PANEL_HEIGHT = 5;
|
|
6848
|
+
function terminalPanelHeight(rows, reservedRows = 4) {
|
|
6849
|
+
return Math.max(MIN_TERMINAL_PANEL_HEIGHT, rows - reservedRows);
|
|
6850
|
+
}
|
|
6851
|
+
function FixedPanel({
|
|
6852
|
+
width,
|
|
6853
|
+
height,
|
|
6854
|
+
minHeight,
|
|
6855
|
+
focused = false,
|
|
6856
|
+
borderStyle,
|
|
6857
|
+
borderColor,
|
|
6858
|
+
paddingLeft,
|
|
6859
|
+
clipOverflow = true,
|
|
6860
|
+
children
|
|
6861
|
+
}) {
|
|
6862
|
+
return /* @__PURE__ */ jsx13(
|
|
6863
|
+
Box10,
|
|
6864
|
+
{
|
|
6865
|
+
flexDirection: "column",
|
|
6866
|
+
width,
|
|
6867
|
+
...height === void 0 ? {} : { height },
|
|
6868
|
+
...minHeight === void 0 ? {} : { minHeight },
|
|
6869
|
+
...height === void 0 || !clipOverflow ? {} : { overflowY: "hidden" },
|
|
6870
|
+
flexShrink: 0,
|
|
6871
|
+
borderStyle,
|
|
6872
|
+
borderColor: focused ? borderColor ?? "white" : borderColor,
|
|
6873
|
+
paddingLeft,
|
|
6874
|
+
children
|
|
6875
|
+
}
|
|
6876
|
+
);
|
|
6755
6877
|
}
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
}
|
|
6770
|
-
|
|
6878
|
+
function WindowedPanel({ width, height, title, focused, children }) {
|
|
6879
|
+
return /* @__PURE__ */ jsxs10(
|
|
6880
|
+
FixedPanel,
|
|
6881
|
+
{
|
|
6882
|
+
width,
|
|
6883
|
+
borderStyle: "single",
|
|
6884
|
+
borderColor: focused ? "white" : void 0,
|
|
6885
|
+
...height === void 0 ? {} : { height },
|
|
6886
|
+
focused,
|
|
6887
|
+
children: [
|
|
6888
|
+
title && /* @__PURE__ */ jsx13(WindowedPanelHeader, { title, width, focused }),
|
|
6889
|
+
children
|
|
6890
|
+
]
|
|
6891
|
+
}
|
|
6892
|
+
);
|
|
6893
|
+
}
|
|
6894
|
+
function WindowedPanelHeader({
|
|
6895
|
+
title,
|
|
6896
|
+
width,
|
|
6897
|
+
focused
|
|
6898
|
+
}) {
|
|
6899
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
6900
|
+
/* @__PURE__ */ jsx13(Text11, { bold: true, color: PALETTE2.info, inverse: focused, children: title }),
|
|
6901
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "\u2500".repeat(Math.max(0, width - 2)) })
|
|
6902
|
+
] });
|
|
6903
|
+
}
|
|
6904
|
+
function formatWindowIndicator(direction, count) {
|
|
6905
|
+
if (count <= 0) return " ";
|
|
6906
|
+
return `${direction === "up" ? "\u2191" : "\u2193"} ${count} more`;
|
|
6907
|
+
}
|
|
6908
|
+
function WindowIndicator({ direction, count }) {
|
|
6909
|
+
return /* @__PURE__ */ jsx13(Text11, { color: PALETTE2.muted, children: formatWindowIndicator(direction, count) });
|
|
6771
6910
|
}
|
|
6772
6911
|
|
|
6773
|
-
// packages/experience-design-system-cli/src/tui/import/
|
|
6774
|
-
|
|
6775
|
-
|
|
6912
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/added-column.tsx
|
|
6913
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
6914
|
+
function AddedColumn(props) {
|
|
6915
|
+
const { title, width, height, entries, cursor, focused, aiFlaggedByKey, visibleCount } = props;
|
|
6916
|
+
const reserveAiBadge = entries.some((e) => aiFlaggedByKey?.get(e.name) === true);
|
|
6917
|
+
const firstNonCycleIdx = entries.findIndex((e) => !e.isCycle);
|
|
6918
|
+
const window = computeColumnWindow(entries.length, cursor, Math.max(1, visibleCount));
|
|
6919
|
+
return /* @__PURE__ */ jsxs11(WindowedPanel, { width, height, title, focused, children: [
|
|
6920
|
+
/* @__PURE__ */ jsx14(WindowIndicator, { direction: "up", count: window.above }),
|
|
6921
|
+
entries.length === 0 ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.muted, children: "(none)" }) : entries.slice(window.start, window.end).map((entry, vi) => {
|
|
6922
|
+
const i = window.start + vi;
|
|
6923
|
+
const isSelected = i === cursor;
|
|
6924
|
+
const isCursor = focused && isSelected;
|
|
6925
|
+
const aiFlagged = aiFlaggedByKey?.get(entry.name) === true;
|
|
6926
|
+
const showSeparator = firstNonCycleIdx > 0 && i === firstNonCycleIdx;
|
|
6927
|
+
const style = sideColumnLabelStyle({ isCycle: entry.isCycle, isSelected, focused });
|
|
6928
|
+
return /* @__PURE__ */ jsxs11(React6.Fragment, { children: [
|
|
6929
|
+
showSeparator && /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "\u2500".repeat(Math.max(0, width - 2)) }),
|
|
6930
|
+
/* @__PURE__ */ jsxs11(Box11, { children: [
|
|
6931
|
+
isCursor ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.info, bold: true, children: figures.pointer }) : /* @__PURE__ */ jsx14(Text12, { children: " " }),
|
|
6932
|
+
reserveAiBadge && (aiFlagged ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.warning, bold: true, children: " [\xD7]" }) : /* @__PURE__ */ jsx14(Text12, { children: " " })),
|
|
6933
|
+
entry.isCycle && /* @__PURE__ */ jsx14(Text12, { color: isCursor ? PALETTE2.info : PALETTE2.warning, bold: true, underline: style.nameUnderline, children: " \u26A0" }),
|
|
6934
|
+
/* @__PURE__ */ jsx14(
|
|
6935
|
+
Text12,
|
|
6936
|
+
{
|
|
6937
|
+
color: style.nameColor,
|
|
6938
|
+
bold: style.nameBold,
|
|
6939
|
+
inverse: style.nameInverse,
|
|
6940
|
+
underline: style.nameUnderline,
|
|
6941
|
+
wrap: "wrap",
|
|
6942
|
+
children: " " + entry.name
|
|
6943
|
+
}
|
|
6944
|
+
)
|
|
6945
|
+
] })
|
|
6946
|
+
] }, entry.name);
|
|
6947
|
+
}),
|
|
6948
|
+
/* @__PURE__ */ jsx14(WindowIndicator, { direction: "down", count: window.below })
|
|
6949
|
+
] });
|
|
6776
6950
|
}
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6951
|
+
|
|
6952
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/cycles-panel.tsx
|
|
6953
|
+
import { Box as Box12, Text as Text13 } from "ink";
|
|
6954
|
+
import figures2 from "figures";
|
|
6955
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6956
|
+
function cycleLabel(cycle, index) {
|
|
6957
|
+
const parts = [];
|
|
6958
|
+
for (let i = 0; i < cycle.edges.length; i++) {
|
|
6959
|
+
parts.push(cycle.path[i]);
|
|
6960
|
+
parts.push(`[${cycle.edges[i].slotName}]`);
|
|
6961
|
+
}
|
|
6962
|
+
parts.push(cycle.path[cycle.path.length - 1]);
|
|
6963
|
+
return `Cycle ${index + 1}: ${parts.join(" \u2192 ")}`;
|
|
6783
6964
|
}
|
|
6784
|
-
function
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6965
|
+
function CyclesPanel({ cycles, cursor }) {
|
|
6966
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE2.warning, paddingX: 1, marginTop: 1, children: [
|
|
6967
|
+
/* @__PURE__ */ jsx15(Text13, { bold: true, color: PALETTE2.warning, children: `Cycles detected (${cycles.length}):` }),
|
|
6968
|
+
/* @__PURE__ */ jsx15(Text13, { children: " " }),
|
|
6969
|
+
cycles.map((cycle, i) => {
|
|
6970
|
+
const isCursor = i === cursor;
|
|
6971
|
+
return /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
6972
|
+
isCursor ? /* @__PURE__ */ jsx15(Text13, { color: PALETTE2.info, bold: true, children: figures2.pointer }) : /* @__PURE__ */ jsx15(Text13, { children: " " }),
|
|
6973
|
+
/* @__PURE__ */ jsx15(Text13, { color: PALETTE2.warning, inverse: isCursor, children: " " + cycleLabel(cycle, i) })
|
|
6974
|
+
] }, i);
|
|
6975
|
+
}),
|
|
6976
|
+
/* @__PURE__ */ jsx15(Text13, { children: "[\u2191/\u2193] move \xB7 [Enter] jump \xB7 [c/Esc] close" })
|
|
6977
|
+
] });
|
|
6789
6978
|
}
|
|
6790
6979
|
|
|
6791
|
-
// packages/experience-design-system-cli/src/tui/
|
|
6792
|
-
import {
|
|
6793
|
-
import {
|
|
6980
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/reject-prompt.tsx
|
|
6981
|
+
import { Box as Box13, Text as Text14 } from "ink";
|
|
6982
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6983
|
+
function RejectPrompt({ pending }) {
|
|
6984
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE2.warning, paddingX: 1, marginTop: 1, children: [
|
|
6985
|
+
/* @__PURE__ */ jsx16(Text14, { bold: true, color: PALETTE2.warning, children: `Rejecting ${pending.target} will:` }),
|
|
6986
|
+
pending.ancestors.length > 0 && /* @__PURE__ */ jsx16(Text14, { children: `- Reject ancestors: ${pending.ancestors.join(", ")}` }),
|
|
6987
|
+
pending.descendants.length > 0 && /* @__PURE__ */ jsx16(Text14, { children: `- Deselect descendants: ${pending.descendants.join(", ")}` }),
|
|
6988
|
+
/* @__PURE__ */ jsx16(Text14, { children: "[y] confirm \xB7 [n]/[Esc] cancel" })
|
|
6989
|
+
] });
|
|
6990
|
+
}
|
|
6794
6991
|
|
|
6795
|
-
// packages/experience-design-system-cli/src/tui/
|
|
6796
|
-
import {
|
|
6797
|
-
import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
|
|
6798
|
-
import { join as join12 } from "node:path";
|
|
6992
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.tsx
|
|
6993
|
+
import { Box as Box14 } from "ink";
|
|
6799
6994
|
|
|
6800
|
-
// packages/experience-design-system-cli/src/tui/
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6995
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/LegendEntry.tsx
|
|
6996
|
+
import { Text as Text15 } from "ink";
|
|
6997
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6998
|
+
function legendEntry(keyBracket, label, active = false) {
|
|
6999
|
+
return /* @__PURE__ */ jsxs14(Text15, { children: [
|
|
7000
|
+
/* @__PURE__ */ jsx17(Text15, { color: active ? PALETTE2.warning : PALETTE2.info, inverse: active, children: keyBracket }),
|
|
7001
|
+
/* @__PURE__ */ jsx17(Text15, { color: active ? PALETTE2.warning : void 0, inverse: active, children: " " + label })
|
|
7002
|
+
] }, keyBracket + label);
|
|
7003
|
+
}
|
|
7004
|
+
|
|
7005
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.tsx
|
|
7006
|
+
import { jsxs as jsxs15 } from "react/jsx-runtime";
|
|
7007
|
+
function CompactControlBar({ hasGroupRoots, searchActive }) {
|
|
7008
|
+
return /* @__PURE__ */ jsxs15(Box14, { borderStyle: "single", borderColor: PALETTE2.border, paddingX: 1, flexWrap: "wrap", columnGap: 2, children: [
|
|
7009
|
+
legendEntry("[\u2191/\u2193]", "move"),
|
|
7010
|
+
legendEntry("[a/r]", "accept/reject"),
|
|
7011
|
+
legendEntry("[f]", "continue/finalize"),
|
|
7012
|
+
hasGroupRoots && legendEntry("[space/E/C]", "expand/collapse"),
|
|
7013
|
+
legendEntry("[/]", "search", searchActive),
|
|
7014
|
+
legendEntry("[h]", "help"),
|
|
7015
|
+
legendEntry("[q]", "quit")
|
|
7016
|
+
] });
|
|
6807
7017
|
}
|
|
6808
|
-
|
|
6809
|
-
|
|
7018
|
+
|
|
7019
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CounterStrip.tsx
|
|
7020
|
+
import { Box as Box15, Text as Text16 } from "ink";
|
|
7021
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
7022
|
+
function CounterStrip(props) {
|
|
7023
|
+
const { counters, totalWidth } = props;
|
|
7024
|
+
const condensed = totalWidth < 60;
|
|
7025
|
+
const labelGrp = condensed ? "Cmp" : "Components with Slots";
|
|
7026
|
+
const labelRej = condensed ? "Rej" : "Rejected";
|
|
7027
|
+
const labelUnd = condensed ? "Und" : "Undecided";
|
|
7028
|
+
const sep = condensed ? " | " : " ";
|
|
7029
|
+
return /* @__PURE__ */ jsx18(Box15, { children: /* @__PURE__ */ jsxs16(Text16, { children: [
|
|
7030
|
+
/* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
|
|
7031
|
+
labelGrp,
|
|
7032
|
+
" "
|
|
7033
|
+
] }),
|
|
7034
|
+
/* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.groups }),
|
|
7035
|
+
/* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep }),
|
|
7036
|
+
/* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
|
|
7037
|
+
labelRej,
|
|
7038
|
+
" "
|
|
7039
|
+
] }),
|
|
7040
|
+
/* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.rejected }),
|
|
7041
|
+
/* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep }),
|
|
7042
|
+
/* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
|
|
7043
|
+
labelUnd,
|
|
7044
|
+
" "
|
|
7045
|
+
] }),
|
|
7046
|
+
/* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.undecided }),
|
|
7047
|
+
/* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep })
|
|
7048
|
+
] }) });
|
|
7049
|
+
}
|
|
7050
|
+
|
|
7051
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GotoBanner.tsx
|
|
7052
|
+
import figures3 from "figures";
|
|
7053
|
+
import { Box as Box16, Text as Text17 } from "ink";
|
|
7054
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7055
|
+
var DEFAULT_MAX_ROWS = 15;
|
|
7056
|
+
function windowStart(rowCount, highlightIndex, maxRows) {
|
|
7057
|
+
if (rowCount <= maxRows) return 0;
|
|
7058
|
+
const maxStart = rowCount - maxRows;
|
|
7059
|
+
let start = highlightIndex - Math.floor(maxRows / 2);
|
|
7060
|
+
if (start < 0) start = 0;
|
|
7061
|
+
if (start > maxStart) start = maxStart;
|
|
7062
|
+
return start;
|
|
7063
|
+
}
|
|
7064
|
+
function defaultRenderRow(row, index, isCursor) {
|
|
7065
|
+
return /* @__PURE__ */ jsxs17(Text17, { children: [
|
|
7066
|
+
isCursor ? /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.info, bold: true, children: figures3.pointer }) : /* @__PURE__ */ jsx19(Text17, { children: " " }),
|
|
7067
|
+
/* @__PURE__ */ jsx19(Text17, { inverse: isCursor, children: " " + row.label })
|
|
7068
|
+
] }, index);
|
|
7069
|
+
}
|
|
7070
|
+
function GotoBanner({
|
|
7071
|
+
title,
|
|
7072
|
+
rows,
|
|
7073
|
+
cursor,
|
|
7074
|
+
cursorRowIndex,
|
|
7075
|
+
maxRows = DEFAULT_MAX_ROWS,
|
|
7076
|
+
width,
|
|
7077
|
+
footerHint,
|
|
7078
|
+
renderRow = defaultRenderRow
|
|
7079
|
+
}) {
|
|
7080
|
+
const highlightIndex = cursorRowIndex ?? cursor;
|
|
7081
|
+
const start = windowStart(rows.length, highlightIndex, maxRows);
|
|
7082
|
+
const end = Math.min(rows.length, start + maxRows);
|
|
7083
|
+
const visible = rows.slice(start, end);
|
|
7084
|
+
const moreAbove = start;
|
|
7085
|
+
const moreBelow = rows.length - end;
|
|
7086
|
+
return /* @__PURE__ */ jsxs17(
|
|
7087
|
+
Box16,
|
|
7088
|
+
{
|
|
7089
|
+
flexDirection: "column",
|
|
7090
|
+
borderStyle: "single",
|
|
7091
|
+
borderColor: PALETTE2.info,
|
|
7092
|
+
paddingX: 1,
|
|
7093
|
+
marginTop: width === void 0 ? 1 : 0,
|
|
7094
|
+
width,
|
|
7095
|
+
flexShrink: 0,
|
|
7096
|
+
children: [
|
|
7097
|
+
/* @__PURE__ */ jsx19(Text17, { bold: true, children: title }),
|
|
7098
|
+
moreAbove > 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: ` \u25B2 ${moreAbove} more` }),
|
|
7099
|
+
visible.map((row, vi) => {
|
|
7100
|
+
const i = start + vi;
|
|
7101
|
+
return renderRow(row, i, i === highlightIndex);
|
|
7102
|
+
}),
|
|
7103
|
+
moreBelow > 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: ` \u25BC ${moreBelow} more` }),
|
|
7104
|
+
footerHint !== void 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: footerHint })
|
|
7105
|
+
]
|
|
7106
|
+
}
|
|
7107
|
+
);
|
|
6810
7108
|
}
|
|
6811
7109
|
|
|
6812
|
-
// packages/experience-design-system-cli/src/tui/
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
7110
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.tsx
|
|
7111
|
+
import figures4 from "figures";
|
|
7112
|
+
import { Box as Box17, Text as Text19 } from "ink";
|
|
7113
|
+
|
|
7114
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/cycle-detection.ts
|
|
7115
|
+
function buildGraph(components) {
|
|
7116
|
+
const nodes = [];
|
|
7117
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7118
|
+
for (const c2 of components) {
|
|
7119
|
+
if (seen.has(c2.name)) continue;
|
|
7120
|
+
seen.add(c2.name);
|
|
7121
|
+
nodes.push(c2.name);
|
|
7122
|
+
}
|
|
7123
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
7124
|
+
for (const node of nodes) adjacency.set(node, []);
|
|
7125
|
+
for (const comp of components) {
|
|
7126
|
+
const outgoing = adjacency.get(comp.name);
|
|
7127
|
+
if (!outgoing) continue;
|
|
7128
|
+
for (const slot of comp.slots) {
|
|
7129
|
+
const allowed = slot.allowedComponents ?? [];
|
|
7130
|
+
for (const target of allowed) {
|
|
7131
|
+
if (!seen.has(target)) continue;
|
|
7132
|
+
outgoing.push({ target, slotName: slot.name });
|
|
7133
|
+
}
|
|
7134
|
+
}
|
|
7135
|
+
}
|
|
7136
|
+
return { nodes, adjacency };
|
|
7137
|
+
}
|
|
7138
|
+
function stronglyConnectedComponents2(nodes, adjacency) {
|
|
7139
|
+
const index = /* @__PURE__ */ new Map();
|
|
7140
|
+
const lowlink = /* @__PURE__ */ new Map();
|
|
7141
|
+
const onStack = /* @__PURE__ */ new Set();
|
|
7142
|
+
const stack = [];
|
|
7143
|
+
const sccs = [];
|
|
7144
|
+
let counter = 0;
|
|
7145
|
+
const nodeSet = new Set(nodes);
|
|
7146
|
+
function strongconnect(v) {
|
|
7147
|
+
index.set(v, counter);
|
|
7148
|
+
lowlink.set(v, counter);
|
|
7149
|
+
counter += 1;
|
|
7150
|
+
stack.push(v);
|
|
7151
|
+
onStack.add(v);
|
|
7152
|
+
const neighbours = adjacency.get(v) ?? [];
|
|
7153
|
+
for (const { target } of neighbours) {
|
|
7154
|
+
if (!nodeSet.has(target)) continue;
|
|
7155
|
+
if (!index.has(target)) {
|
|
7156
|
+
strongconnect(target);
|
|
7157
|
+
lowlink.set(v, Math.min(lowlink.get(v), lowlink.get(target)));
|
|
7158
|
+
} else if (onStack.has(target)) {
|
|
7159
|
+
lowlink.set(v, Math.min(lowlink.get(v), index.get(target)));
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
7162
|
+
if (lowlink.get(v) === index.get(v)) {
|
|
7163
|
+
const scc = [];
|
|
7164
|
+
let w;
|
|
7165
|
+
do {
|
|
7166
|
+
w = stack.pop();
|
|
7167
|
+
onStack.delete(w);
|
|
7168
|
+
scc.push(w);
|
|
7169
|
+
} while (w !== v);
|
|
7170
|
+
sccs.push(scc);
|
|
7171
|
+
}
|
|
7172
|
+
}
|
|
7173
|
+
for (const node of nodes) {
|
|
7174
|
+
if (!index.has(node)) strongconnect(node);
|
|
7175
|
+
}
|
|
7176
|
+
return sccs;
|
|
7177
|
+
}
|
|
7178
|
+
function makeCycle(path5, edges) {
|
|
7179
|
+
return { path: [...path5, path5[0]], edges: [...edges] };
|
|
7180
|
+
}
|
|
7181
|
+
function findSlotCycles3(components) {
|
|
7182
|
+
if (components.length === 0) return [];
|
|
7183
|
+
const { nodes, adjacency } = buildGraph(components);
|
|
7184
|
+
if (nodes.length === 0) return [];
|
|
7185
|
+
const cycles = [];
|
|
7186
|
+
for (const node of nodes) {
|
|
7187
|
+
const outgoing = adjacency.get(node) ?? [];
|
|
7188
|
+
for (const edge of outgoing) {
|
|
7189
|
+
if (edge.target === node) {
|
|
7190
|
+
cycles.push({
|
|
7191
|
+
path: [node, node],
|
|
7192
|
+
edges: [{ fromComponent: node, slotName: edge.slotName, toComponent: node }]
|
|
7193
|
+
});
|
|
7194
|
+
}
|
|
7195
|
+
}
|
|
7196
|
+
}
|
|
7197
|
+
const nodeOrder = [...nodes].sort();
|
|
7198
|
+
let remaining = [...nodeOrder];
|
|
7199
|
+
while (remaining.length > 0) {
|
|
7200
|
+
let unblock2 = function(u) {
|
|
7201
|
+
blocked.delete(u);
|
|
7202
|
+
const dependents = blockedMap.get(u);
|
|
7203
|
+
if (!dependents) return;
|
|
7204
|
+
for (const w of dependents) {
|
|
7205
|
+
if (blocked.has(w)) unblock2(w);
|
|
7206
|
+
}
|
|
7207
|
+
dependents.clear();
|
|
7208
|
+
}, circuit2 = function(v, root) {
|
|
7209
|
+
let foundCycle = false;
|
|
7210
|
+
pathStack.push(v);
|
|
7211
|
+
blocked.add(v);
|
|
7212
|
+
const outgoing = adjacency.get(v) ?? [];
|
|
7213
|
+
for (const { target: w, slotName } of outgoing) {
|
|
7214
|
+
if (!sccSet.has(w)) continue;
|
|
7215
|
+
edgeStack.push({ fromComponent: v, slotName, toComponent: w });
|
|
7216
|
+
if (w === root) {
|
|
7217
|
+
cycles.push(makeCycle(pathStack, edgeStack));
|
|
7218
|
+
foundCycle = true;
|
|
7219
|
+
} else if (!blocked.has(w)) {
|
|
7220
|
+
if (circuit2(w, root)) foundCycle = true;
|
|
7221
|
+
}
|
|
7222
|
+
edgeStack.pop();
|
|
7223
|
+
}
|
|
7224
|
+
if (foundCycle) {
|
|
7225
|
+
unblock2(v);
|
|
7226
|
+
} else {
|
|
7227
|
+
for (const { target: w } of outgoing) {
|
|
7228
|
+
if (!sccSet.has(w)) continue;
|
|
7229
|
+
let deps = blockedMap.get(w);
|
|
7230
|
+
if (!deps) {
|
|
7231
|
+
deps = /* @__PURE__ */ new Set();
|
|
7232
|
+
blockedMap.set(w, deps);
|
|
7233
|
+
}
|
|
7234
|
+
deps.add(v);
|
|
7235
|
+
}
|
|
7236
|
+
}
|
|
7237
|
+
pathStack.pop();
|
|
7238
|
+
return foundCycle;
|
|
7239
|
+
};
|
|
7240
|
+
var unblock = unblock2, circuit = circuit2;
|
|
7241
|
+
const subgraphNodes = remaining;
|
|
7242
|
+
const sccs = stronglyConnectedComponents2(subgraphNodes, adjacency).filter((scc) => {
|
|
7243
|
+
if (scc.length > 1) return true;
|
|
7244
|
+
return false;
|
|
7245
|
+
});
|
|
7246
|
+
if (sccs.length === 0) break;
|
|
7247
|
+
let startNode = null;
|
|
7248
|
+
let startScc = null;
|
|
7249
|
+
for (const scc of sccs) {
|
|
7250
|
+
const min = [...scc].sort()[0];
|
|
7251
|
+
if (startNode === null || min < startNode) {
|
|
7252
|
+
startNode = min;
|
|
7253
|
+
startScc = scc;
|
|
7254
|
+
}
|
|
7255
|
+
}
|
|
7256
|
+
if (startNode === null || startScc === null) break;
|
|
7257
|
+
const sccSet = new Set(startScc);
|
|
7258
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
7259
|
+
const blockedMap = /* @__PURE__ */ new Map();
|
|
7260
|
+
const pathStack = [];
|
|
7261
|
+
const edgeStack = [];
|
|
7262
|
+
circuit2(startNode, startNode);
|
|
7263
|
+
remaining = remaining.filter((n) => n !== startNode);
|
|
7264
|
+
}
|
|
7265
|
+
return cycles;
|
|
6818
7266
|
}
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
7267
|
+
|
|
7268
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/composite-closure.ts
|
|
7269
|
+
function edgesFrom(component, known) {
|
|
7270
|
+
if (!component) return [];
|
|
7271
|
+
const out = [];
|
|
7272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7273
|
+
for (const slot of component.slots) {
|
|
7274
|
+
for (const target of slot.allowedComponents ?? []) {
|
|
7275
|
+
if (!known.has(target)) continue;
|
|
7276
|
+
if (seen.has(target)) continue;
|
|
7277
|
+
seen.add(target);
|
|
7278
|
+
out.push(target);
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
return out.sort();
|
|
7282
|
+
}
|
|
7283
|
+
function collectDependents(components) {
|
|
7284
|
+
const known = new Set(components.map((c2) => c2.name));
|
|
7285
|
+
const dependents = /* @__PURE__ */ new Set();
|
|
7286
|
+
for (const c2 of components) {
|
|
7287
|
+
for (const slot of c2.slots) {
|
|
7288
|
+
for (const target of slot.allowedComponents ?? []) {
|
|
7289
|
+
if (known.has(target) && target !== c2.name) dependents.add(target);
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
}
|
|
7293
|
+
return dependents;
|
|
6822
7294
|
}
|
|
6823
|
-
function
|
|
6824
|
-
|
|
7295
|
+
function findRoots(components, selected) {
|
|
7296
|
+
const scope = selected ? components.filter((c2) => selected.has(c2.name)) : components;
|
|
7297
|
+
const dependents = collectDependents(scope);
|
|
7298
|
+
return scope.map((c2) => c2.name).filter((name) => !dependents.has(name)).sort();
|
|
6825
7299
|
}
|
|
6826
|
-
function
|
|
6827
|
-
const
|
|
6828
|
-
const
|
|
6829
|
-
|
|
6830
|
-
const
|
|
6831
|
-
const
|
|
6832
|
-
|
|
6833
|
-
return match ? Math.max(max, Number(match[1])) : max;
|
|
6834
|
-
}, 0);
|
|
6835
|
-
return `${today}-session-${maxSeq + 1}`;
|
|
7300
|
+
function findCycleInClosure(root, reachable, components) {
|
|
7301
|
+
const scopedComponents = components.filter((c2) => reachable.has(c2.name)).map((c2) => ({ name: c2.name, slots: c2.slots }));
|
|
7302
|
+
const cycles = findSlotCycles3(scopedComponents);
|
|
7303
|
+
if (cycles.length === 0) return null;
|
|
7304
|
+
const involvesRoot = cycles.find((cycle) => cycle.path.includes(root));
|
|
7305
|
+
const picked = involvesRoot ?? cycles[0];
|
|
7306
|
+
return picked.path;
|
|
6836
7307
|
}
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
7308
|
+
function walkReachable2(root, byName, known) {
|
|
7309
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
7310
|
+
const stack = [root];
|
|
7311
|
+
while (stack.length > 0) {
|
|
7312
|
+
const cur = stack.pop();
|
|
7313
|
+
if (reachable.has(cur)) continue;
|
|
7314
|
+
reachable.add(cur);
|
|
7315
|
+
for (const next of edgesFrom(byName.get(cur), known)) {
|
|
7316
|
+
if (!reachable.has(next)) stack.push(next);
|
|
7317
|
+
}
|
|
7318
|
+
}
|
|
7319
|
+
return reachable;
|
|
6840
7320
|
}
|
|
6841
|
-
function
|
|
6842
|
-
|
|
7321
|
+
function computeClosure(root, components) {
|
|
7322
|
+
const known = new Set(components.map((c2) => c2.name));
|
|
7323
|
+
const byName = new Map(components.map((c2) => [c2.name, c2]));
|
|
7324
|
+
if (!known.has(root)) {
|
|
7325
|
+
return {
|
|
7326
|
+
root,
|
|
7327
|
+
nodes: [{ name: root, depth: 0, path: [root], parents: [] }],
|
|
7328
|
+
containsCycle: false
|
|
7329
|
+
};
|
|
7330
|
+
}
|
|
7331
|
+
const reachable = walkReachable2(root, byName, known);
|
|
7332
|
+
const cyclePath = findCycleInClosure(root, reachable, components);
|
|
7333
|
+
if (cyclePath) {
|
|
7334
|
+
const nodes2 = [...reachable].sort().map((name) => ({
|
|
7335
|
+
name,
|
|
7336
|
+
depth: name === root ? 0 : 1,
|
|
7337
|
+
path: [root],
|
|
7338
|
+
parents: []
|
|
7339
|
+
}));
|
|
7340
|
+
return { root, nodes: nodes2, containsCycle: true, cyclePath };
|
|
7341
|
+
}
|
|
7342
|
+
const depth = /* @__PURE__ */ new Map();
|
|
7343
|
+
const parentPath = /* @__PURE__ */ new Map();
|
|
7344
|
+
const parents = /* @__PURE__ */ new Map();
|
|
7345
|
+
depth.set(root, 0);
|
|
7346
|
+
parentPath.set(root, [root]);
|
|
7347
|
+
parents.set(root, /* @__PURE__ */ new Set());
|
|
7348
|
+
const queue = [root];
|
|
7349
|
+
while (queue.length > 0) {
|
|
7350
|
+
const cur = queue.shift();
|
|
7351
|
+
const curDepth = depth.get(cur);
|
|
7352
|
+
const curPath = parentPath.get(cur);
|
|
7353
|
+
for (const next of edgesFrom(byName.get(cur), known)) {
|
|
7354
|
+
if (!parents.has(next)) parents.set(next, /* @__PURE__ */ new Set());
|
|
7355
|
+
parents.get(next).add(cur);
|
|
7356
|
+
const nextDepth = curDepth + 1;
|
|
7357
|
+
const existingDepth = depth.get(next);
|
|
7358
|
+
const nextPath = [...curPath, next];
|
|
7359
|
+
if (existingDepth === void 0 || nextDepth < existingDepth) {
|
|
7360
|
+
depth.set(next, nextDepth);
|
|
7361
|
+
parentPath.set(next, nextPath);
|
|
7362
|
+
queue.push(next);
|
|
7363
|
+
} else if (nextDepth === existingDepth) {
|
|
7364
|
+
const existingPath = parentPath.get(next);
|
|
7365
|
+
if (nextPath.join("\0") < existingPath.join("\0")) {
|
|
7366
|
+
parentPath.set(next, nextPath);
|
|
7367
|
+
}
|
|
7368
|
+
}
|
|
7369
|
+
}
|
|
7370
|
+
}
|
|
7371
|
+
const nodes = [];
|
|
7372
|
+
for (const [name, d] of depth.entries()) {
|
|
7373
|
+
nodes.push({
|
|
7374
|
+
name,
|
|
7375
|
+
depth: d,
|
|
7376
|
+
path: parentPath.get(name),
|
|
7377
|
+
parents: [...parents.get(name) ?? /* @__PURE__ */ new Set()].sort()
|
|
7378
|
+
});
|
|
7379
|
+
}
|
|
7380
|
+
nodes.sort((a, b) => a.depth - b.depth || a.name.localeCompare(b.name));
|
|
7381
|
+
return { root, nodes, containsCycle: false };
|
|
6843
7382
|
}
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
7383
|
+
function computeAllClosures(components, selected) {
|
|
7384
|
+
const roots = findRoots(components, selected);
|
|
7385
|
+
const scope = selected ? components.filter((c2) => selected.has(c2.name)) : components;
|
|
7386
|
+
const out = /* @__PURE__ */ new Map();
|
|
7387
|
+
for (const root of roots) out.set(root, computeClosure(root, scope));
|
|
7388
|
+
return out;
|
|
7389
|
+
}
|
|
7390
|
+
function findSharedDeps(closures) {
|
|
7391
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7392
|
+
for (const [root, closure] of closures.entries()) {
|
|
7393
|
+
for (const node of closure.nodes) {
|
|
7394
|
+
if (node.name === root) continue;
|
|
7395
|
+
if (!counts.has(node.name)) counts.set(node.name, []);
|
|
7396
|
+
counts.get(node.name).push(root);
|
|
7397
|
+
}
|
|
6853
7398
|
}
|
|
7399
|
+
const out = /* @__PURE__ */ new Map();
|
|
7400
|
+
for (const [name, roots] of counts.entries()) {
|
|
7401
|
+
if (roots.length >= 2) out.set(name, [...roots].sort());
|
|
7402
|
+
}
|
|
7403
|
+
return out;
|
|
6854
7404
|
}
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
7405
|
+
|
|
7406
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/badge.tsx
|
|
7407
|
+
import { Text as Text18 } from "ink";
|
|
7408
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
7409
|
+
function previewBadge(annotation) {
|
|
7410
|
+
switch (annotation) {
|
|
7411
|
+
case "new":
|
|
7412
|
+
return { char: "+", color: PALETTE2.success };
|
|
7413
|
+
case "changed":
|
|
7414
|
+
return { char: "~", color: PALETTE2.warning };
|
|
7415
|
+
case "removed":
|
|
7416
|
+
return { char: "-", color: PALETTE2.error, dim: true };
|
|
7417
|
+
case "breaking":
|
|
7418
|
+
return { char: "!", color: PALETTE2.error, bold: true };
|
|
7419
|
+
default:
|
|
7420
|
+
return null;
|
|
6860
7421
|
}
|
|
6861
|
-
return clone;
|
|
6862
7422
|
}
|
|
6863
|
-
function
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
menuOption,
|
|
6867
|
-
inputs
|
|
7423
|
+
function PreviewBadge({
|
|
7424
|
+
badge,
|
|
7425
|
+
highlighted = false
|
|
6868
7426
|
}) {
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
7427
|
+
return badge ? /* @__PURE__ */ jsx20(Text18, { color: !highlighted && badge.dim ? PALETTE2.muted : badge.color, bold: badge.bold, children: badge.char }) : /* @__PURE__ */ jsx20(Text18, { children: " " });
|
|
7428
|
+
}
|
|
7429
|
+
|
|
7430
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.tsx
|
|
7431
|
+
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
7432
|
+
var GLYPH_EXPAND_COLLAPSED = "\u25B8";
|
|
7433
|
+
var GLYPH_EXPAND_EXPANDED = "\u25BE";
|
|
7434
|
+
var GLYPH_TREE_MID = "\u251C\u2500";
|
|
7435
|
+
var GLYPH_TREE_LAST = "\u2514\u2500";
|
|
7436
|
+
var GLYPH_WARN = "\u26A0";
|
|
7437
|
+
var GLYPH_ERROR = "\u2717";
|
|
7438
|
+
function isEmpty(entry) {
|
|
7439
|
+
return Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
|
|
7440
|
+
}
|
|
7441
|
+
function allowedComponentNames(entry) {
|
|
7442
|
+
const names = [];
|
|
7443
|
+
for (const slot of Object.values(entry.$slots ?? {})) {
|
|
7444
|
+
if (!Array.isArray(slot?.$allowedComponents)) continue;
|
|
7445
|
+
names.push(...slot.$allowedComponents.filter((value) => typeof value === "string"));
|
|
7446
|
+
}
|
|
7447
|
+
return names;
|
|
7448
|
+
}
|
|
7449
|
+
function aggregateGlyphFor(closure, statusByName) {
|
|
7450
|
+
let worst = "ok";
|
|
7451
|
+
for (const node of closure.nodes) {
|
|
7452
|
+
const s = statusByName.get(node.name);
|
|
7453
|
+
if (!s) continue;
|
|
7454
|
+
if (s === "error") {
|
|
7455
|
+
worst = "error";
|
|
7456
|
+
break;
|
|
7457
|
+
}
|
|
7458
|
+
if (s === "warning") worst = "warning";
|
|
7459
|
+
}
|
|
7460
|
+
if (worst === "error") return GLYPH_ERROR;
|
|
7461
|
+
if (worst === "warning") return GLYPH_WARN;
|
|
7462
|
+
return null;
|
|
6876
7463
|
}
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
7464
|
+
function buildVisibleRows(props) {
|
|
7465
|
+
const { items, cycleParticipants, alwaysExpanded, showFlatTier, viewMode, graph, filterVisibleKeys } = props;
|
|
7466
|
+
if (viewMode === "flat") {
|
|
7467
|
+
const rows2 = [];
|
|
7468
|
+
if (items.length === 0) return rows2;
|
|
7469
|
+
const itemByKey2 = new Map(items.map((it, idx) => [it.key, { it, idx }]));
|
|
7470
|
+
const cycleKeys2 = [];
|
|
7471
|
+
const otherKeys2 = [];
|
|
7472
|
+
for (const it of items) {
|
|
7473
|
+
if (cycleParticipants.has(it.key)) cycleKeys2.push(it.key);
|
|
7474
|
+
else otherKeys2.push(it.key);
|
|
7475
|
+
}
|
|
7476
|
+
cycleKeys2.sort();
|
|
7477
|
+
otherKeys2.sort();
|
|
7478
|
+
const otherKeySet2 = new Set(otherKeys2);
|
|
7479
|
+
const flatGraph = graph.filter((n) => otherKeySet2.has(n.name));
|
|
7480
|
+
const closures2 = computeAllClosures(flatGraph);
|
|
7481
|
+
const depCountByKey = /* @__PURE__ */ new Map();
|
|
7482
|
+
for (const [name, closure] of closures2) {
|
|
7483
|
+
if (closure.nodes.length > 1) depCountByKey.set(name, closure.nodes.length - 1);
|
|
7484
|
+
}
|
|
7485
|
+
for (const key of cycleKeys2) {
|
|
7486
|
+
const rec = itemByKey2.get(key);
|
|
7487
|
+
if (!rec) continue;
|
|
7488
|
+
rows2.push({
|
|
7489
|
+
kind: "cycle",
|
|
7490
|
+
key: `cycle:${key}`,
|
|
7491
|
+
label: `${GLYPH_WARN} ${key} (cycle)`,
|
|
7492
|
+
indent: 0,
|
|
7493
|
+
itemIdx: rec.idx
|
|
7494
|
+
});
|
|
7495
|
+
}
|
|
7496
|
+
for (const key of otherKeys2) {
|
|
7497
|
+
const rec = itemByKey2.get(key);
|
|
7498
|
+
if (!rec) continue;
|
|
7499
|
+
const dep = depCountByKey.get(key);
|
|
7500
|
+
const suffix = dep !== void 0 ? ` (${dep} dep${dep === 1 ? "" : "s"})` : "";
|
|
7501
|
+
rows2.push({
|
|
7502
|
+
kind: "flat",
|
|
7503
|
+
key: `flat:${key}`,
|
|
7504
|
+
label: `${key}${suffix}`,
|
|
7505
|
+
indent: 0,
|
|
7506
|
+
itemIdx: rec.idx
|
|
7507
|
+
});
|
|
7508
|
+
}
|
|
7509
|
+
return rows2;
|
|
7510
|
+
}
|
|
7511
|
+
const rows = [];
|
|
7512
|
+
if (items.length === 0) return rows;
|
|
7513
|
+
const itemByKey = new Map(items.map((it, idx) => [it.key, { it, idx }]));
|
|
7514
|
+
const statusByName = new Map(items.map((it) => [it.key, it.status]));
|
|
7515
|
+
const cycleKeys = [];
|
|
7516
|
+
const emptyKeys = [];
|
|
7517
|
+
const otherKeys = [];
|
|
7518
|
+
for (const it of items) {
|
|
7519
|
+
if (cycleParticipants.has(it.key)) cycleKeys.push(it.key);
|
|
7520
|
+
else if (isEmpty(it.entry)) emptyKeys.push(it.key);
|
|
7521
|
+
else otherKeys.push(it.key);
|
|
7522
|
+
}
|
|
7523
|
+
cycleKeys.sort();
|
|
7524
|
+
emptyKeys.sort();
|
|
7525
|
+
const seenCycleTierChildOccurrence = /* @__PURE__ */ new Set();
|
|
7526
|
+
const computeCycleMemberSubtree = (root) => {
|
|
7527
|
+
const out = [];
|
|
7528
|
+
const visited = /* @__PURE__ */ new Set([root]);
|
|
7529
|
+
const queue = [{ name: root, depth: 0 }];
|
|
7530
|
+
while (queue.length > 0) {
|
|
7531
|
+
const cur = queue.shift();
|
|
7532
|
+
const parentItem = itemByKey.get(cur.name)?.it;
|
|
7533
|
+
if (!parentItem) continue;
|
|
7534
|
+
const slotTargets2 = [];
|
|
7535
|
+
const seenTarget = /* @__PURE__ */ new Set();
|
|
7536
|
+
for (const target of allowedComponentNames(parentItem.entry)) {
|
|
7537
|
+
if (!itemByKey.has(target)) continue;
|
|
7538
|
+
if (seenTarget.has(target)) continue;
|
|
7539
|
+
seenTarget.add(target);
|
|
7540
|
+
slotTargets2.push(target);
|
|
7541
|
+
}
|
|
7542
|
+
slotTargets2.sort();
|
|
7543
|
+
for (const target of slotTargets2) {
|
|
7544
|
+
if (visited.has(target)) continue;
|
|
7545
|
+
visited.add(target);
|
|
7546
|
+
const isCycleMember = cycleParticipants.has(target);
|
|
7547
|
+
out.push({ name: target, depth: cur.depth + 1, isCycleMember });
|
|
7548
|
+
queue.push({ name: target, depth: cur.depth + 1 });
|
|
7549
|
+
}
|
|
7550
|
+
}
|
|
7551
|
+
return out;
|
|
7552
|
+
};
|
|
7553
|
+
for (const key of cycleKeys) {
|
|
7554
|
+
const rec = itemByKey.get(key);
|
|
7555
|
+
if (!rec) continue;
|
|
7556
|
+
const expanded = alwaysExpanded ? true : props.expandedGroups.has(key);
|
|
7557
|
+
const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
|
|
7558
|
+
rows.push({
|
|
7559
|
+
kind: "cycle",
|
|
7560
|
+
key: `cycle:${key}`,
|
|
7561
|
+
label: `${glyphExpand} ${GLYPH_WARN} ${key} (cycle)`,
|
|
7562
|
+
indent: 0,
|
|
7563
|
+
itemIdx: rec.idx,
|
|
7564
|
+
rootName: key
|
|
7565
|
+
});
|
|
7566
|
+
if (!expanded) continue;
|
|
7567
|
+
const subtree = computeCycleMemberSubtree(key);
|
|
7568
|
+
const isLastAtDepthSubtree = (idx) => {
|
|
7569
|
+
const own = subtree[idx].depth;
|
|
7570
|
+
for (let j = idx + 1; j < subtree.length; j++) {
|
|
7571
|
+
const d = subtree[j].depth;
|
|
7572
|
+
if (d < own) return true;
|
|
7573
|
+
if (d === own) return false;
|
|
7574
|
+
}
|
|
7575
|
+
return true;
|
|
7576
|
+
};
|
|
7577
|
+
subtree.forEach((child, i) => {
|
|
7578
|
+
const isLast = isLastAtDepthSubtree(i);
|
|
7579
|
+
const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
|
|
7580
|
+
let sharedSuffix = false;
|
|
7581
|
+
if (seenCycleTierChildOccurrence.has(child.name)) sharedSuffix = true;
|
|
7582
|
+
else seenCycleTierChildOccurrence.add(child.name);
|
|
7583
|
+
const childRec = itemByKey.get(child.name);
|
|
7584
|
+
const indent = " ".repeat(Math.max(0, child.depth - 1));
|
|
7585
|
+
const labelName = child.isCycleMember ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
|
|
7586
|
+
rows.push({
|
|
7587
|
+
kind: "group-child",
|
|
7588
|
+
key: `cycle-child:${key}:${child.name}`,
|
|
7589
|
+
label: `${indent}${glyph} ${labelName}${sharedSuffix ? " (shared)" : ""}`,
|
|
7590
|
+
indent: child.depth,
|
|
7591
|
+
sharedSuffix,
|
|
7592
|
+
cycleChild: child.isCycleMember || void 0,
|
|
7593
|
+
itemIdx: childRec?.idx ?? -1,
|
|
7594
|
+
rootName: key
|
|
7595
|
+
});
|
|
7596
|
+
});
|
|
7597
|
+
}
|
|
7598
|
+
for (const key of emptyKeys) {
|
|
7599
|
+
const rec = itemByKey.get(key);
|
|
7600
|
+
if (!rec) continue;
|
|
7601
|
+
rows.push({
|
|
7602
|
+
kind: "empty",
|
|
7603
|
+
key: `empty:${key}`,
|
|
7604
|
+
label: `${key} (empty)`,
|
|
7605
|
+
indent: 0,
|
|
7606
|
+
itemIdx: rec.idx
|
|
7607
|
+
});
|
|
7608
|
+
}
|
|
7609
|
+
const otherKeySet = new Set(otherKeys);
|
|
7610
|
+
const subgraph = graph.filter((n) => otherKeySet.has(n.name));
|
|
7611
|
+
const closures = computeAllClosures(subgraph);
|
|
7612
|
+
const sharedDeps = findSharedDeps(closures);
|
|
7613
|
+
const hasCycleDepDirect = (name) => {
|
|
7614
|
+
const it = itemByKey.get(name)?.it;
|
|
7615
|
+
if (!it) return false;
|
|
7616
|
+
for (const target of allowedComponentNames(it.entry)) {
|
|
7617
|
+
if (cycleParticipants.has(target)) return true;
|
|
7618
|
+
}
|
|
7619
|
+
return false;
|
|
7620
|
+
};
|
|
7621
|
+
const rootNames = [...closures.keys()].sort();
|
|
7622
|
+
const standaloneRoots = [];
|
|
7623
|
+
const groupRoots = [];
|
|
7624
|
+
for (const root of rootNames) {
|
|
7625
|
+
const c2 = closures.get(root);
|
|
7626
|
+
const promotesForCycle = hasCycleDepDirect(root);
|
|
7627
|
+
if (c2.nodes.length <= 1 && !promotesForCycle) standaloneRoots.push(root);
|
|
7628
|
+
else groupRoots.push(root);
|
|
7629
|
+
}
|
|
7630
|
+
const seenSharedOccurrence = /* @__PURE__ */ new Set();
|
|
7631
|
+
const seenCycleChildOccurrence = /* @__PURE__ */ new Set();
|
|
7632
|
+
for (const root of groupRoots) {
|
|
7633
|
+
const closure = closures.get(root);
|
|
7634
|
+
let injectedCycleCount = 0;
|
|
7635
|
+
const seenInject = /* @__PURE__ */ new Set();
|
|
7636
|
+
const countInjections = (parentName) => {
|
|
7637
|
+
const parentItem = itemByKey.get(parentName)?.it;
|
|
7638
|
+
if (!parentItem) return;
|
|
7639
|
+
for (const target of allowedComponentNames(parentItem.entry)) {
|
|
7640
|
+
if (!cycleParticipants.has(target)) continue;
|
|
7641
|
+
const key = `${parentName}\u2192${target}`;
|
|
7642
|
+
if (seenInject.has(key)) continue;
|
|
7643
|
+
seenInject.add(key);
|
|
7644
|
+
injectedCycleCount += 1;
|
|
7645
|
+
}
|
|
7646
|
+
};
|
|
7647
|
+
countInjections(root);
|
|
7648
|
+
for (const n of closure.nodes) if (n.name !== root) countInjections(n.name);
|
|
7649
|
+
const depCount = closure.nodes.length - 1 + injectedCycleCount;
|
|
7650
|
+
const expanded = alwaysExpanded ? true : props.expandedGroups.has(root);
|
|
7651
|
+
const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
|
|
7652
|
+
const aggregate = expanded ? null : aggregateGlyphFor(closure, statusByName);
|
|
7653
|
+
const rec = itemByKey.get(root);
|
|
7654
|
+
rows.push({
|
|
7655
|
+
kind: "group-root",
|
|
7656
|
+
key: `root:${root}`,
|
|
7657
|
+
label: `${glyphExpand} ${root} (${depCount} dep${depCount === 1 ? "" : "s"})${aggregate ? " " + aggregate : ""}`,
|
|
7658
|
+
indent: 0,
|
|
7659
|
+
aggregateGlyph: aggregate,
|
|
7660
|
+
itemIdx: rec.idx,
|
|
7661
|
+
rootName: root
|
|
7662
|
+
});
|
|
7663
|
+
if (!expanded) continue;
|
|
7664
|
+
const closureChildren = closure.nodes.filter((n) => n.name !== root).slice().sort((a, b) => a.depth - b.depth || a.name.localeCompare(b.name));
|
|
7665
|
+
const injectedChildren = [];
|
|
7666
|
+
const emitCycleChildrenOf = (parentName, parentDepth) => {
|
|
7667
|
+
const parentItem = itemByKey.get(parentName)?.it;
|
|
7668
|
+
if (!parentItem) return;
|
|
7669
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7670
|
+
for (const target of allowedComponentNames(parentItem.entry)) {
|
|
7671
|
+
if (!cycleParticipants.has(target)) continue;
|
|
7672
|
+
if (seen.has(target)) continue;
|
|
7673
|
+
seen.add(target);
|
|
7674
|
+
injectedChildren.push({
|
|
7675
|
+
name: target,
|
|
7676
|
+
depth: parentDepth + 1,
|
|
7677
|
+
isCycleChild: true
|
|
7678
|
+
});
|
|
7679
|
+
}
|
|
7680
|
+
};
|
|
7681
|
+
emitCycleChildrenOf(root, 0);
|
|
7682
|
+
for (const c2 of closureChildren) {
|
|
7683
|
+
injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
|
|
7684
|
+
emitCycleChildrenOf(c2.name, c2.depth);
|
|
7685
|
+
}
|
|
7686
|
+
const isLastAtDepth = (idx) => {
|
|
7687
|
+
const own = injectedChildren[idx].depth;
|
|
7688
|
+
for (let j = idx + 1; j < injectedChildren.length; j++) {
|
|
7689
|
+
const d = injectedChildren[j].depth;
|
|
7690
|
+
if (d < own) return true;
|
|
7691
|
+
if (d === own) return false;
|
|
7692
|
+
}
|
|
7693
|
+
return true;
|
|
7694
|
+
};
|
|
7695
|
+
injectedChildren.forEach((child, i) => {
|
|
7696
|
+
const isLast = isLastAtDepth(i);
|
|
7697
|
+
const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
|
|
7698
|
+
let sharedSuffix = false;
|
|
7699
|
+
if (child.isCycleChild) {
|
|
7700
|
+
if (seenCycleChildOccurrence.has(child.name)) sharedSuffix = true;
|
|
7701
|
+
else seenCycleChildOccurrence.add(child.name);
|
|
7702
|
+
} else if (sharedDeps.has(child.name)) {
|
|
7703
|
+
if (seenSharedOccurrence.has(child.name)) sharedSuffix = true;
|
|
7704
|
+
else seenSharedOccurrence.add(child.name);
|
|
7705
|
+
}
|
|
7706
|
+
const childRec = itemByKey.get(child.name);
|
|
7707
|
+
const indent = " ".repeat(Math.max(0, child.depth - 1));
|
|
7708
|
+
const labelName = child.isCycleChild ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
|
|
7709
|
+
rows.push({
|
|
7710
|
+
kind: "group-child",
|
|
7711
|
+
key: `child:${root}:${child.name}`,
|
|
7712
|
+
label: `${indent}${glyph} ${labelName}${sharedSuffix ? " (shared)" : ""}`,
|
|
7713
|
+
indent: child.depth,
|
|
7714
|
+
sharedSuffix,
|
|
7715
|
+
cycleChild: child.isCycleChild || void 0,
|
|
7716
|
+
itemIdx: childRec?.idx ?? -1,
|
|
7717
|
+
rootName: root
|
|
7718
|
+
});
|
|
7719
|
+
});
|
|
7720
|
+
}
|
|
7721
|
+
for (const name of standaloneRoots) {
|
|
7722
|
+
const rec = itemByKey.get(name);
|
|
7723
|
+
if (!rec) continue;
|
|
7724
|
+
rows.push({
|
|
7725
|
+
kind: "standalone",
|
|
7726
|
+
key: `stand:${name}`,
|
|
7727
|
+
label: name,
|
|
7728
|
+
indent: 0,
|
|
7729
|
+
itemIdx: rec.idx
|
|
7730
|
+
});
|
|
7731
|
+
}
|
|
7732
|
+
const nodeByName = new Map(subgraph.map((n) => [n.name, n]));
|
|
7733
|
+
const sharedLeafNames = [...sharedDeps.keys()].filter((name) => (nodeByName.get(name)?.slots.length ?? 0) === 0).sort();
|
|
7734
|
+
const seenStandaloneNames = new Set(standaloneRoots);
|
|
7735
|
+
for (const name of sharedLeafNames) {
|
|
7736
|
+
if (seenStandaloneNames.has(name)) continue;
|
|
7737
|
+
const rec = itemByKey.get(name);
|
|
7738
|
+
if (!rec) continue;
|
|
7739
|
+
rows.push({
|
|
7740
|
+
kind: "standalone",
|
|
7741
|
+
key: `shared-standalone:${name}`,
|
|
7742
|
+
label: `${name} (shared)`,
|
|
7743
|
+
indent: 0,
|
|
7744
|
+
sharedSuffix: true,
|
|
7745
|
+
itemIdx: rec.idx
|
|
7746
|
+
});
|
|
7747
|
+
}
|
|
7748
|
+
if (showFlatTier) {
|
|
7749
|
+
const flatNames = otherKeys.slice().sort();
|
|
7750
|
+
if (flatNames.length > 0) {
|
|
7751
|
+
rows.push({
|
|
7752
|
+
kind: "flat-header",
|
|
7753
|
+
key: "flat-header",
|
|
7754
|
+
label: "\u2500\u2500 All components \u2500\u2500",
|
|
7755
|
+
indent: 0,
|
|
7756
|
+
itemIdx: -1
|
|
7757
|
+
});
|
|
7758
|
+
for (const name of flatNames) {
|
|
7759
|
+
const rec = itemByKey.get(name);
|
|
7760
|
+
if (!rec) continue;
|
|
7761
|
+
rows.push({
|
|
7762
|
+
kind: "flat",
|
|
7763
|
+
key: `flat:${name}`,
|
|
7764
|
+
label: name,
|
|
7765
|
+
indent: 0,
|
|
7766
|
+
itemIdx: rec.idx
|
|
7767
|
+
});
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
}
|
|
7771
|
+
if (filterVisibleKeys !== void 0) {
|
|
7772
|
+
return rows.filter((row) => {
|
|
7773
|
+
if (row.itemIdx < 0) return true;
|
|
7774
|
+
const name = items[row.itemIdx]?.key;
|
|
7775
|
+
if (name === void 0) return true;
|
|
7776
|
+
return filterVisibleKeys.has(name);
|
|
7777
|
+
});
|
|
7778
|
+
}
|
|
7779
|
+
return rows;
|
|
7780
|
+
}
|
|
7781
|
+
function rowColor(row, aggregate) {
|
|
7782
|
+
if (row.kind === "cycle") return PALETTE2.warning;
|
|
7783
|
+
if (row.kind === "group-child" && row.cycleChild) return PALETTE2.warning;
|
|
7784
|
+
if (row.kind === "empty") return PALETTE2.warning;
|
|
7785
|
+
if (row.kind === "group-root" && aggregate === GLYPH_ERROR) return PALETTE2.error;
|
|
7786
|
+
if (row.kind === "group-root" && aggregate === GLYPH_WARN) return PALETTE2.warning;
|
|
7787
|
+
return void 0;
|
|
7788
|
+
}
|
|
7789
|
+
function labelStyleFor(input) {
|
|
7790
|
+
const { row, isCursor, wouldDim } = input;
|
|
7791
|
+
if (isCursor) {
|
|
7792
|
+
return { color: PALETTE2.info, bold: true, dim: false };
|
|
7793
|
+
}
|
|
7794
|
+
return {
|
|
7795
|
+
color: rowColor(row, row.aggregateGlyph),
|
|
7796
|
+
bold: false,
|
|
7797
|
+
dim: wouldDim
|
|
7798
|
+
};
|
|
7799
|
+
}
|
|
7800
|
+
function selectionGlyphStyleFor(selState, isCycleRow) {
|
|
7801
|
+
if (selState === "accepted") {
|
|
7802
|
+
return { glyph: "[\u2713]", color: PALETTE2.success, dim: false, bold: isCycleRow };
|
|
7803
|
+
}
|
|
7804
|
+
if (selState === "rejected") {
|
|
7805
|
+
return { glyph: "[\u2717]", color: PALETTE2.error, dim: false, bold: isCycleRow };
|
|
7806
|
+
}
|
|
7807
|
+
if (selState === "undecided") {
|
|
7808
|
+
return { glyph: "[ ]", color: PALETTE2.muted, dim: !isCycleRow, bold: false };
|
|
7809
|
+
}
|
|
7810
|
+
return { glyph: null, color: void 0, dim: false, bold: false };
|
|
7811
|
+
}
|
|
7812
|
+
function inheritanceGlyphStyleFor(input) {
|
|
7813
|
+
const { status, isOwn, isCursor } = input;
|
|
7814
|
+
if (status === "error") {
|
|
7815
|
+
return { glyph: GLYPH_ERROR, color: PALETTE2.error, dim: !isCursor && !isOwn, bold: isCursor };
|
|
7816
|
+
}
|
|
7817
|
+
if (status === "warning") {
|
|
7818
|
+
return { glyph: GLYPH_WARN, color: PALETTE2.warning, dim: !isCursor && !isOwn, bold: isCursor };
|
|
7819
|
+
}
|
|
7820
|
+
return { glyph: null, color: void 0, dim: false, bold: false };
|
|
7821
|
+
}
|
|
7822
|
+
function GroupedSidebar(props) {
|
|
7823
|
+
const {
|
|
7824
|
+
items,
|
|
7825
|
+
cycleParticipants = /* @__PURE__ */ new Set(),
|
|
7826
|
+
expandedGroups,
|
|
7827
|
+
focused,
|
|
7828
|
+
width,
|
|
7829
|
+
title,
|
|
7830
|
+
wrapLabels = false,
|
|
7831
|
+
selectedIdx,
|
|
7832
|
+
selectedRowIdx,
|
|
7833
|
+
renderStatusByKey,
|
|
7834
|
+
previewAnnotationByKey,
|
|
7835
|
+
scrollOffset,
|
|
7836
|
+
visibleCount,
|
|
7837
|
+
alwaysExpanded,
|
|
7838
|
+
showFlatTier,
|
|
7839
|
+
viewMode,
|
|
7840
|
+
selectionStateByKey,
|
|
7841
|
+
aiFlaggedByKey,
|
|
7842
|
+
dimPredicate,
|
|
7843
|
+
visibleRows: providedRows,
|
|
7844
|
+
graph,
|
|
7845
|
+
filterVisibleKeys
|
|
7846
|
+
} = props;
|
|
7847
|
+
const allRows = providedRows ?? buildVisibleRows({
|
|
7848
|
+
items,
|
|
7849
|
+
cycleParticipants,
|
|
7850
|
+
expandedGroups,
|
|
7851
|
+
alwaysExpanded,
|
|
7852
|
+
showFlatTier,
|
|
7853
|
+
viewMode,
|
|
7854
|
+
graph,
|
|
7855
|
+
filterVisibleKeys
|
|
7856
|
+
});
|
|
7857
|
+
const windowed = scrollOffset !== void 0 && visibleCount !== void 0;
|
|
7858
|
+
const start = windowed ? Math.max(0, scrollOffset ?? 0) : 0;
|
|
7859
|
+
const end = windowed ? start + (visibleCount ?? allRows.length) : allRows.length;
|
|
7860
|
+
const rows = windowed ? allRows.slice(start, end) : allRows;
|
|
7861
|
+
return /* @__PURE__ */ jsxs18(WindowedPanel, { width, height: props.height, title, focused, children: [
|
|
7862
|
+
windowed && /* @__PURE__ */ jsx21(WindowIndicator, { direction: "up", count: start }),
|
|
7863
|
+
rows.map((row, i) => {
|
|
7864
|
+
const absoluteRowIdx = start + i;
|
|
7865
|
+
const isSelected = selectedRowIdx !== void 0 ? absoluteRowIdx === selectedRowIdx && row.itemIdx >= 0 : row.itemIdx >= 0 && row.itemIdx === selectedIdx;
|
|
7866
|
+
const itemName = row.itemIdx >= 0 ? items[row.itemIdx]?.key : void 0;
|
|
7867
|
+
const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
|
|
7868
|
+
const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
|
|
7869
|
+
const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
|
|
7870
|
+
const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
|
|
7871
|
+
const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
|
|
7872
|
+
const isCycleRow = row.kind === "cycle";
|
|
7873
|
+
const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
|
|
7874
|
+
const selGlyph = selStyle.glyph;
|
|
7875
|
+
const selColor = selStyle.color;
|
|
7876
|
+
const selDim = selStyle.dim;
|
|
7877
|
+
const selBold = selStyle.bold;
|
|
7878
|
+
const aiFlagged = aiFlaggedByKey !== void 0 && itemName !== void 0 && row.kind !== "flat-header" && aiFlaggedByKey.get(itemName) === true;
|
|
7879
|
+
const canDim = dimPredicate !== void 0 && itemName !== void 0 && row.kind !== "cycle" && row.kind !== "group-root" && row.kind !== "flat-header" && dimPredicate(itemName);
|
|
7880
|
+
const isSynthetic = row.kind === "flat-header";
|
|
7881
|
+
const isCursor = isSelected;
|
|
7882
|
+
const wouldDim = row.kind === "flat-header" || row.sharedSuffix === true || canDim;
|
|
7883
|
+
const labelStyle = labelStyleFor({ row, isCursor, wouldDim });
|
|
7884
|
+
const inheritanceStyle = inheritanceGlyphStyleFor({
|
|
7885
|
+
status: showInheritance ? rs?.status : void 0,
|
|
7886
|
+
isOwn: rs?.isOwn ?? false,
|
|
7887
|
+
isCursor
|
|
7888
|
+
});
|
|
7889
|
+
return /* @__PURE__ */ jsxs18(Box17, { children: [
|
|
7890
|
+
isCursor ? /* @__PURE__ */ jsx21(Text19, { color: PALETTE2.info, bold: true, children: figures4.pointer }) : /* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
7891
|
+
/* @__PURE__ */ jsx21(PreviewBadge, { badge, highlighted: isSelected }),
|
|
7892
|
+
selectionStateByKey !== void 0 && (selGlyph && !isSynthetic ? /* @__PURE__ */ jsx21(Text19, { color: !isSelected && selDim ? PALETTE2.muted : selColor, bold: selBold, children: " " + selGlyph }) : /* @__PURE__ */ jsx21(Text19, { children: " " })),
|
|
7893
|
+
aiFlaggedByKey !== void 0 && (aiFlagged ? /* @__PURE__ */ jsx21(Text19, { color: PALETTE2.warning, bold: true, children: " [\xD7]" }) : /* @__PURE__ */ jsx21(Text19, { children: " " })),
|
|
7894
|
+
/* @__PURE__ */ jsxs18(
|
|
7895
|
+
Text19,
|
|
7896
|
+
{
|
|
7897
|
+
color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
|
|
7898
|
+
bold: isSelected || labelStyle.bold,
|
|
7899
|
+
inverse: false,
|
|
7900
|
+
underline: isSelected && !focused,
|
|
7901
|
+
wrap: wrapLabels ? "wrap" : "truncate",
|
|
7902
|
+
children: [
|
|
7903
|
+
" ",
|
|
7904
|
+
row.label
|
|
7905
|
+
]
|
|
7906
|
+
}
|
|
7907
|
+
),
|
|
7908
|
+
inheritanceStyle.glyph && /* @__PURE__ */ jsx21(Text19, { color: inheritanceStyle.dim ? PALETTE2.muted : inheritanceStyle.color, bold: inheritanceStyle.bold, children: " " + inheritanceStyle.glyph })
|
|
7909
|
+
] }, row.key);
|
|
7910
|
+
}),
|
|
7911
|
+
windowed && /* @__PURE__ */ jsx21(WindowIndicator, { direction: "down", count: allRows.length - end })
|
|
7912
|
+
] });
|
|
7913
|
+
}
|
|
7914
|
+
|
|
7915
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.tsx
|
|
7916
|
+
import React7 from "react";
|
|
7917
|
+
import { Box as Box18, Text as Text20 } from "ink";
|
|
7918
|
+
|
|
7919
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/useImmediateInput.ts
|
|
7920
|
+
import { useLayoutEffect, useRef as useRef3 } from "react";
|
|
7921
|
+
import { useStdin } from "ink";
|
|
7922
|
+
function parseInput(data) {
|
|
7923
|
+
const isShiftTab = data === "\x1B[Z";
|
|
7924
|
+
const key = {
|
|
7925
|
+
upArrow: data === "\x1B[A",
|
|
7926
|
+
downArrow: data === "\x1B[B",
|
|
7927
|
+
leftArrow: data === "\x1B[D",
|
|
7928
|
+
rightArrow: data === "\x1B[C",
|
|
7929
|
+
pageDown: data === "\x1B[6~",
|
|
7930
|
+
pageUp: data === "\x1B[5~",
|
|
7931
|
+
return: data === "\r" || data === "\n",
|
|
7932
|
+
escape: data === "\x1B",
|
|
7933
|
+
ctrl: false,
|
|
7934
|
+
shift: isShiftTab,
|
|
7935
|
+
tab: data === " " || isShiftTab,
|
|
7936
|
+
shiftTab: isShiftTab,
|
|
7937
|
+
backspace: data === "\x7F" || data === "\b",
|
|
7938
|
+
delete: data === "\x1B[3~",
|
|
7939
|
+
meta: data === "\x1B"
|
|
7940
|
+
};
|
|
7941
|
+
let input = data;
|
|
7942
|
+
if (data.length === 1) {
|
|
7943
|
+
const code = data.charCodeAt(0);
|
|
7944
|
+
if (code >= 1 && code <= 26) {
|
|
7945
|
+
key.ctrl = true;
|
|
7946
|
+
input = String.fromCharCode(code + 96);
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.pageUp || key.pageDown || key.return || key.escape || key.tab || key.backspace || key.delete) {
|
|
7950
|
+
if (!key.ctrl) input = "";
|
|
7951
|
+
}
|
|
7952
|
+
return { input, key };
|
|
7953
|
+
}
|
|
7954
|
+
var inputRegistries = /* @__PURE__ */ new WeakMap();
|
|
7955
|
+
function registerInputHandler(stdin, setRawMode, handler) {
|
|
7956
|
+
let registry = inputRegistries.get(stdin);
|
|
7957
|
+
if (!registry) {
|
|
7958
|
+
const handlers = /* @__PURE__ */ new Set();
|
|
7959
|
+
const onData = (data) => {
|
|
7960
|
+
const str = Buffer.isBuffer(data) ? data.toString("utf8") : data;
|
|
7961
|
+
const { input, key } = parseInput(str);
|
|
7962
|
+
for (const registered of [...handlers]) registered(input, key);
|
|
7963
|
+
};
|
|
7964
|
+
registry = { handlers, onData, setRawMode };
|
|
7965
|
+
inputRegistries.set(stdin, registry);
|
|
7966
|
+
setRawMode(true);
|
|
7967
|
+
stdin.on("data", onData);
|
|
7968
|
+
}
|
|
7969
|
+
registry.handlers.add(handler);
|
|
7970
|
+
return () => {
|
|
7971
|
+
const current = inputRegistries.get(stdin);
|
|
7972
|
+
if (!current) return;
|
|
7973
|
+
current.handlers.delete(handler);
|
|
7974
|
+
if (current.handlers.size === 0) {
|
|
7975
|
+
stdin.off("data", current.onData);
|
|
7976
|
+
current.setRawMode(false);
|
|
7977
|
+
inputRegistries.delete(stdin);
|
|
7978
|
+
}
|
|
7979
|
+
};
|
|
7980
|
+
}
|
|
7981
|
+
function useImmediateInput(handler, enabled = true) {
|
|
7982
|
+
const { stdin, setRawMode } = useStdin();
|
|
7983
|
+
const handlerRef = useRef3(handler);
|
|
7984
|
+
handlerRef.current = handler;
|
|
7985
|
+
useLayoutEffect(() => {
|
|
7986
|
+
if (!enabled) return;
|
|
7987
|
+
const unregister = registerInputHandler(stdin, setRawMode, (input, key) => handlerRef.current(input, key));
|
|
7988
|
+
return unregister;
|
|
7989
|
+
}, [enabled, stdin, setRawMode]);
|
|
7990
|
+
}
|
|
7991
|
+
|
|
7992
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.ts
|
|
7993
|
+
import { useStdout as useStdout2 } from "ink";
|
|
7994
|
+
import { useEffect as useEffect6, useState as useState9 } from "react";
|
|
7995
|
+
function readTerminalSize(stdout) {
|
|
7996
|
+
return {
|
|
7997
|
+
columns: stdout?.columns ?? 80,
|
|
7998
|
+
rows: stdout?.rows ?? process.stdout.rows ?? 40
|
|
7999
|
+
};
|
|
8000
|
+
}
|
|
8001
|
+
function useTerminalSize() {
|
|
8002
|
+
const { stdout } = useStdout2();
|
|
8003
|
+
const [size, setSize] = useState9(() => readTerminalSize(stdout));
|
|
8004
|
+
useEffect6(() => {
|
|
8005
|
+
const updateSize = () => setSize(readTerminalSize(stdout));
|
|
8006
|
+
stdout?.on("resize", updateSize);
|
|
8007
|
+
updateSize();
|
|
8008
|
+
return () => {
|
|
8009
|
+
stdout?.off("resize", updateSize);
|
|
8010
|
+
};
|
|
8011
|
+
}, [stdout]);
|
|
8012
|
+
return size;
|
|
8013
|
+
}
|
|
8014
|
+
|
|
8015
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.tsx
|
|
8016
|
+
import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8017
|
+
function HelpOverlay(props) {
|
|
8018
|
+
const { onClose } = props;
|
|
8019
|
+
const { columns: terminalColumns, rows: terminalRows } = useTerminalSize();
|
|
8020
|
+
const panelWidth = Math.max(10, Math.min(64, terminalColumns - 2));
|
|
8021
|
+
const panelHeight = terminalPanelHeight(terminalRows, 2);
|
|
8022
|
+
const titleRule = Math.max(0, Math.floor((panelWidth - 10) / 2));
|
|
8023
|
+
useImmediateInput((input, key) => {
|
|
8024
|
+
if (input === "h" || key.escape) onClose();
|
|
8025
|
+
}, props.handleInput !== false);
|
|
8026
|
+
if (props.sections) {
|
|
8027
|
+
return /* @__PURE__ */ jsxs19(
|
|
8028
|
+
Box18,
|
|
8029
|
+
{
|
|
8030
|
+
flexDirection: "column",
|
|
8031
|
+
borderStyle: "round",
|
|
8032
|
+
padding: 1,
|
|
8033
|
+
width: panelWidth,
|
|
8034
|
+
height: panelHeight,
|
|
8035
|
+
overflowY: "hidden",
|
|
8036
|
+
children: [
|
|
8037
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, children: "\u2500".repeat(titleRule) + " Help " + "\u2500".repeat(titleRule) }),
|
|
8038
|
+
props.sections.map((section) => /* @__PURE__ */ jsxs19(React7.Fragment, { children: [
|
|
8039
|
+
/* @__PURE__ */ jsx22(Text20, { children: " " }),
|
|
8040
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, children: section.title }),
|
|
8041
|
+
section.entries.map((entry) => /* @__PURE__ */ jsx22(Text20, { children: entry.keys ? " " + entry.keys.padEnd(16) + " " + entry.label : " " + entry.label }, entry.keys + entry.label))
|
|
8042
|
+
] }, section.title))
|
|
8043
|
+
]
|
|
8044
|
+
}
|
|
8045
|
+
);
|
|
8046
|
+
}
|
|
8047
|
+
const mode = props.mode;
|
|
8048
|
+
return /* @__PURE__ */ jsxs19(
|
|
8049
|
+
Box18,
|
|
8050
|
+
{
|
|
8051
|
+
flexDirection: "column",
|
|
8052
|
+
borderStyle: "round",
|
|
8053
|
+
padding: 1,
|
|
8054
|
+
width: panelWidth,
|
|
8055
|
+
height: panelHeight,
|
|
8056
|
+
overflowY: "hidden",
|
|
8057
|
+
children: [
|
|
8058
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, children: "\u2500".repeat(titleRule) + " Help " + "\u2500".repeat(titleRule) }),
|
|
8059
|
+
/* @__PURE__ */ jsx22(Text20, { children: " " }),
|
|
8060
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, children: "Navigation" }),
|
|
8061
|
+
/* @__PURE__ */ jsx22(Text20, { children: " \u2191 / k / PgUp Scroll up" }),
|
|
8062
|
+
/* @__PURE__ */ jsx22(Text20, { children: " \u2193 / j / PgDn Scroll down" }),
|
|
8063
|
+
/* @__PURE__ */ jsx22(Text20, { children: " g / Home Jump to top" }),
|
|
8064
|
+
/* @__PURE__ */ jsx22(Text20, { children: " G / End Jump to bottom" }),
|
|
8065
|
+
mode === "review" && /* @__PURE__ */ jsxs19(Fragment2, { children: [
|
|
8066
|
+
/* @__PURE__ */ jsx22(Text20, { children: " " }),
|
|
8067
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, children: "[Review mode only]" }),
|
|
8068
|
+
/* @__PURE__ */ jsx22(Text20, { children: " Tab Toggle sidebar/detail" }),
|
|
8069
|
+
/* @__PURE__ */ jsx22(Text20, { children: " a Accept component" }),
|
|
8070
|
+
/* @__PURE__ */ jsx22(Text20, { children: " r Reject component" }),
|
|
8071
|
+
/* @__PURE__ */ jsx22(Text20, { children: " e Edit proposal" }),
|
|
8072
|
+
/* @__PURE__ */ jsx22(Text20, { children: " s Toggle source code" }),
|
|
8073
|
+
/* @__PURE__ */ jsx22(Text20, { children: " A Approve all" }),
|
|
8074
|
+
/* @__PURE__ */ jsx22(Text20, { children: " F Open finalize dialog" }),
|
|
8075
|
+
/* @__PURE__ */ jsx22(Text20, { children: " Ctrl+S Save draft" }),
|
|
8076
|
+
/* @__PURE__ */ jsx22(Text20, { children: " Ctrl+Z Undo" }),
|
|
8077
|
+
/* @__PURE__ */ jsx22(Text20, { children: " Ctrl+Y Redo" }),
|
|
8078
|
+
/* @__PURE__ */ jsx22(Text20, { children: " Esc Exit edit / close" })
|
|
8079
|
+
] }),
|
|
8080
|
+
/* @__PURE__ */ jsx22(Text20, { children: " " }),
|
|
8081
|
+
/* @__PURE__ */ jsx22(Text20, { children: " h Close help" }),
|
|
8082
|
+
/* @__PURE__ */ jsx22(Text20, { children: " q Quit" })
|
|
8083
|
+
]
|
|
8084
|
+
}
|
|
8085
|
+
);
|
|
8086
|
+
}
|
|
8087
|
+
|
|
8088
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.tsx
|
|
8089
|
+
import { Box as Box19, Text as Text21 } from "ink";
|
|
8090
|
+
|
|
8091
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/autocomplete.ts
|
|
8092
|
+
function longestCommonPrefix(names) {
|
|
8093
|
+
if (names.length === 0) return "";
|
|
8094
|
+
let prefixLen = names[0].length;
|
|
8095
|
+
for (let i = 1; i < names.length; i++) {
|
|
8096
|
+
const other = names[i];
|
|
8097
|
+
let j = 0;
|
|
8098
|
+
while (j < prefixLen && j < other.length && names[0][j].toLowerCase() === other[j].toLowerCase()) {
|
|
8099
|
+
j++;
|
|
8100
|
+
}
|
|
8101
|
+
prefixLen = j;
|
|
8102
|
+
if (prefixLen === 0) break;
|
|
8103
|
+
}
|
|
8104
|
+
return names[0].slice(0, prefixLen);
|
|
8105
|
+
}
|
|
8106
|
+
function computeAutocomplete(query, names) {
|
|
8107
|
+
const q = query.toLowerCase();
|
|
8108
|
+
const candidates = names.filter((n) => n.toLowerCase().startsWith(q));
|
|
8109
|
+
if (candidates.length === 0) {
|
|
8110
|
+
return { completion: query, candidates: [] };
|
|
8111
|
+
}
|
|
8112
|
+
if (candidates.length === 1) {
|
|
8113
|
+
return { completion: candidates[0], candidates: [] };
|
|
8114
|
+
}
|
|
8115
|
+
const lcp = longestCommonPrefix(candidates);
|
|
8116
|
+
const completion = lcp.length >= query.length ? lcp : query;
|
|
8117
|
+
const sorted = [...candidates].sort();
|
|
8118
|
+
return { completion, candidates: sorted };
|
|
8119
|
+
}
|
|
8120
|
+
|
|
8121
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-input.ts
|
|
8122
|
+
function handleSidebarSearchInput(input, key, { query, names, setQuery, setCandidates }) {
|
|
8123
|
+
if (key.tab) {
|
|
8124
|
+
const { completion, candidates } = computeAutocomplete(query, names);
|
|
8125
|
+
setQuery(completion);
|
|
8126
|
+
setCandidates(candidates);
|
|
8127
|
+
return true;
|
|
8128
|
+
}
|
|
8129
|
+
if (key.backspace) {
|
|
8130
|
+
setCandidates([]);
|
|
8131
|
+
setQuery((current) => current.slice(0, -1));
|
|
8132
|
+
return true;
|
|
8133
|
+
}
|
|
8134
|
+
if (input && input.length === 1 && input >= " " && input !== "\r" && input !== "\n") {
|
|
8135
|
+
setCandidates([]);
|
|
8136
|
+
setQuery((current) => current + input);
|
|
8137
|
+
return true;
|
|
8138
|
+
}
|
|
8139
|
+
return false;
|
|
8140
|
+
}
|
|
8141
|
+
function formatSearchMatchSummary(matches, total) {
|
|
8142
|
+
return ` (${matches}/${total} matches)`;
|
|
8143
|
+
}
|
|
8144
|
+
|
|
8145
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.tsx
|
|
8146
|
+
import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
8147
|
+
function SearchMatchSummary({
|
|
8148
|
+
open,
|
|
8149
|
+
query,
|
|
8150
|
+
matches,
|
|
8151
|
+
total,
|
|
8152
|
+
autocompleteCandidates,
|
|
8153
|
+
hidden = false,
|
|
8154
|
+
marginTop
|
|
8155
|
+
}) {
|
|
8156
|
+
if (hidden) return null;
|
|
8157
|
+
return /* @__PURE__ */ jsxs20(Fragment3, { children: [
|
|
8158
|
+
open && /* @__PURE__ */ jsxs20(Box19, { marginTop, flexDirection: "column", children: [
|
|
8159
|
+
/* @__PURE__ */ jsxs20(Text21, { children: [
|
|
8160
|
+
`/${query}`,
|
|
8161
|
+
/* @__PURE__ */ jsx23(Text21, { color: PALETTE2.info, children: "\u258E" }),
|
|
8162
|
+
query && /* @__PURE__ */ jsx23(Text21, { color: PALETTE2.muted, children: formatSearchMatchSummary(matches, total) }),
|
|
8163
|
+
/* @__PURE__ */ jsx23(Text21, { children: " \xB7 [Esc] leave" })
|
|
8164
|
+
] }),
|
|
8165
|
+
autocompleteCandidates.length > 1 && /* @__PURE__ */ jsx23(Text21, { color: PALETTE2.muted, children: ` possibilities: ${autocompleteCandidates.join(" \xB7 ").slice(0, 120)}` })
|
|
8166
|
+
] }),
|
|
8167
|
+
!open && query && /* @__PURE__ */ jsx23(Box19, { marginTop, children: /* @__PURE__ */ jsx23(Text21, { children: `/${query}${formatSearchMatchSummary(matches, total)} \xB7 [Esc] clear` }) })
|
|
8168
|
+
] });
|
|
8169
|
+
}
|
|
8170
|
+
|
|
8171
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-help.ts
|
|
8172
|
+
function createSidebarViewsHelpSection(includeBreaking) {
|
|
8173
|
+
const entries = [
|
|
8174
|
+
{ keys: "L", label: "Flat view" },
|
|
8175
|
+
{ keys: "i", label: "Focus lineage" }
|
|
8176
|
+
];
|
|
8177
|
+
if (includeBreaking) entries.push({ keys: "w", label: "Only breaking" });
|
|
8178
|
+
entries.push(
|
|
8179
|
+
{ keys: "o", label: "Only cycles" },
|
|
8180
|
+
{ keys: "space", label: "Expand/collapse group" },
|
|
8181
|
+
{ keys: "E / C", label: "Expand/collapse all" }
|
|
8182
|
+
);
|
|
8183
|
+
return { title: "Sidebar views", entries };
|
|
8184
|
+
}
|
|
8185
|
+
|
|
8186
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
|
|
8187
|
+
import { useEffect as useEffect7, useMemo as useMemo2, useRef as useRef4, useState as useState12 } from "react";
|
|
8188
|
+
|
|
8189
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/search-neighborhood.ts
|
|
8190
|
+
function computeDirectNeighborhood(matches, graph) {
|
|
8191
|
+
const matchSet = new Set(matches);
|
|
8192
|
+
const out = new Set(matchSet);
|
|
8193
|
+
if (matchSet.size === 0) return out;
|
|
8194
|
+
for (const node of graph) {
|
|
8195
|
+
const targets = [];
|
|
8196
|
+
for (const slot of node.slots) {
|
|
8197
|
+
for (const t of slot.allowedComponents ?? []) targets.push(t);
|
|
8198
|
+
}
|
|
8199
|
+
if (matchSet.has(node.name)) {
|
|
8200
|
+
for (const t of targets) out.add(t);
|
|
8201
|
+
}
|
|
8202
|
+
for (const t of targets) {
|
|
8203
|
+
if (matchSet.has(t)) {
|
|
8204
|
+
out.add(node.name);
|
|
8205
|
+
break;
|
|
8206
|
+
}
|
|
8207
|
+
}
|
|
8208
|
+
}
|
|
8209
|
+
return out;
|
|
8210
|
+
}
|
|
8211
|
+
function findAllAncestors(target, graph) {
|
|
8212
|
+
const out = /* @__PURE__ */ new Set([target]);
|
|
8213
|
+
const parentsOf = /* @__PURE__ */ new Map();
|
|
8214
|
+
for (const node of graph) {
|
|
8215
|
+
for (const slot of node.slots) {
|
|
8216
|
+
for (const child of slot.allowedComponents ?? []) {
|
|
8217
|
+
const list = parentsOf.get(child);
|
|
8218
|
+
if (list) {
|
|
8219
|
+
if (!list.includes(node.name)) list.push(node.name);
|
|
8220
|
+
} else {
|
|
8221
|
+
parentsOf.set(child, [node.name]);
|
|
8222
|
+
}
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
}
|
|
8226
|
+
const queue = [target];
|
|
8227
|
+
while (queue.length > 0) {
|
|
8228
|
+
const cur = queue.shift();
|
|
8229
|
+
const parents = parentsOf.get(cur);
|
|
8230
|
+
if (!parents) continue;
|
|
8231
|
+
for (const p of parents) {
|
|
8232
|
+
if (out.has(p)) continue;
|
|
8233
|
+
out.add(p);
|
|
8234
|
+
queue.push(p);
|
|
8235
|
+
}
|
|
8236
|
+
}
|
|
8237
|
+
return out;
|
|
8238
|
+
}
|
|
8239
|
+
|
|
8240
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/fuzzy-search.ts
|
|
8241
|
+
function match(query, text) {
|
|
8242
|
+
if (query.length === 0) return { score: 0 };
|
|
8243
|
+
if (text.length === 0) return null;
|
|
8244
|
+
const queryLower = query.toLowerCase();
|
|
8245
|
+
const textLower = text.toLowerCase();
|
|
8246
|
+
let score = 0;
|
|
8247
|
+
let qi = 0;
|
|
8248
|
+
let lastMatchIndex = -2;
|
|
8249
|
+
for (let ti = 0; ti < text.length && qi < query.length; ti++) {
|
|
8250
|
+
if (textLower[ti] === queryLower[qi]) {
|
|
8251
|
+
score += 10;
|
|
8252
|
+
if (text[ti] === query[qi]) {
|
|
8253
|
+
score += 5;
|
|
8254
|
+
}
|
|
8255
|
+
if (ti === 0 && qi === 0) {
|
|
8256
|
+
score += 15;
|
|
8257
|
+
}
|
|
8258
|
+
if (ti === lastMatchIndex + 1) {
|
|
8259
|
+
score += 5;
|
|
8260
|
+
}
|
|
8261
|
+
lastMatchIndex = ti;
|
|
8262
|
+
qi++;
|
|
8263
|
+
}
|
|
8264
|
+
}
|
|
8265
|
+
if (qi < query.length) return null;
|
|
8266
|
+
score -= text.length * 0.1;
|
|
8267
|
+
return { score };
|
|
8268
|
+
}
|
|
8269
|
+
function fuzzyMatches(query, text) {
|
|
8270
|
+
return match(query, text) !== null;
|
|
8271
|
+
}
|
|
8272
|
+
|
|
8273
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/ai-flag.ts
|
|
8274
|
+
function isAiFlagged(row) {
|
|
8275
|
+
return row.needsReview === true || row.aiDecision === "rejected" || row.aiDecision === "failed";
|
|
8276
|
+
}
|
|
8277
|
+
|
|
8278
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/lineage.ts
|
|
8279
|
+
function findDirectParents2(target, components) {
|
|
8280
|
+
const out = [];
|
|
8281
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8282
|
+
for (const c2 of components) {
|
|
8283
|
+
if (c2.name === target) continue;
|
|
8284
|
+
for (const slot of c2.slots) {
|
|
8285
|
+
const allowed = slot.allowedComponents ?? [];
|
|
8286
|
+
if (!allowed.includes(target)) continue;
|
|
8287
|
+
const key = `${c2.name}\0${slot.name}`;
|
|
8288
|
+
if (seen.has(key)) continue;
|
|
8289
|
+
seen.add(key);
|
|
8290
|
+
out.push({ parent: c2.name, slotName: slot.name });
|
|
8291
|
+
}
|
|
8292
|
+
}
|
|
8293
|
+
out.sort((a, b) => a.parent.localeCompare(b.parent) || a.slotName.localeCompare(b.slotName));
|
|
8294
|
+
return out;
|
|
8295
|
+
}
|
|
8296
|
+
|
|
8297
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/scope-gate-cascade.ts
|
|
8298
|
+
function buildCycleUnits(slotCycles) {
|
|
8299
|
+
const parent = /* @__PURE__ */ new Map();
|
|
8300
|
+
const find = (x) => {
|
|
8301
|
+
let cur = x;
|
|
8302
|
+
while (parent.get(cur) !== cur) {
|
|
8303
|
+
cur = parent.get(cur);
|
|
8304
|
+
}
|
|
8305
|
+
let walk = x;
|
|
8306
|
+
while (parent.get(walk) !== cur) {
|
|
8307
|
+
const next = parent.get(walk);
|
|
8308
|
+
parent.set(walk, cur);
|
|
8309
|
+
walk = next;
|
|
8310
|
+
}
|
|
8311
|
+
return cur;
|
|
8312
|
+
};
|
|
8313
|
+
const union = (a, b) => {
|
|
8314
|
+
const ra = find(a);
|
|
8315
|
+
const rb = find(b);
|
|
8316
|
+
if (ra !== rb) parent.set(ra, rb);
|
|
8317
|
+
};
|
|
8318
|
+
for (const cycle of slotCycles) {
|
|
8319
|
+
for (const node of cycle.path) {
|
|
8320
|
+
if (!parent.has(node)) parent.set(node, node);
|
|
8321
|
+
}
|
|
8322
|
+
for (let i = 1; i < cycle.path.length; i++) {
|
|
8323
|
+
union(cycle.path[0], cycle.path[i]);
|
|
8324
|
+
}
|
|
8325
|
+
}
|
|
8326
|
+
const groups = /* @__PURE__ */ new Map();
|
|
8327
|
+
for (const node of parent.keys()) {
|
|
8328
|
+
const root = find(node);
|
|
8329
|
+
let group = groups.get(root);
|
|
8330
|
+
if (!group) {
|
|
8331
|
+
group = /* @__PURE__ */ new Set();
|
|
8332
|
+
groups.set(root, group);
|
|
8333
|
+
}
|
|
8334
|
+
group.add(node);
|
|
8335
|
+
}
|
|
8336
|
+
const out = /* @__PURE__ */ new Map();
|
|
8337
|
+
for (const group of groups.values()) {
|
|
8338
|
+
for (const node of group) {
|
|
8339
|
+
out.set(node, group);
|
|
8340
|
+
}
|
|
8341
|
+
}
|
|
8342
|
+
return out;
|
|
8343
|
+
}
|
|
8344
|
+
function slotTargets(node, byName) {
|
|
8345
|
+
const c2 = byName.get(node);
|
|
8346
|
+
if (!c2) return [];
|
|
8347
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8348
|
+
const out = [];
|
|
8349
|
+
for (const slot of c2.slots) {
|
|
8350
|
+
for (const target of slot.allowedComponents ?? []) {
|
|
8351
|
+
if (!byName.has(target)) continue;
|
|
8352
|
+
if (seen.has(target)) continue;
|
|
8353
|
+
seen.add(target);
|
|
8354
|
+
out.push(target);
|
|
8355
|
+
}
|
|
8356
|
+
}
|
|
8357
|
+
return out;
|
|
8358
|
+
}
|
|
8359
|
+
function computeCycleAwareAcceptCascade(target, components, cycleUnits) {
|
|
8360
|
+
const byName = new Map(components.map((c2) => [c2.name, c2]));
|
|
8361
|
+
const visited = /* @__PURE__ */ new Set();
|
|
8362
|
+
const queue = [];
|
|
8363
|
+
const enqueue = (name) => {
|
|
8364
|
+
if (visited.has(name)) return;
|
|
8365
|
+
visited.add(name);
|
|
8366
|
+
queue.push(name);
|
|
8367
|
+
const unit = cycleUnits.get(name);
|
|
8368
|
+
if (unit) {
|
|
8369
|
+
for (const member of unit) {
|
|
8370
|
+
if (!visited.has(member)) {
|
|
8371
|
+
visited.add(member);
|
|
8372
|
+
queue.push(member);
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
}
|
|
8376
|
+
};
|
|
8377
|
+
enqueue(target);
|
|
8378
|
+
while (queue.length > 0) {
|
|
8379
|
+
const cur = queue.shift();
|
|
8380
|
+
for (const next of slotTargets(cur, byName)) {
|
|
8381
|
+
enqueue(next);
|
|
8382
|
+
}
|
|
8383
|
+
}
|
|
8384
|
+
return visited;
|
|
8385
|
+
}
|
|
8386
|
+
function computeCycleAwareRejectCascade(target, components, cycleUnits) {
|
|
8387
|
+
const toReject = /* @__PURE__ */ new Set();
|
|
8388
|
+
const targetUnit = cycleUnits.get(target);
|
|
8389
|
+
const initialSeeds = targetUnit ? [...targetUnit] : [target];
|
|
8390
|
+
for (const seed of initialSeeds) toReject.add(seed);
|
|
8391
|
+
const stack = [...toReject];
|
|
8392
|
+
while (stack.length > 0) {
|
|
8393
|
+
const cur = stack.pop();
|
|
8394
|
+
for (const { parent } of findDirectParents2(cur, components)) {
|
|
8395
|
+
if (toReject.has(parent)) continue;
|
|
8396
|
+
toReject.add(parent);
|
|
8397
|
+
stack.push(parent);
|
|
8398
|
+
const unit = cycleUnits.get(parent);
|
|
8399
|
+
if (unit) {
|
|
8400
|
+
for (const member of unit) {
|
|
8401
|
+
if (!toReject.has(member)) {
|
|
8402
|
+
toReject.add(member);
|
|
8403
|
+
stack.push(member);
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8409
|
+
const acceptCascade2 = computeCycleAwareAcceptCascade(target, components, cycleUnits);
|
|
8410
|
+
const toDeselect = /* @__PURE__ */ new Set();
|
|
8411
|
+
for (const n of acceptCascade2) {
|
|
8412
|
+
if (toReject.has(n)) continue;
|
|
8413
|
+
toDeselect.add(n);
|
|
8414
|
+
}
|
|
8415
|
+
const cyclePartners = [];
|
|
8416
|
+
if (targetUnit) {
|
|
8417
|
+
for (const m of targetUnit) {
|
|
8418
|
+
if (m !== target) cyclePartners.push(m);
|
|
8419
|
+
}
|
|
8420
|
+
cyclePartners.sort();
|
|
8421
|
+
}
|
|
8422
|
+
return { toReject, toDeselect, cyclePartners };
|
|
8423
|
+
}
|
|
8424
|
+
function collectReachableCycleUnits(seeds, components, cycleUnits) {
|
|
8425
|
+
const out = /* @__PURE__ */ new Set();
|
|
8426
|
+
if (cycleUnits.size === 0) return out;
|
|
8427
|
+
const byName = new Map(components.map((c2) => [c2.name, c2]));
|
|
8428
|
+
const visited = /* @__PURE__ */ new Set();
|
|
8429
|
+
const queue = [...seeds];
|
|
8430
|
+
while (queue.length > 0) {
|
|
8431
|
+
const cur = queue.shift();
|
|
8432
|
+
if (visited.has(cur)) continue;
|
|
8433
|
+
visited.add(cur);
|
|
8434
|
+
const unit = cycleUnits.get(cur);
|
|
8435
|
+
if (unit) {
|
|
8436
|
+
for (const member of unit) {
|
|
8437
|
+
out.add(member);
|
|
8438
|
+
if (!visited.has(member)) queue.push(member);
|
|
8439
|
+
}
|
|
8440
|
+
}
|
|
8441
|
+
for (const next of slotTargets(cur, byName)) {
|
|
8442
|
+
if (!visited.has(next)) queue.push(next);
|
|
8443
|
+
}
|
|
8444
|
+
}
|
|
8445
|
+
return out;
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8448
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/slot-graph.ts
|
|
8449
|
+
var REJECTED_STATUSES = /* @__PURE__ */ new Set(["error", "rejected"]);
|
|
8450
|
+
function buildComponentGraph3(components, opts) {
|
|
8451
|
+
const stripRejectedEdges = opts?.stripRejectedEdges === true;
|
|
8452
|
+
return components.map((row) => {
|
|
8453
|
+
if (stripRejectedEdges && row.status !== void 0 && REJECTED_STATUSES.has(row.status)) {
|
|
8454
|
+
return { name: row.key, slots: [] };
|
|
8455
|
+
}
|
|
8456
|
+
const slotDefs = row.entry.$slots ?? {};
|
|
8457
|
+
const slots = Object.entries(slotDefs).map(([slotName, slotDef]) => ({
|
|
8458
|
+
name: slotName,
|
|
8459
|
+
allowedComponents: Array.isArray(slotDef?.$allowedComponents) ? slotDef.$allowedComponents.filter((v) => typeof v === "string") : []
|
|
8460
|
+
}));
|
|
8461
|
+
return { name: row.key, slots };
|
|
8462
|
+
});
|
|
8463
|
+
}
|
|
8464
|
+
|
|
8465
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/index.ts
|
|
8466
|
+
function sidebarItems(components) {
|
|
8467
|
+
return components.map((c2) => ({
|
|
8468
|
+
key: c2.name,
|
|
8469
|
+
entry: toSidebarEntry(c2),
|
|
8470
|
+
status: isAiFlagged(c2) ? "warning" : "ok"
|
|
8471
|
+
}));
|
|
8472
|
+
}
|
|
8473
|
+
function toSidebarEntry(c2) {
|
|
8474
|
+
const $slots = {};
|
|
8475
|
+
for (const s of c2.slots ?? []) $slots[s.name] = { $allowedComponents: s.allowedComponents };
|
|
8476
|
+
const entry = {
|
|
8477
|
+
$type: "component",
|
|
8478
|
+
$properties: { __scopeGate: { $type: "string", $category: "content" } }
|
|
8479
|
+
};
|
|
8480
|
+
if (Object.keys($slots).length > 0) entry.$slots = $slots;
|
|
8481
|
+
return entry;
|
|
8482
|
+
}
|
|
8483
|
+
function buildScopeGraph(components) {
|
|
8484
|
+
const nodes = buildComponentGraph3(sidebarItems(components));
|
|
8485
|
+
let cycles;
|
|
8486
|
+
try {
|
|
8487
|
+
cycles = findSlotCycles3(nodes);
|
|
8488
|
+
} catch {
|
|
8489
|
+
cycles = [];
|
|
8490
|
+
}
|
|
8491
|
+
const cycleParticipants = /* @__PURE__ */ new Set();
|
|
8492
|
+
for (const cycle of cycles) for (const name of cycle.path) cycleParticipants.add(name);
|
|
8493
|
+
return {
|
|
8494
|
+
nodes,
|
|
8495
|
+
cycles,
|
|
8496
|
+
cycleParticipants,
|
|
8497
|
+
cycleUnits: buildCycleUnits(cycles),
|
|
8498
|
+
closures: computeAllClosures(nodes)
|
|
8499
|
+
};
|
|
8500
|
+
}
|
|
8501
|
+
function acceptCascade(graph, target) {
|
|
8502
|
+
return [...computeCycleAwareAcceptCascade(target, graph.nodes, graph.cycleUnits)];
|
|
8503
|
+
}
|
|
8504
|
+
function rejectCascade(graph, target) {
|
|
8505
|
+
const { toReject, toDeselect } = computeCycleAwareRejectCascade(target, graph.nodes, graph.cycleUnits);
|
|
8506
|
+
return { toReject: [...toReject], toDeselect: [...toDeselect] };
|
|
8507
|
+
}
|
|
8508
|
+
function reachableCycleMembers(graph, seeds) {
|
|
8509
|
+
return [...collectReachableCycleUnits(seeds, graph.nodes, graph.cycleUnits)];
|
|
8510
|
+
}
|
|
8511
|
+
|
|
8512
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/keymap.ts
|
|
8513
|
+
var NONE = { type: "none" };
|
|
8514
|
+
function resolveKey(mode, key, ctx) {
|
|
8515
|
+
switch (mode) {
|
|
8516
|
+
case "help":
|
|
8517
|
+
return key.input === "h" || key.escape ? { type: "close-help" } : NONE;
|
|
8518
|
+
case "reject-prompt":
|
|
8519
|
+
if (key.input === "y" || key.input === "Y") return { type: "answer-reject-prompt", confirm: true };
|
|
8520
|
+
if (key.input === "n" || key.input === "N" || key.escape) return { type: "answer-reject-prompt", confirm: false };
|
|
8521
|
+
return NONE;
|
|
8522
|
+
case "search":
|
|
8523
|
+
if (key.escape) return { type: "close-search" };
|
|
8524
|
+
if (key.return) return { type: "submit-search" };
|
|
8525
|
+
return { type: "search-input" };
|
|
8526
|
+
case "cycles":
|
|
8527
|
+
if (key.escape || key.input === "c") return { type: "close-panel" };
|
|
8528
|
+
if (key.upArrow) return { type: "move", delta: -1 };
|
|
8529
|
+
if (key.downArrow) return { type: "move", delta: 1 };
|
|
8530
|
+
if (key.return) return { type: "jump-to-selected" };
|
|
8531
|
+
return NONE;
|
|
8532
|
+
case "flags":
|
|
8533
|
+
if (key.upArrow) return { type: "move", delta: -1 };
|
|
8534
|
+
if (key.downArrow) return { type: "move", delta: 1 };
|
|
8535
|
+
if (key.return) return { type: "jump-to-selected" };
|
|
8536
|
+
return NONE;
|
|
8537
|
+
case "main":
|
|
8538
|
+
return resolveMain(key, ctx);
|
|
8539
|
+
}
|
|
8540
|
+
}
|
|
8541
|
+
function resolveMain(key, ctx) {
|
|
8542
|
+
const { input } = key;
|
|
8543
|
+
const inMain = ctx.focusedColumn === "main";
|
|
8544
|
+
if (input === "q" || key.escape) {
|
|
8545
|
+
if (key.escape && ctx.jumpFilterActive) return { type: "clear-jump-filter" };
|
|
8546
|
+
if (key.escape && ctx.searchActive) return { type: "clear-search" };
|
|
8547
|
+
return { type: "quit" };
|
|
8548
|
+
}
|
|
8549
|
+
if (input === "h") return { type: "open-panel", panel: "help" };
|
|
8550
|
+
if (input === "f" || input === "F") return { type: "confirm" };
|
|
8551
|
+
if (input === "c") return ctx.hasCycles ? { type: "open-panel", panel: "cycles" } : NONE;
|
|
8552
|
+
if (input === "d") return { type: "toggle-dependencies" };
|
|
8553
|
+
if (input === "x") return ctx.hasFlagReasons ? { type: "open-panel", panel: "flags" } : NONE;
|
|
8554
|
+
if (input === "/") return { type: "open-panel", panel: "search" };
|
|
8555
|
+
if (input === "o") return ctx.hasCycles ? { type: "toggle-cycle-filter" } : NONE;
|
|
8556
|
+
if (input === "i" && !key.tab && !key.ctrl) return { type: "toggle-jump-filter" };
|
|
8557
|
+
if (input === " ") return inMain ? { type: "toggle-group" } : NONE;
|
|
8558
|
+
if (input === "E") return inMain ? { type: "expand-all" } : NONE;
|
|
8559
|
+
if (input === "C") return inMain ? { type: "collapse-all" } : NONE;
|
|
8560
|
+
if (input === "a") return inMain ? { type: "accept" } : NONE;
|
|
8561
|
+
if (input === "r") return { type: "reject" };
|
|
8562
|
+
if (input === "L") return { type: "toggle-view" };
|
|
8563
|
+
if (input === "A") return { type: "toggle-all" };
|
|
8564
|
+
if (input === "Y") return { type: "accept-unflagged" };
|
|
8565
|
+
if (key.tab) {
|
|
8566
|
+
if (ctx.singleColumn) return NONE;
|
|
8567
|
+
return { type: "switch-column", delta: key.shiftTab ? -1 : 1 };
|
|
8568
|
+
}
|
|
8569
|
+
if (key.return) return inMain ? NONE : { type: "jump-to-selected" };
|
|
8570
|
+
if (key.upArrow) return ctx.focusedListEmpty ? NONE : { type: "move", delta: -1 };
|
|
8571
|
+
if (key.downArrow) return ctx.focusedListEmpty ? NONE : { type: "move", delta: 1 };
|
|
8572
|
+
return NONE;
|
|
8573
|
+
}
|
|
8574
|
+
|
|
8575
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/group-collapse.ts
|
|
8576
|
+
function resolveGroupRoot(key, closures, cycleSet) {
|
|
8577
|
+
if (cycleSet.has(key)) return key;
|
|
8578
|
+
if (closures.has(key)) return key;
|
|
8579
|
+
for (const [root, closure] of closures.entries()) {
|
|
8580
|
+
if (closure.nodes.some((n) => n.name === key)) return root;
|
|
8581
|
+
}
|
|
8582
|
+
return void 0;
|
|
8583
|
+
}
|
|
8584
|
+
|
|
8585
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/sidebar-search-state.ts
|
|
8586
|
+
import { useState as useState10 } from "react";
|
|
8587
|
+
function useSidebarSearchState() {
|
|
8588
|
+
const [searchOpen, setSearchOpen] = useState10(false);
|
|
8589
|
+
const [searchQuery, setSearchQuery] = useState10("");
|
|
8590
|
+
const [autocompleteCandidates, setAutocompleteCandidates] = useState10([]);
|
|
8591
|
+
const [jumpFilterTarget, setJumpFilterTarget] = useState10(null);
|
|
8592
|
+
const [columnOneView, setColumnOneView] = useState10("grouped");
|
|
8593
|
+
const [activeFilters, setActiveFilters] = useState10(/* @__PURE__ */ new Set());
|
|
8594
|
+
const [showHelp, setShowHelp] = useState10(false);
|
|
8595
|
+
return {
|
|
8596
|
+
searchOpen,
|
|
8597
|
+
setSearchOpen,
|
|
8598
|
+
searchQuery,
|
|
8599
|
+
setSearchQuery,
|
|
8600
|
+
autocompleteCandidates,
|
|
8601
|
+
setAutocompleteCandidates,
|
|
8602
|
+
jumpFilterTarget,
|
|
8603
|
+
setJumpFilterTarget,
|
|
8604
|
+
columnOneView,
|
|
8605
|
+
setColumnOneView,
|
|
8606
|
+
activeFilters,
|
|
8607
|
+
setActiveFilters,
|
|
8608
|
+
showHelp,
|
|
8609
|
+
setShowHelp
|
|
8610
|
+
};
|
|
8611
|
+
}
|
|
8612
|
+
|
|
8613
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/useOverlayPanel.ts
|
|
8614
|
+
import { useCallback, useState as useState11 } from "react";
|
|
8615
|
+
function useOverlayPanel(opts) {
|
|
8616
|
+
const { toggleKey, onClose } = opts;
|
|
8617
|
+
const [isOpen, setIsOpen] = useState11(false);
|
|
8618
|
+
const open = useCallback(() => {
|
|
8619
|
+
setIsOpen(true);
|
|
8620
|
+
}, []);
|
|
8621
|
+
const close = useCallback(() => {
|
|
8622
|
+
setIsOpen((prev) => {
|
|
8623
|
+
if (prev && onClose) onClose();
|
|
8624
|
+
return false;
|
|
8625
|
+
});
|
|
8626
|
+
}, [onClose]);
|
|
8627
|
+
const handleInput = useCallback(
|
|
8628
|
+
(input, key) => {
|
|
8629
|
+
if (!isOpen) return false;
|
|
8630
|
+
if (input === toggleKey || key.escape === true) {
|
|
8631
|
+
if (onClose) onClose();
|
|
8632
|
+
setIsOpen(false);
|
|
8633
|
+
return true;
|
|
8634
|
+
}
|
|
8635
|
+
return false;
|
|
8636
|
+
},
|
|
8637
|
+
[isOpen, toggleKey, onClose]
|
|
8638
|
+
);
|
|
8639
|
+
return { isOpen, open, close, handleInput };
|
|
8640
|
+
}
|
|
8641
|
+
|
|
8642
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/lineage-layout.ts
|
|
8643
|
+
var VISIBLE_COUNT = 200;
|
|
8644
|
+
var MAX_PANEL_ROWS = 200;
|
|
8645
|
+
var SIDEBAR_MIN = 4;
|
|
8646
|
+
var MIN_PANEL_ROWS = 4;
|
|
8647
|
+
var FALLBACK_ROWS = 40;
|
|
8648
|
+
var HEADER_ROWS = 2;
|
|
8649
|
+
var COUNTER_STRIP_ROWS = 2;
|
|
8650
|
+
var FOCUSED_DETAIL_ROWS = 2;
|
|
8651
|
+
var LEGEND_ROWS = 3;
|
|
8652
|
+
var FIXED_OVERHEAD = HEADER_ROWS + COUNTER_STRIP_ROWS + FOCUSED_DETAIL_ROWS + LEGEND_ROWS;
|
|
8653
|
+
var PANEL_BOX_CHROME = 6;
|
|
8654
|
+
var BASE_CHROME_OVERHEAD = 18;
|
|
8655
|
+
function clamp(value, min, max) {
|
|
8656
|
+
return Math.max(min, Math.min(max, value));
|
|
8657
|
+
}
|
|
8658
|
+
function computeLineageLayout({ rows, panelOpen, entryCount }) {
|
|
8659
|
+
const sidebarVisible = clamp(rows - BASE_CHROME_OVERHEAD, SIDEBAR_MIN, VISIBLE_COUNT);
|
|
8660
|
+
if (!panelOpen) {
|
|
8661
|
+
return { sidebarVisible, panelMaxRows: MAX_PANEL_ROWS };
|
|
8662
|
+
}
|
|
8663
|
+
const terminalFit = rows - FIXED_OVERHEAD - PANEL_BOX_CHROME;
|
|
8664
|
+
let panelBase = Math.min(MAX_PANEL_ROWS, terminalFit);
|
|
8665
|
+
if (entryCount !== void 0 && entryCount > 0) {
|
|
8666
|
+
panelBase = Math.min(panelBase, entryCount);
|
|
8667
|
+
}
|
|
8668
|
+
const panelMaxRows = clamp(panelBase, MIN_PANEL_ROWS, MAX_PANEL_ROWS);
|
|
8669
|
+
return { sidebarVisible, panelMaxRows };
|
|
8670
|
+
}
|
|
8671
|
+
function computeSidebarBudget({ rows, panelOpen, entryCount }) {
|
|
8672
|
+
const sidebarVisibleCount = clamp(rows - BASE_CHROME_OVERHEAD, SIDEBAR_MIN, VISIBLE_COUNT);
|
|
8673
|
+
const { panelMaxRows } = computeLineageLayout({ rows, panelOpen, entryCount });
|
|
8674
|
+
return { sidebarVisibleCount, panelMaxRows };
|
|
8675
|
+
}
|
|
8676
|
+
|
|
8677
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-navigation.ts
|
|
8678
|
+
function collectExpandedGroupRoots(closures, cycleParticipants) {
|
|
8679
|
+
const roots = /* @__PURE__ */ new Set();
|
|
8680
|
+
for (const [name, closure] of closures.entries()) {
|
|
8681
|
+
if (closure.nodes.length > 1) roots.add(name);
|
|
8682
|
+
}
|
|
8683
|
+
for (const name of cycleParticipants) roots.add(name);
|
|
8684
|
+
return roots;
|
|
8685
|
+
}
|
|
8686
|
+
function computeSidebarViewToggle({
|
|
8687
|
+
currentView,
|
|
8688
|
+
currentKey,
|
|
8689
|
+
currentScroll,
|
|
8690
|
+
visibleCount,
|
|
8691
|
+
items,
|
|
8692
|
+
cycleParticipants,
|
|
8693
|
+
expandedGroups,
|
|
8694
|
+
graph,
|
|
8695
|
+
showFlatTier = false
|
|
8696
|
+
}) {
|
|
8697
|
+
const view = currentView === "grouped" ? "flat" : "grouped";
|
|
8698
|
+
const rows = buildVisibleRows({
|
|
8699
|
+
items,
|
|
8700
|
+
cycleParticipants,
|
|
8701
|
+
expandedGroups,
|
|
8702
|
+
showFlatTier,
|
|
8703
|
+
viewMode: view,
|
|
8704
|
+
graph
|
|
8705
|
+
});
|
|
8706
|
+
let cursor = 0;
|
|
8707
|
+
if (currentKey) {
|
|
8708
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8709
|
+
const row = rows[i];
|
|
8710
|
+
if (row.itemIdx < 0) continue;
|
|
8711
|
+
if (items[row.itemIdx]?.key === currentKey) {
|
|
8712
|
+
cursor = i;
|
|
8713
|
+
break;
|
|
8714
|
+
}
|
|
8715
|
+
}
|
|
8716
|
+
}
|
|
8717
|
+
const scroll = cursor < currentScroll ? cursor : cursor >= currentScroll + visibleCount ? cursor - visibleCount + 1 : currentScroll;
|
|
8718
|
+
return { view, cursor, scroll };
|
|
8719
|
+
}
|
|
8720
|
+
|
|
8721
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/step-filters.ts
|
|
8722
|
+
function computeFilterKeys(input) {
|
|
8723
|
+
const active = new Set(input.filters);
|
|
8724
|
+
if (active.size === 0) return void 0;
|
|
8725
|
+
const out = /* @__PURE__ */ new Set();
|
|
8726
|
+
if (active.has("cycles")) for (const k of input.data.cycles ?? []) out.add(k);
|
|
8727
|
+
if (active.has("broken")) for (const k of input.data.broken ?? []) out.add(k);
|
|
8728
|
+
if (active.has("deleted")) for (const k of input.data.deleted ?? []) out.add(k);
|
|
8729
|
+
return out;
|
|
8730
|
+
}
|
|
8731
|
+
function intersectFilterKeys(a, b) {
|
|
8732
|
+
if (a === void 0) return b;
|
|
8733
|
+
if (b === void 0) return a;
|
|
8734
|
+
const out = /* @__PURE__ */ new Set();
|
|
8735
|
+
for (const k of a) if (b.has(k)) out.add(k);
|
|
8736
|
+
return out;
|
|
8737
|
+
}
|
|
8738
|
+
function buildFlatDimPredicate(input) {
|
|
8739
|
+
const hasSearch = input.searchQuery.length > 0;
|
|
8740
|
+
const isFlat = input.viewMode === "flat";
|
|
8741
|
+
const keys = isFlat ? input.filterVisibleKeys : void 0;
|
|
8742
|
+
if (!hasSearch && keys === void 0) return void 0;
|
|
8743
|
+
return (name) => {
|
|
8744
|
+
if (hasSearch && !fuzzyMatches(input.searchQuery, name)) return true;
|
|
8745
|
+
if (keys !== void 0 && !keys.has(name)) return true;
|
|
8746
|
+
return false;
|
|
8747
|
+
};
|
|
8748
|
+
}
|
|
8749
|
+
|
|
8750
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/state.ts
|
|
8751
|
+
function apply(state, entries) {
|
|
8752
|
+
const next = new Map(state);
|
|
8753
|
+
for (const [name, decision] of entries) next.set(name, decision);
|
|
8754
|
+
return next;
|
|
8755
|
+
}
|
|
8756
|
+
function reduceDecisions(state, action, components, graph) {
|
|
8757
|
+
switch (action.type) {
|
|
8758
|
+
case "accept": {
|
|
8759
|
+
if (state.get(action.name) === "accepted") return state;
|
|
8760
|
+
return apply(
|
|
8761
|
+
state,
|
|
8762
|
+
acceptCascade(graph, action.name).map((name) => [name, "accepted"])
|
|
8763
|
+
);
|
|
8764
|
+
}
|
|
8765
|
+
case "reject": {
|
|
8766
|
+
if (state.get(action.name) === "rejected") return state;
|
|
8767
|
+
const { toReject, toDeselect } = rejectCascade(graph, action.name);
|
|
8768
|
+
return apply(state, [
|
|
8769
|
+
...toReject.map((name) => [name, "rejected"]),
|
|
8770
|
+
...toDeselect.map((name) => [name, "undecided"])
|
|
8771
|
+
]);
|
|
8772
|
+
}
|
|
8773
|
+
case "toggle-all": {
|
|
8774
|
+
const nonCycle = components.filter((c2) => !graph.cycleParticipants.has(c2.name)).map((c2) => c2.name);
|
|
8775
|
+
const anyNotAccepted = nonCycle.some((name) => state.get(name) !== "accepted");
|
|
8776
|
+
if (anyNotAccepted) {
|
|
8777
|
+
return apply(state, [
|
|
8778
|
+
...nonCycle.map((name) => [name, "accepted"]),
|
|
8779
|
+
...reachableCycleMembers(graph, nonCycle).map((name) => [name, "accepted"])
|
|
8780
|
+
]);
|
|
8781
|
+
}
|
|
8782
|
+
return apply(state, [
|
|
8783
|
+
...nonCycle.map((name) => [name, "rejected"]),
|
|
8784
|
+
...components.filter((c2) => graph.cycleParticipants.has(c2.name) && state.get(c2.name) === "accepted").map((c2) => [c2.name, "undecided"])
|
|
8785
|
+
]);
|
|
8786
|
+
}
|
|
8787
|
+
case "accept-unflagged": {
|
|
8788
|
+
const seeds = components.filter((c2) => !graph.cycleParticipants.has(c2.name) && !isAiFlagged(c2)).map((c2) => c2.name);
|
|
8789
|
+
return apply(state, [
|
|
8790
|
+
...seeds.map((name) => [name, "accepted"]),
|
|
8791
|
+
...reachableCycleMembers(graph, seeds).map((name) => [name, "accepted"])
|
|
8792
|
+
]);
|
|
8793
|
+
}
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
function rejectNeedsConfirmation(graph, name, state) {
|
|
8797
|
+
if (state.get(name) === "rejected") return false;
|
|
8798
|
+
const { toReject, toDeselect } = rejectCascade(graph, name);
|
|
8799
|
+
const ancestors = toReject.filter((n) => n !== name);
|
|
8800
|
+
return ancestors.length + toDeselect.length >= 2;
|
|
8801
|
+
}
|
|
8802
|
+
function partitionDecisions(components, state) {
|
|
8803
|
+
const accepted = [];
|
|
8804
|
+
const rejected = [];
|
|
8805
|
+
for (const c2 of components) {
|
|
8806
|
+
if (state.get(c2.name) === "accepted") accepted.push(c2.name);
|
|
8807
|
+
else rejected.push(c2.name);
|
|
8808
|
+
}
|
|
8809
|
+
return { accepted, rejected };
|
|
8810
|
+
}
|
|
8811
|
+
|
|
8812
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
|
|
8813
|
+
function useScopeGate({ components, onConfirm, onQuit }) {
|
|
8814
|
+
const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
|
|
8815
|
+
const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
|
|
8816
|
+
const [decisions, setDecisions] = useState12(/* @__PURE__ */ new Map());
|
|
8817
|
+
const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
|
|
8818
|
+
const [focusedColumn, setFocusedColumn] = useState12("main");
|
|
8819
|
+
const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
|
|
8820
|
+
const [showDependencies, setShowDependencies] = useState12(false);
|
|
8821
|
+
const [cyclesPanelOpen, setCyclesPanelOpen] = useState12(false);
|
|
8822
|
+
const [cyclesCursor, setCyclesCursor] = useState12(0);
|
|
8823
|
+
const aiRationalePanel = useOverlayPanel({ toggleKey: "x" });
|
|
8824
|
+
const [aiCursor, setAiCursor] = useState12(0);
|
|
8825
|
+
const [pendingRejectCascade, setPendingRejectCascade] = useState12(null);
|
|
8826
|
+
const search = useSidebarSearchState();
|
|
8827
|
+
const {
|
|
8828
|
+
searchOpen,
|
|
8829
|
+
setSearchOpen,
|
|
8830
|
+
searchQuery,
|
|
8831
|
+
setSearchQuery,
|
|
8832
|
+
setAutocompleteCandidates,
|
|
8833
|
+
jumpFilterTarget,
|
|
8834
|
+
setJumpFilterTarget,
|
|
8835
|
+
columnOneView,
|
|
8836
|
+
setColumnOneView,
|
|
8837
|
+
activeFilters,
|
|
8838
|
+
setActiveFilters,
|
|
8839
|
+
showHelp,
|
|
8840
|
+
setShowHelp
|
|
8841
|
+
} = search;
|
|
8842
|
+
const groupedItems = useMemo2(() => sidebarItems(components), [components]);
|
|
8843
|
+
const graph = useMemo2(() => buildScopeGraph(components), [components]);
|
|
8844
|
+
const { cycles: slotCycles, cycleParticipants, cycleUnits, closures } = graph;
|
|
8845
|
+
const hasCycles = slotCycles.length > 0;
|
|
8846
|
+
const cyclesJumpables = useMemo2(
|
|
8847
|
+
() => slotCycles.map((c2, i) => ({ cycleIndex: i, jumpTarget: c2.path[0] })),
|
|
8848
|
+
[slotCycles]
|
|
8849
|
+
);
|
|
8850
|
+
const [expandedGroups, setExpandedGroups] = useState12(() => {
|
|
8851
|
+
const seed = new Set(closures.keys());
|
|
8852
|
+
for (const p of cycleParticipants) seed.add(p);
|
|
8853
|
+
return seed;
|
|
8854
|
+
});
|
|
8855
|
+
const seededGroupsRef = useRef4(closures.size > 0 || cycleParticipants.size > 0);
|
|
8856
|
+
useEffect7(() => {
|
|
8857
|
+
if (seededGroupsRef.current) return;
|
|
8858
|
+
if (closures.size === 0 && cycleParticipants.size === 0) return;
|
|
8859
|
+
seededGroupsRef.current = true;
|
|
8860
|
+
const seed = new Set(closures.keys());
|
|
8861
|
+
for (const p of cycleParticipants) seed.add(p);
|
|
8862
|
+
setExpandedGroups(seed);
|
|
8863
|
+
}, [closures, cycleParticipants]);
|
|
8864
|
+
const hasGroupRoots = useMemo2(() => {
|
|
8865
|
+
if (cycleParticipants.size > 0) return true;
|
|
8866
|
+
for (const c2 of closures.values()) if (c2.nodes.length > 1) return true;
|
|
8867
|
+
return false;
|
|
8868
|
+
}, [closures, cycleParticipants]);
|
|
8869
|
+
const toggleExpanded = (rootName) => {
|
|
8870
|
+
setExpandedGroups((prev) => {
|
|
8871
|
+
const next = new Set(prev);
|
|
8872
|
+
if (next.has(rootName)) next.delete(rootName);
|
|
8873
|
+
else next.add(rootName);
|
|
8874
|
+
return next;
|
|
8875
|
+
});
|
|
8876
|
+
};
|
|
8877
|
+
const brokenKeys = useMemo2(() => new Set(components.filter(isAiFlagged).map((c2) => c2.name)), [components]);
|
|
8878
|
+
const dependencyFilterKeys = useMemo2(() => {
|
|
8879
|
+
if (!showDependencies) return void 0;
|
|
8880
|
+
const keys = /* @__PURE__ */ new Set();
|
|
8881
|
+
for (const [root, closure] of closures) {
|
|
8882
|
+
if (closure.nodes.length <= 1 || decisions.get(root) !== "accepted") continue;
|
|
8883
|
+
for (const node of closure.nodes) keys.add(node.name);
|
|
8884
|
+
}
|
|
8885
|
+
for (const unit of cycleUnits.values()) {
|
|
8886
|
+
if (![...unit].some((name) => decisions.get(name) === "accepted")) continue;
|
|
8887
|
+
for (const name of unit) keys.add(name);
|
|
8888
|
+
}
|
|
8889
|
+
return keys;
|
|
8890
|
+
}, [closures, cycleUnits, showDependencies, decisions]);
|
|
8891
|
+
const filterVisibleKeys = useMemo2(() => {
|
|
8892
|
+
if (jumpFilterTarget) return findAllAncestors(jumpFilterTarget, graph.nodes);
|
|
8893
|
+
const categoryKeys = computeFilterKeys({
|
|
8894
|
+
filters: activeFilters,
|
|
8895
|
+
data: { cycles: cycleParticipants, broken: brokenKeys }
|
|
8896
|
+
});
|
|
8897
|
+
const searchKeys = (() => {
|
|
8898
|
+
if (!searchQuery) return void 0;
|
|
8899
|
+
const matches = groupedItems.map((it) => it.key).filter((k) => fuzzyMatches(searchQuery, k));
|
|
8900
|
+
if (matches.length === 0) return void 0;
|
|
8901
|
+
return computeDirectNeighborhood(matches, graph.nodes);
|
|
8902
|
+
})();
|
|
8903
|
+
return intersectFilterKeys(intersectFilterKeys(categoryKeys, searchKeys), dependencyFilterKeys);
|
|
8904
|
+
}, [
|
|
8905
|
+
jumpFilterTarget,
|
|
8906
|
+
activeFilters,
|
|
8907
|
+
cycleParticipants,
|
|
8908
|
+
brokenKeys,
|
|
8909
|
+
searchQuery,
|
|
8910
|
+
groupedItems,
|
|
8911
|
+
graph,
|
|
8912
|
+
dependencyFilterKeys
|
|
8913
|
+
]);
|
|
8914
|
+
const visibleRows = useMemo2(
|
|
8915
|
+
() => buildVisibleRows({
|
|
8916
|
+
items: groupedItems,
|
|
8917
|
+
cycleParticipants,
|
|
8918
|
+
expandedGroups,
|
|
8919
|
+
showFlatTier: false,
|
|
8920
|
+
viewMode: columnOneView,
|
|
8921
|
+
graph: graph.nodes,
|
|
8922
|
+
filterVisibleKeys
|
|
8923
|
+
}),
|
|
8924
|
+
[groupedItems, cycleParticipants, expandedGroups, columnOneView, graph, filterVisibleKeys]
|
|
8925
|
+
);
|
|
8926
|
+
const total = visibleRows.length;
|
|
8927
|
+
const safeCursor = Math.min(nav.cursor, Math.max(0, total - 1));
|
|
8928
|
+
const currentRow = visibleRows[safeCursor];
|
|
8929
|
+
const currentRowKey = currentRow && currentRow.itemIdx >= 0 ? groupedItems[currentRow.itemIdx]?.key : void 0;
|
|
8930
|
+
const selectionStateByKey = useMemo2(() => {
|
|
8931
|
+
const map = /* @__PURE__ */ new Map();
|
|
8932
|
+
for (const c2 of components) map.set(c2.name, decisions.get(c2.name) ?? "undecided");
|
|
8933
|
+
return map;
|
|
8934
|
+
}, [components, decisions]);
|
|
8935
|
+
const aiFlaggedByKey = useMemo2(() => new Map(components.map((c2) => [c2.name, isAiFlagged(c2)])), [components]);
|
|
8936
|
+
const dimPredicate = useMemo2(
|
|
8937
|
+
() => buildFlatDimPredicate({ viewMode: columnOneView, searchQuery, filterVisibleKeys }),
|
|
8938
|
+
[columnOneView, searchQuery, filterVisibleKeys]
|
|
8939
|
+
);
|
|
8940
|
+
const { sidebarVisibleCount: visibleCount, panelMaxRows } = computeSidebarBudget({
|
|
8941
|
+
rows: terminalRows || FALLBACK_ROWS,
|
|
8942
|
+
panelOpen: false,
|
|
8943
|
+
entryCount: 0
|
|
8944
|
+
});
|
|
8945
|
+
const panelLayout = useMemo2(() => computePanelLayout(visibleCount), [visibleCount]);
|
|
8946
|
+
useEffect7(() => {
|
|
8947
|
+
setNav((prev) => {
|
|
8948
|
+
const maxIdx = Math.max(0, visibleRows.length - 1);
|
|
8949
|
+
const nextCursor = Math.min(prev.cursor, maxIdx);
|
|
8950
|
+
const nextScroll = Math.min(prev.scrollOffset, maxIdx);
|
|
8951
|
+
if (nextCursor === prev.cursor && nextScroll === prev.scrollOffset) return prev;
|
|
8952
|
+
return { cursor: nextCursor, scrollOffset: nextScroll };
|
|
8953
|
+
});
|
|
8954
|
+
}, [visibleRows]);
|
|
8955
|
+
const searchMatches = useMemo2(() => {
|
|
8956
|
+
if (!searchQuery) return [];
|
|
8957
|
+
return components.filter((c2) => fuzzyMatches(searchQuery, c2.name)).map((c2) => c2.name);
|
|
8958
|
+
}, [components, searchQuery]);
|
|
8959
|
+
const aiExcluded = components.filter(isAiFlagged);
|
|
8960
|
+
const aiRows = useMemo2(
|
|
8961
|
+
() => aiExcluded.filter((c2) => c2.aiReason !== null && c2.aiReason !== void 0 && c2.aiReason !== "").map((c2) => ({ label: `${c2.name} \u2014 ${c2.aiReason}`, jumpTarget: c2.name })),
|
|
8962
|
+
[aiExcluded]
|
|
8963
|
+
);
|
|
8964
|
+
const addedComponents = useMemo2(
|
|
8965
|
+
() => buildAddedComponentsList(components, selectionStateByKey, cycleParticipants),
|
|
8966
|
+
[components, selectionStateByKey, cycleParticipants]
|
|
8967
|
+
);
|
|
8968
|
+
const counters = useMemo2(
|
|
8969
|
+
() => computeCounters(components, closures, selectionStateByKey),
|
|
8970
|
+
[components, closures, selectionStateByKey]
|
|
8971
|
+
);
|
|
8972
|
+
const safeAddedComponentsCursor = Math.min(addedComponentsCursor, Math.max(0, addedComponents.length - 1));
|
|
8973
|
+
const focusedRowKey = () => {
|
|
8974
|
+
const row = visibleRows[safeCursor];
|
|
8975
|
+
if (!row) return void 0;
|
|
8976
|
+
switch (row.kind) {
|
|
8977
|
+
case "standalone":
|
|
8978
|
+
case "empty":
|
|
8979
|
+
case "group-root":
|
|
8980
|
+
case "group-child":
|
|
8981
|
+
case "flat":
|
|
8982
|
+
case "cycle":
|
|
8983
|
+
return row.itemIdx >= 0 ? groupedItems[row.itemIdx]?.key : void 0;
|
|
8984
|
+
default:
|
|
8985
|
+
return void 0;
|
|
8986
|
+
}
|
|
8987
|
+
};
|
|
8988
|
+
const jumpCursorTo = (name) => {
|
|
8989
|
+
let idx = -1;
|
|
8990
|
+
for (let i = 0; i < visibleRows.length; i++) {
|
|
8991
|
+
const row = visibleRows[i];
|
|
8992
|
+
if (row.itemIdx < 0) continue;
|
|
8993
|
+
if (groupedItems[row.itemIdx]?.key === name) {
|
|
8994
|
+
idx = i;
|
|
8995
|
+
break;
|
|
8996
|
+
}
|
|
8997
|
+
}
|
|
8998
|
+
if (idx < 0) return;
|
|
8999
|
+
setNav(({ scrollOffset: prev }) => {
|
|
9000
|
+
let nextScroll = prev;
|
|
9001
|
+
if (idx < prev) nextScroll = idx;
|
|
9002
|
+
else if (idx >= prev + visibleCount) nextScroll = idx - visibleCount + 1;
|
|
9003
|
+
return { cursor: idx, scrollOffset: nextScroll };
|
|
9004
|
+
});
|
|
9005
|
+
};
|
|
9006
|
+
const decide = (action) => setDecisions((prev) => reduceDecisions(prev, action, components, graph));
|
|
9007
|
+
const requestReject = (name) => {
|
|
9008
|
+
if (decisions.get(name) === "rejected") return;
|
|
9009
|
+
if (rejectNeedsConfirmation(graph, name, decisions)) {
|
|
9010
|
+
const { toReject, toDeselect } = rejectCascade(graph, name);
|
|
9011
|
+
setPendingRejectCascade({
|
|
9012
|
+
target: name,
|
|
9013
|
+
ancestors: toReject.filter((n) => n !== name).sort(),
|
|
9014
|
+
descendants: [...toDeselect].sort()
|
|
9015
|
+
});
|
|
9016
|
+
return;
|
|
9017
|
+
}
|
|
9018
|
+
decide({ type: "reject", name });
|
|
9019
|
+
};
|
|
9020
|
+
const mode = showHelp ? "help" : pendingRejectCascade ? "reject-prompt" : searchOpen ? "search" : cyclesPanelOpen ? "cycles" : aiRationalePanel.isOpen ? "flags" : "main";
|
|
9021
|
+
const context = {
|
|
9022
|
+
focusedColumn,
|
|
9023
|
+
singleColumn: columnPlan.layout === "single",
|
|
9024
|
+
hasCycles,
|
|
9025
|
+
hasFlagReasons: aiRows.length > 0,
|
|
9026
|
+
jumpFilterActive: jumpFilterTarget !== null,
|
|
9027
|
+
searchActive: searchQuery.length > 0,
|
|
9028
|
+
focusedListEmpty: focusedColumn === "added-components" ? addedComponents.length === 0 : total === 0
|
|
9029
|
+
};
|
|
9030
|
+
const submitSearch = () => {
|
|
9031
|
+
const closeSearch = () => {
|
|
9032
|
+
setSearchOpen(false);
|
|
9033
|
+
setSearchQuery("");
|
|
9034
|
+
setAutocompleteCandidates([]);
|
|
9035
|
+
};
|
|
9036
|
+
if (!searchQuery || searchMatches.length === 0) {
|
|
9037
|
+
closeSearch();
|
|
9038
|
+
return;
|
|
9039
|
+
}
|
|
9040
|
+
const cursorName = currentRow && currentRow.itemIdx >= 0 ? groupedItems[currentRow.itemIdx]?.key : void 0;
|
|
9041
|
+
const rowName = (i) => {
|
|
9042
|
+
const r = visibleRows[i];
|
|
9043
|
+
return r && r.itemIdx >= 0 ? groupedItems[r.itemIdx]?.key : void 0;
|
|
9044
|
+
};
|
|
9045
|
+
let target;
|
|
9046
|
+
for (let i = safeCursor; i < visibleRows.length && !target; i++) {
|
|
9047
|
+
const n = rowName(i);
|
|
9048
|
+
if (n && n !== cursorName && fuzzyMatches(searchQuery, n)) target = n;
|
|
9049
|
+
}
|
|
9050
|
+
for (let i = 0; i < visibleRows.length && !target; i++) {
|
|
9051
|
+
const n = rowName(i);
|
|
9052
|
+
if (n && fuzzyMatches(searchQuery, n)) target = n;
|
|
9053
|
+
}
|
|
9054
|
+
if (target) jumpCursorTo(target);
|
|
9055
|
+
setSearchOpen(false);
|
|
9056
|
+
};
|
|
9057
|
+
const move = (delta) => {
|
|
9058
|
+
if (mode === "cycles") {
|
|
9059
|
+
setCyclesCursor((c2) => Math.max(0, Math.min(Math.max(0, cyclesJumpables.length - 1), c2 + delta)));
|
|
9060
|
+
return;
|
|
9061
|
+
}
|
|
9062
|
+
if (mode === "flags") {
|
|
9063
|
+
setAiCursor((c2) => Math.max(0, Math.min(Math.max(0, aiRows.length - 1), c2 + delta)));
|
|
9064
|
+
return;
|
|
9065
|
+
}
|
|
9066
|
+
if (focusedColumn === "added-components") {
|
|
9067
|
+
setAddedComponentsCursor((c2) => Math.max(0, Math.min(addedComponents.length - 1, c2 + delta)));
|
|
9068
|
+
return;
|
|
9069
|
+
}
|
|
9070
|
+
setNav(({ cursor: c2, scrollOffset: prev }) => {
|
|
9071
|
+
if (delta < 0) {
|
|
9072
|
+
const next2 = c2 <= 0 ? 0 : c2 - 1;
|
|
9073
|
+
return { cursor: next2, scrollOffset: Math.min(prev, next2) };
|
|
9074
|
+
}
|
|
9075
|
+
const next = c2 >= total - 1 ? total - 1 : c2 + 1;
|
|
9076
|
+
return { cursor: next, scrollOffset: next >= prev + visibleCount ? next - visibleCount + 1 : prev };
|
|
9077
|
+
});
|
|
9078
|
+
};
|
|
9079
|
+
const perform = (action) => {
|
|
9080
|
+
switch (action.type) {
|
|
9081
|
+
case "none":
|
|
9082
|
+
return;
|
|
9083
|
+
case "quit":
|
|
9084
|
+
onQuit();
|
|
9085
|
+
return;
|
|
9086
|
+
case "confirm":
|
|
9087
|
+
onConfirm(partitionDecisions(components, decisions));
|
|
9088
|
+
return;
|
|
9089
|
+
case "close-help":
|
|
9090
|
+
setShowHelp(false);
|
|
9091
|
+
return;
|
|
9092
|
+
case "answer-reject-prompt":
|
|
9093
|
+
if (action.confirm && pendingRejectCascade) decide({ type: "reject", name: pendingRejectCascade.target });
|
|
9094
|
+
setPendingRejectCascade(null);
|
|
9095
|
+
return;
|
|
9096
|
+
case "close-panel":
|
|
9097
|
+
setCyclesPanelOpen(false);
|
|
9098
|
+
return;
|
|
9099
|
+
case "close-search":
|
|
9100
|
+
setSearchOpen(false);
|
|
9101
|
+
setSearchQuery("");
|
|
9102
|
+
setAutocompleteCandidates([]);
|
|
9103
|
+
return;
|
|
9104
|
+
case "submit-search":
|
|
9105
|
+
submitSearch();
|
|
9106
|
+
return;
|
|
9107
|
+
case "search-input":
|
|
9108
|
+
return;
|
|
9109
|
+
case "clear-jump-filter":
|
|
9110
|
+
setJumpFilterTarget(null);
|
|
9111
|
+
return;
|
|
9112
|
+
case "clear-search":
|
|
9113
|
+
setSearchQuery("");
|
|
9114
|
+
setAutocompleteCandidates([]);
|
|
9115
|
+
return;
|
|
9116
|
+
case "move":
|
|
9117
|
+
move(action.delta);
|
|
9118
|
+
return;
|
|
9119
|
+
case "jump-to-selected":
|
|
9120
|
+
if (mode === "cycles") {
|
|
9121
|
+
const target = cyclesJumpables[cyclesCursor];
|
|
9122
|
+
if (target) jumpCursorTo(target.jumpTarget);
|
|
9123
|
+
setCyclesPanelOpen(false);
|
|
9124
|
+
} else if (mode === "flags") {
|
|
9125
|
+
const row = aiRows[aiCursor];
|
|
9126
|
+
if (row) jumpCursorTo(row.jumpTarget);
|
|
9127
|
+
aiRationalePanel.close();
|
|
9128
|
+
} else {
|
|
9129
|
+
const entry = addedComponents[safeAddedComponentsCursor];
|
|
9130
|
+
if (entry) jumpCursorTo(entry.name);
|
|
9131
|
+
setFocusedColumn("main");
|
|
9132
|
+
}
|
|
9133
|
+
return;
|
|
9134
|
+
case "accept": {
|
|
9135
|
+
const key = focusedRowKey();
|
|
9136
|
+
if (key) decide({ type: "accept", name: key });
|
|
9137
|
+
return;
|
|
9138
|
+
}
|
|
9139
|
+
case "reject": {
|
|
9140
|
+
const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
|
|
9141
|
+
if (key) requestReject(key);
|
|
9142
|
+
return;
|
|
9143
|
+
}
|
|
9144
|
+
case "toggle-all":
|
|
9145
|
+
decide({ type: "toggle-all" });
|
|
9146
|
+
return;
|
|
9147
|
+
case "accept-unflagged":
|
|
9148
|
+
decide({ type: "accept-unflagged" });
|
|
9149
|
+
return;
|
|
9150
|
+
case "toggle-group": {
|
|
9151
|
+
const key = focusedRowKey();
|
|
9152
|
+
const rootName = key ? resolveGroupRoot(key, closures, cycleParticipants) : void 0;
|
|
9153
|
+
if (rootName) toggleExpanded(rootName);
|
|
9154
|
+
return;
|
|
9155
|
+
}
|
|
9156
|
+
case "expand-all":
|
|
9157
|
+
setExpandedGroups(collectExpandedGroupRoots(closures, cycleParticipants));
|
|
9158
|
+
return;
|
|
9159
|
+
case "collapse-all":
|
|
9160
|
+
setExpandedGroups(/* @__PURE__ */ new Set());
|
|
9161
|
+
return;
|
|
9162
|
+
case "switch-column": {
|
|
9163
|
+
const order = ["main", "added-components"];
|
|
9164
|
+
const at = order.indexOf(focusedColumn);
|
|
9165
|
+
setFocusedColumn(order[(at + action.delta + order.length) % order.length]);
|
|
9166
|
+
return;
|
|
9167
|
+
}
|
|
9168
|
+
case "open-panel":
|
|
9169
|
+
if (action.panel === "help") setShowHelp(true);
|
|
9170
|
+
else if (action.panel === "search") setSearchOpen(true);
|
|
9171
|
+
else if (action.panel === "cycles") {
|
|
9172
|
+
setCyclesPanelOpen(true);
|
|
9173
|
+
setCyclesCursor(0);
|
|
9174
|
+
aiRationalePanel.close();
|
|
9175
|
+
} else {
|
|
9176
|
+
aiRationalePanel.open();
|
|
9177
|
+
setAiCursor(0);
|
|
9178
|
+
setCyclesPanelOpen(false);
|
|
9179
|
+
}
|
|
9180
|
+
return;
|
|
9181
|
+
case "toggle-dependencies":
|
|
9182
|
+
setShowDependencies((current) => !current);
|
|
9183
|
+
setNav({ cursor: 0, scrollOffset: 0 });
|
|
9184
|
+
return;
|
|
9185
|
+
case "toggle-cycle-filter":
|
|
9186
|
+
setActiveFilters((prev) => {
|
|
9187
|
+
const next = new Set(prev);
|
|
9188
|
+
if (next.has("cycles")) next.delete("cycles");
|
|
9189
|
+
else next.add("cycles");
|
|
9190
|
+
return next;
|
|
9191
|
+
});
|
|
9192
|
+
return;
|
|
9193
|
+
case "toggle-jump-filter": {
|
|
9194
|
+
const target = focusedColumn === "main" ? focusedRowKey() : addedComponents[safeAddedComponentsCursor]?.name;
|
|
9195
|
+
if (target) setJumpFilterTarget((prev) => prev === target ? null : target);
|
|
9196
|
+
return;
|
|
9197
|
+
}
|
|
9198
|
+
case "toggle-view": {
|
|
9199
|
+
const next = computeSidebarViewToggle({
|
|
9200
|
+
currentView: columnOneView,
|
|
9201
|
+
currentKey: currentRowKey,
|
|
9202
|
+
currentScroll: nav.scrollOffset,
|
|
9203
|
+
visibleCount,
|
|
9204
|
+
items: groupedItems,
|
|
9205
|
+
cycleParticipants,
|
|
9206
|
+
expandedGroups,
|
|
9207
|
+
graph: graph.nodes
|
|
9208
|
+
});
|
|
9209
|
+
setColumnOneView(next.view);
|
|
9210
|
+
setNav({ cursor: next.cursor, scrollOffset: next.scroll });
|
|
9211
|
+
return;
|
|
9212
|
+
}
|
|
9213
|
+
}
|
|
9214
|
+
};
|
|
9215
|
+
useImmediateInput((input, key) => {
|
|
9216
|
+
if (mode === "flags" && aiRationalePanel.handleInput(input, key)) return;
|
|
9217
|
+
if (mode === "search") {
|
|
9218
|
+
const action = resolveKey(mode, { input, ...key }, context);
|
|
9219
|
+
if (action.type === "search-input") {
|
|
9220
|
+
handleSidebarSearchInput(input, key, {
|
|
9221
|
+
query: searchQuery,
|
|
9222
|
+
names: components.map((c2) => c2.name),
|
|
9223
|
+
setQuery: setSearchQuery,
|
|
9224
|
+
setCandidates: setAutocompleteCandidates
|
|
9225
|
+
});
|
|
9226
|
+
return;
|
|
9227
|
+
}
|
|
9228
|
+
perform(action);
|
|
9229
|
+
return;
|
|
9230
|
+
}
|
|
9231
|
+
perform(resolveKey(mode, { input, ...key }, context));
|
|
9232
|
+
});
|
|
9233
|
+
return {
|
|
9234
|
+
// layout
|
|
9235
|
+
totalWidth,
|
|
9236
|
+
columnPlan,
|
|
9237
|
+
panelLayout,
|
|
9238
|
+
visibleCount,
|
|
9239
|
+
panelMaxRows,
|
|
9240
|
+
// sidebar
|
|
9241
|
+
groupedItems,
|
|
9242
|
+
graph,
|
|
9243
|
+
hasGroupRoots,
|
|
9244
|
+
expandedGroups,
|
|
9245
|
+
toggleExpanded,
|
|
9246
|
+
visibleRows,
|
|
9247
|
+
safeCursor,
|
|
9248
|
+
scrollOffset: nav.scrollOffset,
|
|
9249
|
+
selectionStateByKey,
|
|
9250
|
+
aiFlaggedByKey,
|
|
9251
|
+
dimPredicate,
|
|
9252
|
+
columnOneView,
|
|
9253
|
+
focusedColumn,
|
|
9254
|
+
// panels
|
|
9255
|
+
showHelp,
|
|
9256
|
+
closeHelp: () => setShowHelp(false),
|
|
9257
|
+
cyclesPanelOpen,
|
|
9258
|
+
cyclesCursor,
|
|
9259
|
+
slotCycles,
|
|
9260
|
+
aiRationalePanelOpen: aiRationalePanel.isOpen,
|
|
9261
|
+
aiCursor,
|
|
9262
|
+
aiRows,
|
|
9263
|
+
aiExcludedCount: aiExcluded.length,
|
|
9264
|
+
pendingRejectCascade,
|
|
9265
|
+
// added column
|
|
9266
|
+
addedComponents,
|
|
9267
|
+
safeAddedComponentsCursor,
|
|
9268
|
+
counters,
|
|
9269
|
+
// search
|
|
9270
|
+
search,
|
|
9271
|
+
searchMatches
|
|
9272
|
+
};
|
|
9273
|
+
}
|
|
9274
|
+
|
|
9275
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
|
|
9276
|
+
import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
9277
|
+
var HELP_SECTIONS = [
|
|
9278
|
+
{
|
|
9279
|
+
title: "Navigation",
|
|
9280
|
+
entries: [
|
|
9281
|
+
{ keys: "\u2191 / \u2193", label: "Move cursor" },
|
|
9282
|
+
{ keys: "Tab / Shift-Tab", label: "Switch column" },
|
|
9283
|
+
{ keys: "Enter", label: "Jump to row in main column" }
|
|
9284
|
+
]
|
|
9285
|
+
},
|
|
9286
|
+
{
|
|
9287
|
+
title: "Selection",
|
|
9288
|
+
entries: [
|
|
9289
|
+
{ keys: "a", label: "Accept" },
|
|
9290
|
+
{ keys: "r", label: "Reject" },
|
|
9291
|
+
{ keys: "A", label: "Toggle all" },
|
|
9292
|
+
{ keys: "Y", label: "Accept non-flagged" }
|
|
9293
|
+
]
|
|
9294
|
+
},
|
|
9295
|
+
createSidebarViewsHelpSection(false),
|
|
9296
|
+
{
|
|
9297
|
+
title: "Panels",
|
|
9298
|
+
entries: [
|
|
9299
|
+
{ keys: "c", label: "Cycle list" },
|
|
9300
|
+
{ keys: "d", label: "Show slot dependencies in main list" },
|
|
9301
|
+
{ keys: "x", label: "Review flags" }
|
|
9302
|
+
]
|
|
9303
|
+
},
|
|
9304
|
+
{ title: "Search", entries: [{ keys: "/", label: "Search" }] },
|
|
9305
|
+
{
|
|
9306
|
+
title: "General",
|
|
9307
|
+
entries: [
|
|
9308
|
+
{ keys: "f", label: "Continue" },
|
|
9309
|
+
{ keys: "h", label: "Close help" },
|
|
9310
|
+
{ keys: "q", label: "Quit" }
|
|
9311
|
+
]
|
|
9312
|
+
}
|
|
9313
|
+
];
|
|
9314
|
+
function ScopeGateScreen(props) {
|
|
9315
|
+
if (props.components.length === 0) {
|
|
9316
|
+
return /* @__PURE__ */ jsx24(Box20, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.error, children: "Error: no components found for this session \u2014 please re-run analyze extract." }) });
|
|
9317
|
+
}
|
|
9318
|
+
return /* @__PURE__ */ jsx24(ScopeGateView, { ...props });
|
|
9319
|
+
}
|
|
9320
|
+
function ScopeGateView({ components, onConfirm, onQuit }) {
|
|
9321
|
+
const gate = useScopeGate({ components, onConfirm, onQuit });
|
|
9322
|
+
const { search, graph, columnPlan, panelLayout, counters } = gate;
|
|
9323
|
+
if (gate.showHelp) {
|
|
9324
|
+
return /* @__PURE__ */ jsx24(HelpOverlay, { sections: HELP_SECTIONS, handleInput: false, onClose: gate.closeHelp });
|
|
9325
|
+
}
|
|
9326
|
+
return /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", paddingX: 2, children: [
|
|
9327
|
+
/* @__PURE__ */ jsxs21(Box20, { flexDirection: "row", flexWrap: "wrap", children: [
|
|
9328
|
+
/* @__PURE__ */ jsx24(CounterStrip, { counters, totalWidth: gate.totalWidth }),
|
|
9329
|
+
gate.aiExcludedCount > 0 && /* @__PURE__ */ jsxs21(Text22, { color: PALETTE2.muted, children: [
|
|
9330
|
+
`${gate.aiExcludedCount} component${gate.aiExcludedCount === 1 ? "" : "s"} flagged by AI`,
|
|
9331
|
+
gate.aiRows.length > 0 && /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.info, children: " \u2014 press [x] to see why" })
|
|
9332
|
+
] })
|
|
9333
|
+
] }),
|
|
9334
|
+
graph.cycles.length > 0 && /* @__PURE__ */ jsx24(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.muted, children: "If you must have components with cycles, select them together into the generate step and then use the editor to fix them." }) }),
|
|
9335
|
+
/* @__PURE__ */ jsxs21(Box20, { flexDirection: "row", alignItems: "stretch", children: [
|
|
9336
|
+
gate.aiRationalePanelOpen ? /* @__PURE__ */ jsx24(
|
|
9337
|
+
GotoBanner,
|
|
9338
|
+
{
|
|
9339
|
+
title: `Review flags (${gate.aiExcludedCount})`,
|
|
9340
|
+
rows: gate.aiRows,
|
|
9341
|
+
cursor: gate.aiCursor,
|
|
9342
|
+
maxRows: gate.panelMaxRows,
|
|
9343
|
+
width: columnPlan.main,
|
|
9344
|
+
footerHint: "[\u2191/\u2193] move \xB7 [Enter] jump \xB7 [x/Esc] close"
|
|
9345
|
+
}
|
|
9346
|
+
) : /* @__PURE__ */ jsx24(
|
|
9347
|
+
GroupedSidebar,
|
|
9348
|
+
{
|
|
9349
|
+
items: gate.groupedItems,
|
|
9350
|
+
cycleParticipants: graph.cycleParticipants,
|
|
9351
|
+
selectedIdx: gate.visibleRows[gate.safeCursor]?.itemIdx ?? -1,
|
|
9352
|
+
selectedRowIdx: gate.safeCursor,
|
|
9353
|
+
onSelect: () => {
|
|
9354
|
+
},
|
|
9355
|
+
expandedGroups: gate.expandedGroups,
|
|
9356
|
+
onToggleExpanded: gate.toggleExpanded,
|
|
9357
|
+
width: columnPlan.main,
|
|
9358
|
+
height: panelLayout.height,
|
|
9359
|
+
title: "All components",
|
|
9360
|
+
wrapLabels: true,
|
|
9361
|
+
focused: gate.focusedColumn === "main",
|
|
9362
|
+
scrollOffset: gate.scrollOffset,
|
|
9363
|
+
visibleCount: gate.visibleCount,
|
|
9364
|
+
showFlatTier: false,
|
|
9365
|
+
selectionStateByKey: gate.selectionStateByKey,
|
|
9366
|
+
aiFlaggedByKey: gate.aiFlaggedByKey,
|
|
9367
|
+
dimPredicate: gate.dimPredicate,
|
|
9368
|
+
visibleRows: gate.visibleRows,
|
|
9369
|
+
viewMode: gate.columnOneView,
|
|
9370
|
+
graph: graph.nodes
|
|
9371
|
+
}
|
|
9372
|
+
),
|
|
9373
|
+
columnPlan.layout === "two-column" && /* @__PURE__ */ jsxs21(Fragment4, { children: [
|
|
9374
|
+
/* @__PURE__ */ jsx24(Box20, { width: 2, flexShrink: 0 }),
|
|
9375
|
+
/* @__PURE__ */ jsx24(
|
|
9376
|
+
AddedColumn,
|
|
9377
|
+
{
|
|
9378
|
+
width: columnPlan.added,
|
|
9379
|
+
entries: gate.addedComponents,
|
|
9380
|
+
cursor: gate.safeAddedComponentsCursor,
|
|
9381
|
+
focused: gate.focusedColumn === "added-components",
|
|
9382
|
+
height: panelLayout.height,
|
|
9383
|
+
title: `Accepted Components (${counters.accepted}/${counters.total})`,
|
|
9384
|
+
aiFlaggedByKey: gate.aiFlaggedByKey,
|
|
9385
|
+
visibleCount: panelLayout.sideVisibleCount
|
|
9386
|
+
}
|
|
9387
|
+
)
|
|
9388
|
+
] })
|
|
9389
|
+
] }),
|
|
9390
|
+
gate.cyclesPanelOpen && /* @__PURE__ */ jsx24(CyclesPanel, { cycles: gate.slotCycles, cursor: gate.cyclesCursor }),
|
|
9391
|
+
gate.pendingRejectCascade && /* @__PURE__ */ jsx24(RejectPrompt, { pending: gate.pendingRejectCascade }),
|
|
9392
|
+
/* @__PURE__ */ jsx24(
|
|
9393
|
+
SearchMatchSummary,
|
|
9394
|
+
{
|
|
9395
|
+
open: search.searchOpen,
|
|
9396
|
+
query: search.searchQuery,
|
|
9397
|
+
matches: search.searchQuery ? gate.searchMatches.length : 0,
|
|
9398
|
+
total: components.length,
|
|
9399
|
+
autocompleteCandidates: search.autocompleteCandidates,
|
|
9400
|
+
marginTop: 1
|
|
9401
|
+
}
|
|
9402
|
+
),
|
|
9403
|
+
/* @__PURE__ */ jsx24(
|
|
9404
|
+
CompactControlBar,
|
|
9405
|
+
{
|
|
9406
|
+
hasGroupRoots: gate.hasGroupRoots,
|
|
9407
|
+
searchActive: search.searchOpen || search.searchQuery.length > 0
|
|
9408
|
+
}
|
|
9409
|
+
)
|
|
9410
|
+
] });
|
|
9411
|
+
}
|
|
9412
|
+
|
|
9413
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
|
|
9414
|
+
import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef5, useState as useState13 } from "react";
|
|
9415
|
+
|
|
9416
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/cache-check.ts
|
|
9417
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
9418
|
+
function buildCacheCheckArgs(input) {
|
|
9419
|
+
const args = ["__generate", "components", "--agent", input.agent, "--session", input.sessionId];
|
|
9420
|
+
if (input.tokensPath) args.push("--tokens", input.tokensPath);
|
|
9421
|
+
if (input.agentModel) args.push("--model", input.agentModel);
|
|
9422
|
+
if (input.noCache) args.push("--no-cache");
|
|
9423
|
+
for (const prompt of input.promptOverrides) args.push("--prompt", prompt);
|
|
9424
|
+
if (input.existingEntitiesPath) args.push("--existing-entities-path", input.existingEntitiesPath);
|
|
9425
|
+
args.push("--cache-status", "--restore-cache");
|
|
9426
|
+
return args;
|
|
9427
|
+
}
|
|
9428
|
+
function parseCacheComponents(stdout) {
|
|
9429
|
+
const line = /^cache-components=(.+)$/m.exec(stdout)?.[1];
|
|
9430
|
+
if (!line) return [];
|
|
9431
|
+
try {
|
|
9432
|
+
const names = JSON.parse(line);
|
|
9433
|
+
return Array.isArray(names) ? names.filter((name) => typeof name === "string") : [];
|
|
9434
|
+
} catch {
|
|
9435
|
+
return [];
|
|
9436
|
+
}
|
|
9437
|
+
}
|
|
9438
|
+
var runLegacyCli = (args) => new Promise((resolve10) => {
|
|
9439
|
+
execFile3("node", [findLegacyCliPath(), ...args], (error, stdout, stderr) => {
|
|
9440
|
+
resolve10({ exitCode: error?.code ? Number(error.code) : 0, stdout, stderr });
|
|
9441
|
+
});
|
|
9442
|
+
});
|
|
9443
|
+
async function checkGenerationCache(input, run2 = runLegacyCli) {
|
|
9444
|
+
if (input.noCache) return [];
|
|
9445
|
+
try {
|
|
9446
|
+
const result = await run2(buildCacheCheckArgs(input));
|
|
9447
|
+
if (result.exitCode !== 0) return [];
|
|
9448
|
+
return parseCacheComponents(result.stdout);
|
|
9449
|
+
} catch {
|
|
9450
|
+
return [];
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
|
|
9454
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/load.ts
|
|
9455
|
+
function loadScopeGate(sessionId) {
|
|
9456
|
+
try {
|
|
9457
|
+
const db = openPipelineDb();
|
|
9458
|
+
try {
|
|
9459
|
+
const components = loadScopeComponents(db, sessionId);
|
|
9460
|
+
if (components.length === 0) {
|
|
9461
|
+
return { ok: false, message: "No components found for this session. Please run the import again." };
|
|
9462
|
+
}
|
|
9463
|
+
return { ok: true, components };
|
|
9464
|
+
} finally {
|
|
9465
|
+
db.close();
|
|
9466
|
+
}
|
|
9467
|
+
} catch (error) {
|
|
9468
|
+
return {
|
|
9469
|
+
ok: false,
|
|
9470
|
+
message: `Could not read the extracted components: ${error instanceof Error ? error.message : String(error)}`
|
|
9471
|
+
};
|
|
9472
|
+
}
|
|
9473
|
+
}
|
|
9474
|
+
|
|
9475
|
+
// packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
|
|
9476
|
+
var realDeps2 = { load: loadScopeGate, checkCache: checkGenerationCache };
|
|
9477
|
+
function useScopeGateFlow(input, deps = realDeps2) {
|
|
9478
|
+
const sessionId = input?.sessionId;
|
|
9479
|
+
const loaded = useMemo3(() => sessionId ? deps.load(sessionId) : void 0, [sessionId]);
|
|
9480
|
+
const cacheCheck = useRef5(void 0);
|
|
9481
|
+
const [confirmed, setConfirmed] = useState13();
|
|
9482
|
+
const [scope, setScope] = useState13();
|
|
9483
|
+
useEffect8(() => {
|
|
9484
|
+
if (!input || !loaded?.ok || cacheCheck.current) return;
|
|
9485
|
+
cacheCheck.current = deps.checkCache(input.cache);
|
|
9486
|
+
}, [input, loaded]);
|
|
9487
|
+
useEffect8(() => {
|
|
9488
|
+
if (!confirmed || !cacheCheck.current) return;
|
|
9489
|
+
let current = true;
|
|
9490
|
+
void cacheCheck.current.then((cachedNames) => {
|
|
9491
|
+
if (current) setScope({ ...confirmed, cachedNames });
|
|
9492
|
+
});
|
|
9493
|
+
return () => {
|
|
9494
|
+
current = false;
|
|
9495
|
+
};
|
|
9496
|
+
}, [confirmed]);
|
|
9497
|
+
if (!input || !loaded) return void 0;
|
|
9498
|
+
if (!loaded.ok) return { status: "failed", message: loaded.message };
|
|
9499
|
+
if (scope) return { status: "confirmed", scope };
|
|
9500
|
+
if (confirmed) return { status: "preparing" };
|
|
9501
|
+
return { status: "deciding", load: loaded, confirm: setConfirmed };
|
|
9502
|
+
}
|
|
9503
|
+
|
|
9504
|
+
// packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
|
|
9505
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
9506
|
+
|
|
9507
|
+
// packages/experience-design-system-cli/src/commands/import-options.ts
|
|
9508
|
+
function importOptionArgs(options) {
|
|
9509
|
+
return [
|
|
9510
|
+
...options.agent ? ["--agent", options.agent] : [],
|
|
9511
|
+
...options.prompt.flatMap((value) => ["--prompt", value]),
|
|
9512
|
+
...options.cache ? [] : ["--no-cache"]
|
|
9513
|
+
];
|
|
9514
|
+
}
|
|
9515
|
+
|
|
9516
|
+
// packages/experience-design-system-types/dist/src/handoff/index.js
|
|
9517
|
+
import * as z5 from "zod/mini";
|
|
9518
|
+
var HANDOFF_ENV = "EDS_IMPORT_HANDOFF";
|
|
9519
|
+
var NonEmpty = z5.string().check(z5.minLength(1));
|
|
9520
|
+
var TokensSchema = z5.object({
|
|
9521
|
+
/**
|
|
9522
|
+
* What to do about an existing `tokens.json`.
|
|
9523
|
+
* reuse: keep it. regenerate: build it again with the cache off. generate: nothing was asked, build it as usual.
|
|
9524
|
+
*/
|
|
9525
|
+
strategy: z5.enum(["reuse", "regenerate", "generate"])
|
|
9526
|
+
});
|
|
9527
|
+
var ExtractionSchema = z5.object({
|
|
9528
|
+
sessionId: NonEmpty,
|
|
9529
|
+
outDir: NonEmpty,
|
|
9530
|
+
tokensPath: z5.string(),
|
|
9531
|
+
tokenSessionId: z5.nullable(z5.string()),
|
|
9532
|
+
tokenCount: z5.number(),
|
|
9533
|
+
existingEntitiesPath: z5.nullable(z5.string()),
|
|
9534
|
+
/** Never 'running': the wizard starts its background cache check only once this has settled. */
|
|
9535
|
+
existingEntitiesStatus: z5.enum(["idle", "complete", "failed"]),
|
|
9536
|
+
/** The only phases the scope gate can start from. */
|
|
9537
|
+
compositionPhase: z5.enum(["done", "cache-hit"])
|
|
9538
|
+
});
|
|
9539
|
+
var ScopeSchema = z5.object({
|
|
9540
|
+
/** The components the user kept at the scope gate. The wizard saves these, then generates them. */
|
|
9541
|
+
accepted: z5.array(z5.string()),
|
|
9542
|
+
/** Everything else at the gate, which counts as rejected. */
|
|
9543
|
+
rejected: z5.array(z5.string()),
|
|
9544
|
+
/**
|
|
9545
|
+
* Components the generation cache already holds, found by the check that ran while the gate was open and which has
|
|
9546
|
+
* finished (and restored them) before the wizard starts. Empty when the cache is off or the check failed.
|
|
9547
|
+
*/
|
|
9548
|
+
cachedNames: z5.array(z5.string())
|
|
9549
|
+
});
|
|
9550
|
+
var ImportHandoffSchema = z5.object({
|
|
9551
|
+
/** The user skipped the credentials screen, so nothing is fetched from or pushed to Contentful. */
|
|
9552
|
+
credentialsSkipped: z5.boolean(),
|
|
9553
|
+
tokens: TokensSchema,
|
|
9554
|
+
/** Present once the CLI has run the extraction stage; the wizard then starts at the scope gate. */
|
|
9555
|
+
extraction: z5.optional(ExtractionSchema),
|
|
9556
|
+
/** Present once the user has confirmed the scope gate; the wizard then saves the decisions and starts generating. */
|
|
9557
|
+
scope: z5.optional(ScopeSchema)
|
|
9558
|
+
});
|
|
9559
|
+
function serializeHandoff(handoff) {
|
|
9560
|
+
return JSON.stringify(handoff);
|
|
9561
|
+
}
|
|
9562
|
+
|
|
9563
|
+
// packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
|
|
9564
|
+
function buildArgs2(options) {
|
|
9565
|
+
const args = ["import"];
|
|
9566
|
+
if (options.projectPath) {
|
|
9567
|
+
args.push("--project", options.projectPath);
|
|
9568
|
+
}
|
|
9569
|
+
if (options.tokens) {
|
|
9570
|
+
args.push("--tokens", options.tokens);
|
|
9571
|
+
}
|
|
9572
|
+
args.push(...importOptionArgs({ agent: options.agent, prompt: options.prompt ?? [], cache: options.cache ?? true }));
|
|
9573
|
+
return args;
|
|
9574
|
+
}
|
|
9575
|
+
function buildEnv(options, base = process.env) {
|
|
9576
|
+
return { ...base, ...options.handoff ? { [HANDOFF_ENV]: serializeHandoff(options.handoff) } : {} };
|
|
9577
|
+
}
|
|
9578
|
+
async function spawnV1Import(options = {}) {
|
|
9579
|
+
const cliPath = findLegacyCliPath();
|
|
9580
|
+
const args = buildArgs2(options);
|
|
9581
|
+
return new Promise((resolvePromise) => {
|
|
9582
|
+
const child = spawn7("node", [cliPath, ...args], {
|
|
9583
|
+
stdio: "inherit",
|
|
9584
|
+
env: buildEnv(options)
|
|
9585
|
+
});
|
|
9586
|
+
child.on("close", (code) => {
|
|
9587
|
+
resolvePromise({ exitCode: code ?? 1, result: void 0, stdout: "", stderr: "" });
|
|
9588
|
+
});
|
|
9589
|
+
child.on("error", (err) => {
|
|
9590
|
+
resolvePromise({ exitCode: 1, result: void 0, stdout: "", stderr: err.message });
|
|
9591
|
+
});
|
|
9592
|
+
});
|
|
9593
|
+
}
|
|
9594
|
+
|
|
9595
|
+
// packages/experience-design-system-cli/src/tui/import/terminal-input.ts
|
|
9596
|
+
function getTerminalHandle() {
|
|
9597
|
+
return process.stdin._handle;
|
|
9598
|
+
}
|
|
9599
|
+
async function stopReadingTerminal() {
|
|
9600
|
+
await new Promise((resolve10) => setImmediate(resolve10));
|
|
9601
|
+
const handle = getTerminalHandle();
|
|
9602
|
+
if (!handle?.readStop) return;
|
|
9603
|
+
handle.reading = false;
|
|
9604
|
+
handle.readStop();
|
|
9605
|
+
}
|
|
9606
|
+
function startReadingTerminal() {
|
|
9607
|
+
const handle = getTerminalHandle();
|
|
9608
|
+
if (!handle?.readStart) return;
|
|
9609
|
+
handle.reading = true;
|
|
9610
|
+
handle.readStart();
|
|
9611
|
+
}
|
|
9612
|
+
|
|
9613
|
+
// packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
|
|
9614
|
+
import { useEffect as useEffect9, useState as useState14 } from "react";
|
|
9615
|
+
import { Box as Box21, Text as Text23, useInput as useInput9 } from "ink";
|
|
9616
|
+
|
|
9617
|
+
// packages/experience-design-system-cli/src/tui/debug-store.ts
|
|
9618
|
+
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
9619
|
+
import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
|
|
9620
|
+
import { join as join12 } from "node:path";
|
|
9621
|
+
|
|
9622
|
+
// packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
|
|
9623
|
+
var DEFAULT_DEBUG_MODE_SETTING = {
|
|
9624
|
+
enabled: true
|
|
9625
|
+
};
|
|
9626
|
+
async function readDebugModeSetting() {
|
|
9627
|
+
const { debugMode } = await readSettings2();
|
|
9628
|
+
return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
|
|
9629
|
+
}
|
|
9630
|
+
async function writeDebugModeSetting(setting) {
|
|
9631
|
+
await updateSettings2({ debugMode: setting });
|
|
9632
|
+
}
|
|
9633
|
+
|
|
9634
|
+
// packages/experience-design-system-cli/src/tui/debug-store.ts
|
|
9635
|
+
var pendingRun;
|
|
9636
|
+
function generateRunId() {
|
|
9637
|
+
const now = /* @__PURE__ */ new Date();
|
|
9638
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
9639
|
+
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
9640
|
+
}
|
|
9641
|
+
function datePrefix(now = /* @__PURE__ */ new Date()) {
|
|
9642
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
9643
|
+
return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
|
|
9644
|
+
}
|
|
9645
|
+
function slugify(value) {
|
|
9646
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
9647
|
+
}
|
|
9648
|
+
function generateSessionId3() {
|
|
9649
|
+
const today = datePrefix();
|
|
9650
|
+
const root = debugSessionsDir2();
|
|
9651
|
+
const existing = existsSync5(root) ? readdirSync2(root) : [];
|
|
9652
|
+
const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
|
|
9653
|
+
const maxSeq = existing.reduce((max, entry) => {
|
|
9654
|
+
const match2 = seqPattern.exec(entry);
|
|
9655
|
+
return match2 ? Math.max(max, Number(match2[1])) : max;
|
|
9656
|
+
}, 0);
|
|
9657
|
+
return `${today}-session-${maxSeq + 1}`;
|
|
9658
|
+
}
|
|
9659
|
+
var SESSION_ID = generateSessionId3();
|
|
9660
|
+
function sessionDebugDir() {
|
|
9661
|
+
return join12(debugSessionsDir2(), SESSION_ID);
|
|
9662
|
+
}
|
|
9663
|
+
function currentDebugSessionDir() {
|
|
9664
|
+
return sessionDebugDir();
|
|
9665
|
+
}
|
|
9666
|
+
void isDebugModeEnabled().then((enabled) => {
|
|
9667
|
+
if (!enabled) return void 0;
|
|
9668
|
+
return mkdir3(sessionDebugDir(), { recursive: true });
|
|
9669
|
+
});
|
|
9670
|
+
async function isDebugModeEnabled() {
|
|
9671
|
+
try {
|
|
9672
|
+
return (await readDebugModeSetting()).enabled;
|
|
9673
|
+
} catch {
|
|
9674
|
+
return true;
|
|
9675
|
+
}
|
|
9676
|
+
}
|
|
9677
|
+
function redact(value) {
|
|
9678
|
+
const clone = { ...value };
|
|
9679
|
+
if ("cma_token" in clone) {
|
|
9680
|
+
const raw = clone.cma_token;
|
|
9681
|
+
clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
|
|
9682
|
+
}
|
|
9683
|
+
return clone;
|
|
9684
|
+
}
|
|
9685
|
+
function startDebugRun({
|
|
9686
|
+
flow,
|
|
9687
|
+
step,
|
|
9688
|
+
menuOption,
|
|
9689
|
+
inputs
|
|
9690
|
+
}) {
|
|
9691
|
+
const runId = generateRunId();
|
|
9692
|
+
const startedAt = Date.now();
|
|
9693
|
+
const redactedInputs = redact(inputs);
|
|
9694
|
+
isDebugModeEnabled().then((enabled) => {
|
|
9695
|
+
if (!enabled) return;
|
|
9696
|
+
pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
|
|
9697
|
+
});
|
|
9698
|
+
}
|
|
9699
|
+
async function finishDebugRun({
|
|
9700
|
+
outputs,
|
|
9701
|
+
status,
|
|
9702
|
+
exitMethod
|
|
9703
|
+
}) {
|
|
9704
|
+
const run2 = pendingRun;
|
|
6883
9705
|
if (!run2) return;
|
|
6884
9706
|
pendingRun = void 0;
|
|
6885
9707
|
const durationMs = Date.now() - run2.startedAt;
|
|
@@ -6896,8 +9718,8 @@ function nextAttemptFilename(dir, menuOption) {
|
|
|
6896
9718
|
const existing = existsSync5(dir) ? readdirSync2(dir) : [];
|
|
6897
9719
|
const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
|
|
6898
9720
|
const maxAttempt = existing.reduce((max, entry) => {
|
|
6899
|
-
const
|
|
6900
|
-
return
|
|
9721
|
+
const match2 = attemptPattern.exec(entry);
|
|
9722
|
+
return match2 ? Math.max(max, Number(match2[1])) : max;
|
|
6901
9723
|
}, 0);
|
|
6902
9724
|
return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
|
|
6903
9725
|
}
|
|
@@ -6971,19 +9793,19 @@ async function readHelpInfo() {
|
|
|
6971
9793
|
}
|
|
6972
9794
|
|
|
6973
9795
|
// packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
|
|
6974
|
-
import { Fragment as
|
|
9796
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
6975
9797
|
function Section({ title, rows }) {
|
|
6976
|
-
return /* @__PURE__ */
|
|
6977
|
-
/* @__PURE__ */
|
|
6978
|
-
rows.map((row) => /* @__PURE__ */
|
|
6979
|
-
/* @__PURE__ */
|
|
6980
|
-
/* @__PURE__ */
|
|
9798
|
+
return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
|
|
9799
|
+
/* @__PURE__ */ jsx25(Text23, { bold: true, color: PALETTE.accent, children: title }),
|
|
9800
|
+
rows.map((row) => /* @__PURE__ */ jsxs22(Box21, { gap: 1, children: [
|
|
9801
|
+
/* @__PURE__ */ jsx25(Box21, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx25(Text23, { color: PALETTE.muted, children: row.label }) }),
|
|
9802
|
+
/* @__PURE__ */ jsx25(Text23, { children: row.value })
|
|
6981
9803
|
] }, row.label))
|
|
6982
9804
|
] });
|
|
6983
9805
|
}
|
|
6984
9806
|
function HelpScreen({ onDone }) {
|
|
6985
|
-
const [info, setInfo] =
|
|
6986
|
-
|
|
9807
|
+
const [info, setInfo] = useState14();
|
|
9808
|
+
useEffect9(() => {
|
|
6987
9809
|
startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
|
|
6988
9810
|
void readHelpInfo().then(setInfo);
|
|
6989
9811
|
}, []);
|
|
@@ -7001,14 +9823,14 @@ function HelpScreen({ onDone }) {
|
|
|
7001
9823
|
return;
|
|
7002
9824
|
}
|
|
7003
9825
|
});
|
|
7004
|
-
return /* @__PURE__ */
|
|
7005
|
-
/* @__PURE__ */
|
|
7006
|
-
info ? /* @__PURE__ */
|
|
7007
|
-
/* @__PURE__ */
|
|
7008
|
-
/* @__PURE__ */
|
|
7009
|
-
/* @__PURE__ */
|
|
7010
|
-
] }) : /* @__PURE__ */
|
|
7011
|
-
/* @__PURE__ */
|
|
9826
|
+
return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [
|
|
9827
|
+
/* @__PURE__ */ jsx25(Text23, { bold: true, children: "Help" }),
|
|
9828
|
+
info ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
9829
|
+
/* @__PURE__ */ jsx25(Section, { title: "Where things are stored", rows: info.storage }),
|
|
9830
|
+
/* @__PURE__ */ jsx25(Section, { title: "Troubleshooting", rows: info.troubleshooting }),
|
|
9831
|
+
/* @__PURE__ */ jsx25(Text23, { color: PALETTE.muted, children: "Hit a problem? Turn on Debug Mode in Settings, reproduce it, then share the session folder above. The CMA token is redacted from those logs." })
|
|
9832
|
+
] }) : /* @__PURE__ */ jsx25(Text23, { color: PALETTE.accent, children: "Loading..." }),
|
|
9833
|
+
/* @__PURE__ */ jsx25(
|
|
7012
9834
|
ControlHints,
|
|
7013
9835
|
{
|
|
7014
9836
|
hints: [
|
|
@@ -7021,14 +9843,14 @@ function HelpScreen({ onDone }) {
|
|
|
7021
9843
|
}
|
|
7022
9844
|
|
|
7023
9845
|
// packages/experience-design-system-cli/src/tui/settings/PageContainer.tsx
|
|
7024
|
-
import { useState as
|
|
7025
|
-
import { Box as
|
|
7026
|
-
import { jsx as
|
|
9846
|
+
import { useState as useState15 } from "react";
|
|
9847
|
+
import { Box as Box22, Text as Text24, useInput as useInput10 } from "ink";
|
|
9848
|
+
import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
7027
9849
|
function SettingsScreen({
|
|
7028
9850
|
onNavigate,
|
|
7029
9851
|
onBack
|
|
7030
9852
|
}) {
|
|
7031
|
-
const [focusIdx, setFocusIdx] =
|
|
9853
|
+
const [focusIdx, setFocusIdx] = useState15(0);
|
|
7032
9854
|
const items = [
|
|
7033
9855
|
{ label: "Configuration", screen: "settings-configuration" },
|
|
7034
9856
|
{ label: "Opt-in Analytics", screen: "settings-opt-in-analytics" },
|
|
@@ -7054,15 +9876,15 @@ function SettingsScreen({
|
|
|
7054
9876
|
onBack();
|
|
7055
9877
|
}
|
|
7056
9878
|
});
|
|
7057
|
-
return /* @__PURE__ */
|
|
7058
|
-
/* @__PURE__ */
|
|
7059
|
-
/* @__PURE__ */
|
|
7060
|
-
items.map((item, i) => /* @__PURE__ */
|
|
9879
|
+
return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
9880
|
+
/* @__PURE__ */ jsx26(Text24, { bold: true, children: "Settings" }),
|
|
9881
|
+
/* @__PURE__ */ jsx26(Text24, { children: " " }),
|
|
9882
|
+
items.map((item, i) => /* @__PURE__ */ jsxs23(Text24, { color: i === focusIdx ? "cyan" : void 0, children: [
|
|
7061
9883
|
i === focusIdx ? "> " : " ",
|
|
7062
9884
|
item.label
|
|
7063
9885
|
] }, item.label)),
|
|
7064
|
-
/* @__PURE__ */
|
|
7065
|
-
/* @__PURE__ */
|
|
9886
|
+
/* @__PURE__ */ jsx26(Text24, { children: " " }),
|
|
9887
|
+
/* @__PURE__ */ jsx26(
|
|
7066
9888
|
ControlHints,
|
|
7067
9889
|
{
|
|
7068
9890
|
hints: [
|
|
@@ -7076,8 +9898,8 @@ function SettingsScreen({
|
|
|
7076
9898
|
}
|
|
7077
9899
|
|
|
7078
9900
|
// packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
|
|
7079
|
-
import { useEffect as
|
|
7080
|
-
import { Box as
|
|
9901
|
+
import { useEffect as useEffect10, useState as useState16 } from "react";
|
|
9902
|
+
import { Box as Box23, Text as Text25, useInput as useInput11 } from "ink";
|
|
7081
9903
|
import TextInput4 from "ink-text-input";
|
|
7082
9904
|
|
|
7083
9905
|
// packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
|
|
@@ -7109,7 +9931,7 @@ async function writeCredentials(config) {
|
|
|
7109
9931
|
}
|
|
7110
9932
|
|
|
7111
9933
|
// packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
|
|
7112
|
-
import { Fragment as
|
|
9934
|
+
import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7113
9935
|
var FIELD_ORDER = [
|
|
7114
9936
|
"spaceId",
|
|
7115
9937
|
"environmentId",
|
|
@@ -7137,14 +9959,14 @@ var FIELD_LABELS = {
|
|
|
7137
9959
|
defaultTokenFile: "Default token file (optional)"
|
|
7138
9960
|
};
|
|
7139
9961
|
function ConfigurationScreen({ onDone }) {
|
|
7140
|
-
const [stage, setStage] =
|
|
7141
|
-
const [config, setConfig] =
|
|
7142
|
-
const [activeField, setActiveField] =
|
|
7143
|
-
const [notice, setNotice] =
|
|
7144
|
-
const [lastSaved, setLastSaved] =
|
|
7145
|
-
const [editing, setEditing] =
|
|
7146
|
-
const [valueBeforeEdit, setValueBeforeEdit] =
|
|
7147
|
-
|
|
9962
|
+
const [stage, setStage] = useState16("loading");
|
|
9963
|
+
const [config, setConfig] = useState16(null);
|
|
9964
|
+
const [activeField, setActiveField] = useState16("spaceId");
|
|
9965
|
+
const [notice, setNotice] = useState16(null);
|
|
9966
|
+
const [lastSaved, setLastSaved] = useState16(null);
|
|
9967
|
+
const [editing, setEditing] = useState16(false);
|
|
9968
|
+
const [valueBeforeEdit, setValueBeforeEdit] = useState16("");
|
|
9969
|
+
useEffect10(() => {
|
|
7148
9970
|
readCredentials().then((cfg) => {
|
|
7149
9971
|
setConfig(cfg);
|
|
7150
9972
|
setStage("form");
|
|
@@ -7221,26 +10043,26 @@ function ConfigurationScreen({ onDone }) {
|
|
|
7221
10043
|
}
|
|
7222
10044
|
});
|
|
7223
10045
|
if (stage === "loading") {
|
|
7224
|
-
return /* @__PURE__ */
|
|
7225
|
-
/* @__PURE__ */
|
|
7226
|
-
/* @__PURE__ */
|
|
7227
|
-
/* @__PURE__ */
|
|
10046
|
+
return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10047
|
+
/* @__PURE__ */ jsx27(Text25, { bold: true, children: "Configuration" }),
|
|
10048
|
+
/* @__PURE__ */ jsx27(Text25, { children: " " }),
|
|
10049
|
+
/* @__PURE__ */ jsx27(Text25, { color: PALETTE.accent, children: "Loading..." })
|
|
7228
10050
|
] });
|
|
7229
10051
|
}
|
|
7230
|
-
return /* @__PURE__ */
|
|
7231
|
-
/* @__PURE__ */
|
|
7232
|
-
/* @__PURE__ */
|
|
7233
|
-
/* @__PURE__ */
|
|
10052
|
+
return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10053
|
+
/* @__PURE__ */ jsx27(Text25, { bold: true, children: "Configuration" }),
|
|
10054
|
+
/* @__PURE__ */ jsx27(Text25, { children: " " }),
|
|
10055
|
+
/* @__PURE__ */ jsx27(Box23, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
|
|
7234
10056
|
const isActive = activeField === field;
|
|
7235
10057
|
const value = fieldValue(field);
|
|
7236
10058
|
const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
|
|
7237
|
-
return /* @__PURE__ */
|
|
7238
|
-
/* @__PURE__ */
|
|
7239
|
-
/* @__PURE__ */
|
|
10059
|
+
return /* @__PURE__ */ jsxs24(Box23, { gap: 1, children: [
|
|
10060
|
+
/* @__PURE__ */ jsx27(Text25, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
|
|
10061
|
+
/* @__PURE__ */ jsxs24(Text25, { bold: isActive, children: [
|
|
7240
10062
|
FIELD_LABELS[field],
|
|
7241
10063
|
":"
|
|
7242
10064
|
] }),
|
|
7243
|
-
isActive && editing ? /* @__PURE__ */
|
|
10065
|
+
isActive && editing ? /* @__PURE__ */ jsx27(
|
|
7244
10066
|
TextInput4,
|
|
7245
10067
|
{
|
|
7246
10068
|
value,
|
|
@@ -7248,19 +10070,19 @@ function ConfigurationScreen({ onDone }) {
|
|
|
7248
10070
|
onSubmit: () => setEditing(false),
|
|
7249
10071
|
mask: field === "cmaToken" ? "\u2022" : void 0
|
|
7250
10072
|
}
|
|
7251
|
-
) : /* @__PURE__ */
|
|
10073
|
+
) : /* @__PURE__ */ jsx27(Text25, { children: display || /* @__PURE__ */ jsx27(Text25, { color: PALETTE.muted, children: "(empty)" }) })
|
|
7252
10074
|
] }, field);
|
|
7253
10075
|
}) }),
|
|
7254
|
-
notice && /* @__PURE__ */
|
|
7255
|
-
/* @__PURE__ */
|
|
7256
|
-
/* @__PURE__ */
|
|
10076
|
+
notice && /* @__PURE__ */ jsxs24(Fragment6, { children: [
|
|
10077
|
+
/* @__PURE__ */ jsx27(Text25, { children: " " }),
|
|
10078
|
+
/* @__PURE__ */ jsxs24(Text25, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
|
|
7257
10079
|
notice.kind === "success" ? "\u2713" : "\u2717",
|
|
7258
10080
|
" ",
|
|
7259
10081
|
notice.text
|
|
7260
10082
|
] })
|
|
7261
10083
|
] }),
|
|
7262
|
-
/* @__PURE__ */
|
|
7263
|
-
/* @__PURE__ */
|
|
10084
|
+
/* @__PURE__ */ jsx27(Text25, { children: " " }),
|
|
10085
|
+
/* @__PURE__ */ jsx27(
|
|
7264
10086
|
ControlHints,
|
|
7265
10087
|
{
|
|
7266
10088
|
hints: editing ? [
|
|
@@ -7281,8 +10103,8 @@ function ConfigurationScreen({ onDone }) {
|
|
|
7281
10103
|
}
|
|
7282
10104
|
|
|
7283
10105
|
// packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
|
|
7284
|
-
import { useEffect as
|
|
7285
|
-
import { Box as
|
|
10106
|
+
import { useEffect as useEffect11, useState as useState17 } from "react";
|
|
10107
|
+
import { Box as Box24, Text as Text26, useInput as useInput12 } from "ink";
|
|
7286
10108
|
|
|
7287
10109
|
// packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/analytics-store.ts
|
|
7288
10110
|
async function readAnalyticsSetting() {
|
|
@@ -7300,11 +10122,11 @@ async function writeAnalyticsSetting(setting) {
|
|
|
7300
10122
|
}
|
|
7301
10123
|
|
|
7302
10124
|
// packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
|
|
7303
|
-
import { Fragment as
|
|
10125
|
+
import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7304
10126
|
function OptInAnalyticsScreen({ onDone }) {
|
|
7305
|
-
const [loading, setLoading] =
|
|
7306
|
-
const [enabled, setEnabled] =
|
|
7307
|
-
|
|
10127
|
+
const [loading, setLoading] = useState17(true);
|
|
10128
|
+
const [enabled, setEnabled] = useState17(true);
|
|
10129
|
+
useEffect11(() => {
|
|
7308
10130
|
readAnalyticsSetting().then((setting) => {
|
|
7309
10131
|
setEnabled(setting.enabled);
|
|
7310
10132
|
setLoading(false);
|
|
@@ -7331,21 +10153,21 @@ function OptInAnalyticsScreen({ onDone }) {
|
|
|
7331
10153
|
onDone();
|
|
7332
10154
|
}
|
|
7333
10155
|
});
|
|
7334
|
-
return /* @__PURE__ */
|
|
7335
|
-
/* @__PURE__ */
|
|
7336
|
-
/* @__PURE__ */
|
|
7337
|
-
loading ? /* @__PURE__ */
|
|
7338
|
-
/* @__PURE__ */
|
|
10156
|
+
return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10157
|
+
/* @__PURE__ */ jsx28(Text26, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
|
|
10158
|
+
/* @__PURE__ */ jsx28(Text26, { children: " " }),
|
|
10159
|
+
loading ? /* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs25(Fragment7, { children: [
|
|
10160
|
+
/* @__PURE__ */ jsxs25(Text26, { children: [
|
|
7339
10161
|
"Share anonymous usage data:",
|
|
7340
10162
|
" ",
|
|
7341
|
-
/* @__PURE__ */
|
|
10163
|
+
/* @__PURE__ */ jsx28(Text26, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
|
|
7342
10164
|
] }),
|
|
7343
|
-
/* @__PURE__ */
|
|
7344
|
-
/* @__PURE__ */
|
|
7345
|
-
/* @__PURE__ */
|
|
10165
|
+
/* @__PURE__ */ jsx28(Text26, { children: " " }),
|
|
10166
|
+
/* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Shares which CLI commands are used and where imports succeed or fail." }),
|
|
10167
|
+
/* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Never includes source code, file paths, credentials, or authored content." })
|
|
7346
10168
|
] }),
|
|
7347
|
-
/* @__PURE__ */
|
|
7348
|
-
/* @__PURE__ */
|
|
10169
|
+
/* @__PURE__ */ jsx28(Text26, { children: " " }),
|
|
10170
|
+
/* @__PURE__ */ jsx28(
|
|
7349
10171
|
ControlHints,
|
|
7350
10172
|
{
|
|
7351
10173
|
hints: [
|
|
@@ -7358,13 +10180,13 @@ function OptInAnalyticsScreen({ onDone }) {
|
|
|
7358
10180
|
}
|
|
7359
10181
|
|
|
7360
10182
|
// packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
|
|
7361
|
-
import { useEffect as
|
|
7362
|
-
import { Box as
|
|
7363
|
-
import { jsx as
|
|
10183
|
+
import { useEffect as useEffect12, useState as useState18 } from "react";
|
|
10184
|
+
import { Box as Box25, Text as Text27, useInput as useInput13 } from "ink";
|
|
10185
|
+
import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7364
10186
|
var UPGRADE_COMMANDS = ["git pull", "pnpm install", "pnpm build"];
|
|
7365
10187
|
function UpgradeScreen({ onDone }) {
|
|
7366
|
-
const [upgradeCheck, setUpgradeCheck] =
|
|
7367
|
-
|
|
10188
|
+
const [upgradeCheck, setUpgradeCheck] = useState18();
|
|
10189
|
+
useEffect12(() => {
|
|
7368
10190
|
startDebugRun({
|
|
7369
10191
|
flow: "upgrade",
|
|
7370
10192
|
step: "01-upgrade",
|
|
@@ -7384,12 +10206,12 @@ function UpgradeScreen({ onDone }) {
|
|
|
7384
10206
|
return;
|
|
7385
10207
|
}
|
|
7386
10208
|
});
|
|
7387
|
-
return /* @__PURE__ */
|
|
7388
|
-
/* @__PURE__ */
|
|
7389
|
-
/* @__PURE__ */
|
|
10209
|
+
return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10210
|
+
/* @__PURE__ */ jsx29(Text27, { bold: true, children: "Upgrade" }),
|
|
10211
|
+
/* @__PURE__ */ jsx29(Text27, { children: " " }),
|
|
7390
10212
|
renderBody(upgradeCheck),
|
|
7391
|
-
/* @__PURE__ */
|
|
7392
|
-
/* @__PURE__ */
|
|
10213
|
+
/* @__PURE__ */ jsx29(Text27, { children: " " }),
|
|
10214
|
+
/* @__PURE__ */ jsxs26(Text27, { bold: true, color: PALETTE.accent, children: [
|
|
7393
10215
|
FOCUS_MARKER,
|
|
7394
10216
|
" Go Back"
|
|
7395
10217
|
] })
|
|
@@ -7397,45 +10219,45 @@ function UpgradeScreen({ onDone }) {
|
|
|
7397
10219
|
}
|
|
7398
10220
|
function renderBody(upgradeCheck) {
|
|
7399
10221
|
if (!upgradeCheck) {
|
|
7400
|
-
return /* @__PURE__ */
|
|
10222
|
+
return /* @__PURE__ */ jsx29(Text27, { color: PALETTE.muted, children: "Checking for updates\u2026" });
|
|
7401
10223
|
}
|
|
7402
10224
|
if (upgradeCheck.status === "error") {
|
|
7403
|
-
return /* @__PURE__ */
|
|
10225
|
+
return /* @__PURE__ */ jsx29(Text27, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
|
|
7404
10226
|
}
|
|
7405
10227
|
if (upgradeCheck.status === "up-to-date") {
|
|
7406
|
-
return /* @__PURE__ */
|
|
10228
|
+
return /* @__PURE__ */ jsxs26(Text27, { color: PALETTE.success, children: [
|
|
7407
10229
|
"You're already on the latest version (v",
|
|
7408
10230
|
upgradeCheck.current,
|
|
7409
10231
|
")."
|
|
7410
10232
|
] });
|
|
7411
10233
|
}
|
|
7412
|
-
return /* @__PURE__ */
|
|
7413
|
-
/* @__PURE__ */
|
|
7414
|
-
/* @__PURE__ */
|
|
10234
|
+
return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", children: [
|
|
10235
|
+
/* @__PURE__ */ jsxs26(Text27, { color: PALETTE.muted, children: [
|
|
10236
|
+
/* @__PURE__ */ jsxs26(Text27, { bold: true, color: PALETTE.success, children: [
|
|
7415
10237
|
"v",
|
|
7416
10238
|
upgradeCheck.latest
|
|
7417
10239
|
] }),
|
|
7418
10240
|
" ",
|
|
7419
10241
|
"is available (you're on ",
|
|
7420
|
-
/* @__PURE__ */
|
|
10242
|
+
/* @__PURE__ */ jsxs26(Text27, { bold: true, children: [
|
|
7421
10243
|
"v",
|
|
7422
10244
|
upgradeCheck.current
|
|
7423
10245
|
] }),
|
|
7424
10246
|
"). Exit this program, cd into the root of your local clone of contentful/experience-design-system-sdk-public, then run:"
|
|
7425
10247
|
] }),
|
|
7426
|
-
/* @__PURE__ */
|
|
7427
|
-
/* @__PURE__ */
|
|
10248
|
+
/* @__PURE__ */ jsx29(Text27, { children: " " }),
|
|
10249
|
+
/* @__PURE__ */ jsx29(Box25, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx29(Text27, { bold: true, children: cmd }, cmd)) })
|
|
7428
10250
|
] });
|
|
7429
10251
|
}
|
|
7430
10252
|
|
|
7431
10253
|
// packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
|
|
7432
|
-
import { useEffect as
|
|
7433
|
-
import { Box as
|
|
7434
|
-
import { jsx as
|
|
10254
|
+
import { useEffect as useEffect13, useState as useState19 } from "react";
|
|
10255
|
+
import { Box as Box26, Text as Text28, useInput as useInput14 } from "ink";
|
|
10256
|
+
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
7435
10257
|
function DebugModeScreen({ onDone }) {
|
|
7436
|
-
const [loading, setLoading] =
|
|
7437
|
-
const [enabled, setEnabled] =
|
|
7438
|
-
|
|
10258
|
+
const [loading, setLoading] = useState19(true);
|
|
10259
|
+
const [enabled, setEnabled] = useState19(true);
|
|
10260
|
+
useEffect13(() => {
|
|
7439
10261
|
readDebugModeSetting().then((setting) => {
|
|
7440
10262
|
setEnabled(setting.enabled);
|
|
7441
10263
|
setLoading(false);
|
|
@@ -7462,16 +10284,16 @@ function DebugModeScreen({ onDone }) {
|
|
|
7462
10284
|
onDone();
|
|
7463
10285
|
}
|
|
7464
10286
|
});
|
|
7465
|
-
return /* @__PURE__ */
|
|
7466
|
-
/* @__PURE__ */
|
|
7467
|
-
/* @__PURE__ */
|
|
7468
|
-
loading ? /* @__PURE__ */
|
|
10287
|
+
return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
10288
|
+
/* @__PURE__ */ jsx30(Text28, { bold: true, children: "Settings \u203A Debug Mode" }),
|
|
10289
|
+
/* @__PURE__ */ jsx30(Text28, { children: " " }),
|
|
10290
|
+
loading ? /* @__PURE__ */ jsx30(Text28, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs27(Text28, { children: [
|
|
7469
10291
|
"Debug logging:",
|
|
7470
10292
|
" ",
|
|
7471
|
-
/* @__PURE__ */
|
|
10293
|
+
/* @__PURE__ */ jsx30(Text28, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
|
|
7472
10294
|
] }),
|
|
7473
|
-
/* @__PURE__ */
|
|
7474
|
-
/* @__PURE__ */
|
|
10295
|
+
/* @__PURE__ */ jsx30(Text28, { children: " " }),
|
|
10296
|
+
/* @__PURE__ */ jsx30(
|
|
7475
10297
|
ControlHints,
|
|
7476
10298
|
{
|
|
7477
10299
|
hints: [
|
|
@@ -7484,19 +10306,34 @@ function DebugModeScreen({ onDone }) {
|
|
|
7484
10306
|
}
|
|
7485
10307
|
|
|
7486
10308
|
// packages/experience-design-system-cli/app.tsx
|
|
7487
|
-
import { Fragment as
|
|
10309
|
+
import { Fragment as Fragment8, jsx as jsx31 } from "react/jsx-runtime";
|
|
7488
10310
|
function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
7489
10311
|
const returnedFromImport = importExitCode !== void 0;
|
|
7490
|
-
const [screen, setScreen] =
|
|
7491
|
-
const [showImportResult, setShowImportResult] =
|
|
7492
|
-
const [projectPath, setProjectPath] =
|
|
7493
|
-
const [tokensPath, setTokensPath] =
|
|
7494
|
-
const [scannedFiles, setScannedFiles] =
|
|
7495
|
-
const [pendingLaunch, setPendingLaunch] =
|
|
7496
|
-
const [extractionRun, setExtractionRun] =
|
|
10312
|
+
const [screen, setScreen] = useState20(returnedFromImport ? "import" : "start");
|
|
10313
|
+
const [showImportResult, setShowImportResult] = useState20(returnedFromImport);
|
|
10314
|
+
const [projectPath, setProjectPath] = useState20();
|
|
10315
|
+
const [tokensPath, setTokensPath] = useState20();
|
|
10316
|
+
const [scannedFiles, setScannedFiles] = useState20();
|
|
10317
|
+
const [pendingLaunch, setPendingLaunch] = useState20();
|
|
10318
|
+
const [extractionRun, setExtractionRun] = useState20();
|
|
7497
10319
|
const extraction = useExtraction(extractionRun?.input);
|
|
7498
|
-
const [
|
|
7499
|
-
|
|
10320
|
+
const [scopeRun, setScopeRun] = useState20();
|
|
10321
|
+
const scopeFlow = useScopeGateFlow(
|
|
10322
|
+
scopeRun && {
|
|
10323
|
+
sessionId: scopeRun.extraction.sessionId,
|
|
10324
|
+
cache: {
|
|
10325
|
+
sessionId: scopeRun.extraction.sessionId,
|
|
10326
|
+
tokensPath: scopeRun.extraction.tokensPath,
|
|
10327
|
+
agent: scopeRun.input.agent,
|
|
10328
|
+
...scopeRun.input.agentModel ? { agentModel: scopeRun.input.agentModel } : {},
|
|
10329
|
+
promptOverrides: scopeRun.input.promptOverrides,
|
|
10330
|
+
existingEntitiesPath: scopeRun.extraction.existingEntitiesPath,
|
|
10331
|
+
noCache: scopeRun.input.noCache
|
|
10332
|
+
}
|
|
10333
|
+
}
|
|
10334
|
+
);
|
|
10335
|
+
const [importDefaults, setImportDefaults] = useState20();
|
|
10336
|
+
useEffect14(() => {
|
|
7500
10337
|
if (screen !== "import") {
|
|
7501
10338
|
setImportDefaults(void 0);
|
|
7502
10339
|
return;
|
|
@@ -7550,15 +10387,25 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7550
10387
|
}
|
|
7551
10388
|
});
|
|
7552
10389
|
};
|
|
7553
|
-
|
|
10390
|
+
useEffect14(() => {
|
|
7554
10391
|
if (!extractionRun || extraction?.status !== "done" || !extraction.result.ok) return;
|
|
7555
|
-
const { launch, credentialsSkipped, tokenStrategy } = extractionRun;
|
|
7556
10392
|
setExtractionRun(void 0);
|
|
10393
|
+
setScopeRun({ ...extractionRun, extraction: extraction.result.extraction });
|
|
10394
|
+
}, [extraction, extractionRun]);
|
|
10395
|
+
useEffect14(() => {
|
|
10396
|
+
if (!scopeRun || scopeFlow?.status !== "confirmed") return;
|
|
10397
|
+
const { launch, credentialsSkipped, tokenStrategy, extraction: produced } = scopeRun;
|
|
10398
|
+
setScopeRun(void 0);
|
|
7557
10399
|
onLaunchImport?.({
|
|
7558
10400
|
...launch,
|
|
7559
|
-
handoff: {
|
|
10401
|
+
handoff: {
|
|
10402
|
+
credentialsSkipped,
|
|
10403
|
+
tokens: { strategy: tokenStrategy },
|
|
10404
|
+
extraction: produced,
|
|
10405
|
+
scope: scopeFlow.scope
|
|
10406
|
+
}
|
|
7560
10407
|
});
|
|
7561
|
-
}, [
|
|
10408
|
+
}, [scopeFlow, scopeRun]);
|
|
7562
10409
|
const goToStart = () => setScreen("start");
|
|
7563
10410
|
const goToSettings = () => setScreen("settings");
|
|
7564
10411
|
const resetImport = () => {
|
|
@@ -7567,6 +10414,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7567
10414
|
setScannedFiles(void 0);
|
|
7568
10415
|
setPendingLaunch(void 0);
|
|
7569
10416
|
setExtractionRun(void 0);
|
|
10417
|
+
setScopeRun(void 0);
|
|
7570
10418
|
};
|
|
7571
10419
|
const finishImportResult = () => {
|
|
7572
10420
|
setShowImportResult(false);
|
|
@@ -7579,13 +10427,13 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7579
10427
|
};
|
|
7580
10428
|
switch (screen) {
|
|
7581
10429
|
case "import":
|
|
7582
|
-
if (showImportResult) return /* @__PURE__ */
|
|
7583
|
-
if (importDefaults === void 0) return /* @__PURE__ */
|
|
10430
|
+
if (showImportResult) return /* @__PURE__ */ jsx31(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
|
|
10431
|
+
if (importDefaults === void 0) return /* @__PURE__ */ jsx31(Fragment8, {});
|
|
7584
10432
|
if (projectPath === void 0) {
|
|
7585
|
-
return /* @__PURE__ */
|
|
10433
|
+
return /* @__PURE__ */ jsx31(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
|
|
7586
10434
|
}
|
|
7587
10435
|
if (tokensPath === void 0) {
|
|
7588
|
-
return /* @__PURE__ */
|
|
10436
|
+
return /* @__PURE__ */ jsx31(
|
|
7589
10437
|
TokenInputScreen,
|
|
7590
10438
|
{
|
|
7591
10439
|
initialPath: importDefaults.tokenFile,
|
|
@@ -7595,7 +10443,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7595
10443
|
);
|
|
7596
10444
|
}
|
|
7597
10445
|
if (scannedFiles === void 0) {
|
|
7598
|
-
return /* @__PURE__ */
|
|
10446
|
+
return /* @__PURE__ */ jsx31(
|
|
7599
10447
|
PathValidationScreen,
|
|
7600
10448
|
{
|
|
7601
10449
|
projectPath,
|
|
@@ -7607,10 +10455,10 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7607
10455
|
}
|
|
7608
10456
|
if (extractionRun) {
|
|
7609
10457
|
if (extraction?.status === "done" && !extraction.result.ok) {
|
|
7610
|
-
return /* @__PURE__ */
|
|
10458
|
+
return /* @__PURE__ */ jsx31(ErrorStep, { stepName: extraction.result.step, message: extraction.result.message, onExit: leaveImport });
|
|
7611
10459
|
}
|
|
7612
10460
|
if (extraction?.status === "running") {
|
|
7613
|
-
return /* @__PURE__ */
|
|
10461
|
+
return /* @__PURE__ */ jsx31(
|
|
7614
10462
|
ExtractionScreen,
|
|
7615
10463
|
{
|
|
7616
10464
|
progress: extraction.progress,
|
|
@@ -7619,10 +10467,35 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7619
10467
|
}
|
|
7620
10468
|
);
|
|
7621
10469
|
}
|
|
7622
|
-
return /* @__PURE__ */
|
|
10470
|
+
return /* @__PURE__ */ jsx31(Fragment8, {});
|
|
10471
|
+
}
|
|
10472
|
+
if (scopeRun && scopeFlow) {
|
|
10473
|
+
if (scopeFlow.status === "failed") {
|
|
10474
|
+
return /* @__PURE__ */ jsx31(ErrorStep, { stepName: "scope gate", message: scopeFlow.message, onExit: leaveImport });
|
|
10475
|
+
}
|
|
10476
|
+
if (scopeFlow.status === "deciding") {
|
|
10477
|
+
return /* @__PURE__ */ jsx31(
|
|
10478
|
+
ScopeGateScreen,
|
|
10479
|
+
{
|
|
10480
|
+
components: scopeFlow.load.components,
|
|
10481
|
+
onConfirm: scopeFlow.confirm,
|
|
10482
|
+
onQuit: leaveImport
|
|
10483
|
+
}
|
|
10484
|
+
);
|
|
10485
|
+
}
|
|
10486
|
+
const numbers = stepNumbers({ hasRawTokens: scopeRun.input.rawTokensPath !== "" });
|
|
10487
|
+
return /* @__PURE__ */ jsx31(
|
|
10488
|
+
RunningStep,
|
|
10489
|
+
{
|
|
10490
|
+
stepNumber: numbers.stepNumber + 1,
|
|
10491
|
+
totalSteps: numbers.totalSteps,
|
|
10492
|
+
title: "Preparing",
|
|
10493
|
+
description: "Checking which components are already generated..."
|
|
10494
|
+
}
|
|
10495
|
+
);
|
|
7623
10496
|
}
|
|
7624
10497
|
if (pendingLaunch?.cached) {
|
|
7625
|
-
return /* @__PURE__ */
|
|
10498
|
+
return /* @__PURE__ */ jsx31(
|
|
7626
10499
|
TokenReuseScreen,
|
|
7627
10500
|
{
|
|
7628
10501
|
tokensPath: pendingLaunch.cached.tokensPath,
|
|
@@ -7633,7 +10506,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7633
10506
|
}
|
|
7634
10507
|
);
|
|
7635
10508
|
}
|
|
7636
|
-
return /* @__PURE__ */
|
|
10509
|
+
return /* @__PURE__ */ jsx31(
|
|
7637
10510
|
CredentialsScreen,
|
|
7638
10511
|
{
|
|
7639
10512
|
initial: importDefaults.credentials,
|
|
@@ -7642,26 +10515,26 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
|
|
|
7642
10515
|
}
|
|
7643
10516
|
);
|
|
7644
10517
|
case "help":
|
|
7645
|
-
return /* @__PURE__ */
|
|
10518
|
+
return /* @__PURE__ */ jsx31(HelpScreen, { onDone: goToStart });
|
|
7646
10519
|
case "upgrade":
|
|
7647
|
-
return /* @__PURE__ */
|
|
10520
|
+
return /* @__PURE__ */ jsx31(UpgradeScreen, { onDone: goToStart });
|
|
7648
10521
|
case "settings":
|
|
7649
|
-
return /* @__PURE__ */
|
|
10522
|
+
return /* @__PURE__ */ jsx31(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
|
|
7650
10523
|
case "settings-configuration":
|
|
7651
|
-
return /* @__PURE__ */
|
|
10524
|
+
return /* @__PURE__ */ jsx31(ConfigurationScreen, { onDone: goToSettings });
|
|
7652
10525
|
case "settings-opt-in-analytics":
|
|
7653
|
-
return /* @__PURE__ */
|
|
10526
|
+
return /* @__PURE__ */ jsx31(OptInAnalyticsScreen, { onDone: goToSettings });
|
|
7654
10527
|
case "settings-debug-mode":
|
|
7655
|
-
return /* @__PURE__ */
|
|
10528
|
+
return /* @__PURE__ */ jsx31(DebugModeScreen, { onDone: goToSettings });
|
|
7656
10529
|
case "start":
|
|
7657
|
-
return /* @__PURE__ */
|
|
10530
|
+
return /* @__PURE__ */ jsx31(HomeScreen, { onNavigate: setScreen });
|
|
7658
10531
|
}
|
|
7659
10532
|
}
|
|
7660
10533
|
var CLEAR_SCREEN = "\x1B[2J\x1B[H";
|
|
7661
10534
|
async function renderUntilImportRequestedOrExit(renderApp, importOptions, importExitCode) {
|
|
7662
10535
|
let requestedImport;
|
|
7663
10536
|
const instance = renderApp(
|
|
7664
|
-
/* @__PURE__ */
|
|
10537
|
+
/* @__PURE__ */ jsx31(
|
|
7665
10538
|
App,
|
|
7666
10539
|
{
|
|
7667
10540
|
importOptions,
|