@starlein/paperclip-plugin-company-wizard 0.4.16 → 0.4.18
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/CHANGELOG.md +41 -0
- package/dist/manifest.js +1 -1
- package/dist/manifest.js.map +1 -1
- package/dist/ui/index.css +6 -0
- package/dist/ui/index.css.map +2 -2
- package/dist/ui/index.js +145 -6
- package/dist/ui/index.js.map +4 -4
- package/dist/worker.js +205 -84
- package/dist/worker.js.map +4 -4
- package/package.json +17 -17
- package/templates/bootstrap-instructions.md +0 -5
- package/templates/modules/dependency-management/agents/security-engineer/skills/dependency-audit.fallback.md +18 -0
- package/templates/modules/game-design/agents/engineer/skills/game-design.fallback.md +17 -0
- package/templates/modules/triage/agents/engineer/skills/issue-triage.fallback.md +20 -0
- package/templates/roles/engineer/HEARTBEAT.md +1 -1
package/dist/ui/index.js
CHANGED
|
@@ -581,7 +581,7 @@ var __iconNode45 = [
|
|
|
581
581
|
var Zap = createLucideIcon("zap", __iconNode45);
|
|
582
582
|
|
|
583
583
|
// src/ui/components/WizardShell.tsx
|
|
584
|
-
import { useEffect as useEffect9 } from "react";
|
|
584
|
+
import { useEffect as useEffect9, useRef as useRef8 } from "react";
|
|
585
585
|
|
|
586
586
|
// src/ui/context/WizardContext.tsx
|
|
587
587
|
import { createContext, useCallback, useContext, useState } from "react";
|
|
@@ -679,6 +679,8 @@ function reducer(state, action) {
|
|
|
679
679
|
}
|
|
680
680
|
case "GO_TO":
|
|
681
681
|
return { ...state, step: action.step, error: null };
|
|
682
|
+
case "RESTORE_NAV":
|
|
683
|
+
return { ...state, path: action.path, step: action.step, error: null };
|
|
682
684
|
case "SET_COMPANY_NAME":
|
|
683
685
|
return { ...state, companyName: action.value };
|
|
684
686
|
case "SET_GOALS":
|
|
@@ -4024,6 +4026,19 @@ CardFooter.displayName = "CardFooter";
|
|
|
4024
4026
|
|
|
4025
4027
|
// src/ui/components/steps/StepOnboarding.tsx
|
|
4026
4028
|
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
4029
|
+
async function upgradeInstalledPlugin(pluginId, version) {
|
|
4030
|
+
const response = await fetch(`/api/plugins/${encodeURIComponent(pluginId)}/upgrade`, {
|
|
4031
|
+
method: "POST",
|
|
4032
|
+
headers: { "Content-Type": "application/json" },
|
|
4033
|
+
credentials: "include",
|
|
4034
|
+
body: JSON.stringify({ version })
|
|
4035
|
+
});
|
|
4036
|
+
if (!response.ok) {
|
|
4037
|
+
const body = await response.json().catch(() => null);
|
|
4038
|
+
throw new Error(body?.error || `Plugin upgrade failed (${response.status})`);
|
|
4039
|
+
}
|
|
4040
|
+
return response.json();
|
|
4041
|
+
}
|
|
4027
4042
|
function PathCard({
|
|
4028
4043
|
icon: Icon2,
|
|
4029
4044
|
title,
|
|
@@ -4060,9 +4075,12 @@ function StepOnboarding() {
|
|
|
4060
4075
|
const dispatch = useWizardDispatch();
|
|
4061
4076
|
const refreshTemplates = usePluginAction("refresh-templates");
|
|
4062
4077
|
const checkUpdate = usePluginAction("check-update");
|
|
4078
|
+
const preparePluginUpdate = usePluginAction("prepare-plugin-update");
|
|
4063
4079
|
const [refreshing, setRefreshing] = useState2(false);
|
|
4064
4080
|
const [refreshMsg, setRefreshMsg] = useState2(null);
|
|
4065
4081
|
const [updateInfo, setUpdateInfo] = useState2(null);
|
|
4082
|
+
const [pluginUpdating, setPluginUpdating] = useState2(false);
|
|
4083
|
+
const [pluginUpdateMsg, setPluginUpdateMsg] = useState2(null);
|
|
4066
4084
|
useEffect(() => {
|
|
4067
4085
|
let cancelled = false;
|
|
4068
4086
|
checkUpdate({}).then((result) => {
|
|
@@ -4090,6 +4108,43 @@ function StepOnboarding() {
|
|
|
4090
4108
|
setRefreshing(false);
|
|
4091
4109
|
}
|
|
4092
4110
|
};
|
|
4111
|
+
const handlePluginUpdate = async () => {
|
|
4112
|
+
setPluginUpdating(true);
|
|
4113
|
+
setPluginUpdateMsg("Updating templates...");
|
|
4114
|
+
try {
|
|
4115
|
+
const prepared = await preparePluginUpdate({});
|
|
4116
|
+
if (!prepared?.ok) {
|
|
4117
|
+
throw new Error(prepared?.error || "Could not prepare plugin update");
|
|
4118
|
+
}
|
|
4119
|
+
if (!prepared.updateAvailable) {
|
|
4120
|
+
setUpdateInfo({
|
|
4121
|
+
ok: true,
|
|
4122
|
+
currentVersion: prepared.currentVersion,
|
|
4123
|
+
latestVersion: prepared.latestVersion,
|
|
4124
|
+
updateAvailable: false
|
|
4125
|
+
});
|
|
4126
|
+
setPluginUpdateMsg("Templates updated. Plugin is already current.");
|
|
4127
|
+
return;
|
|
4128
|
+
}
|
|
4129
|
+
if (!prepared.pluginId || !prepared.latestVersion) {
|
|
4130
|
+
throw new Error("Could not resolve installed plugin record or target version");
|
|
4131
|
+
}
|
|
4132
|
+
setPluginUpdateMsg(`Installing Company Wizard ${prepared.latestVersion}...`);
|
|
4133
|
+
await upgradeInstalledPlugin(prepared.pluginId, prepared.latestVersion);
|
|
4134
|
+
setUpdateInfo({
|
|
4135
|
+
ok: true,
|
|
4136
|
+
currentVersion: prepared.latestVersion,
|
|
4137
|
+
latestVersion: prepared.latestVersion,
|
|
4138
|
+
updateAvailable: false
|
|
4139
|
+
});
|
|
4140
|
+
setPluginUpdateMsg("Plugin updated. Reloading...");
|
|
4141
|
+
window.setTimeout(() => window.location.reload(), 1200);
|
|
4142
|
+
} catch (err) {
|
|
4143
|
+
setPluginUpdateMsg(err instanceof Error ? err.message : "Plugin update failed");
|
|
4144
|
+
} finally {
|
|
4145
|
+
setPluginUpdating(false);
|
|
4146
|
+
}
|
|
4147
|
+
};
|
|
4093
4148
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
|
|
4094
4149
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4095
4150
|
/* @__PURE__ */ jsx3("h1", { className: "text-2xl font-semibold tracking-tight", children: "Create a company" }),
|
|
@@ -4147,7 +4202,7 @@ function StepOnboarding() {
|
|
|
4147
4202
|
"button",
|
|
4148
4203
|
{
|
|
4149
4204
|
onClick: handleRefresh,
|
|
4150
|
-
disabled: refreshing,
|
|
4205
|
+
disabled: refreshing || pluginUpdating,
|
|
4151
4206
|
className: "flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50",
|
|
4152
4207
|
children: [
|
|
4153
4208
|
/* @__PURE__ */ jsx3(RefreshCw, { className: cn("h-3 w-3", refreshing && "animate-spin") }),
|
|
@@ -4163,14 +4218,28 @@ function StepOnboarding() {
|
|
|
4163
4218
|
updateInfo.currentVersion,
|
|
4164
4219
|
" \u2192 ",
|
|
4165
4220
|
updateInfo.latestVersion,
|
|
4221
|
+
/* @__PURE__ */ jsxs(
|
|
4222
|
+
"button",
|
|
4223
|
+
{
|
|
4224
|
+
type: "button",
|
|
4225
|
+
onClick: handlePluginUpdate,
|
|
4226
|
+
disabled: pluginUpdating,
|
|
4227
|
+
className: "inline-flex items-center gap-1 font-medium text-foreground hover:underline disabled:opacity-50 disabled:no-underline",
|
|
4228
|
+
title: "Install the latest Company Wizard plugin, refresh templates, and reload",
|
|
4229
|
+
children: [
|
|
4230
|
+
/* @__PURE__ */ jsx3(RefreshCw, { className: cn("h-3 w-3", pluginUpdating && "animate-spin") }),
|
|
4231
|
+
pluginUpdating ? "Updating..." : "Update now"
|
|
4232
|
+
]
|
|
4233
|
+
}
|
|
4234
|
+
),
|
|
4166
4235
|
updateInfo.url && /* @__PURE__ */ jsxs(
|
|
4167
4236
|
"a",
|
|
4168
4237
|
{
|
|
4169
4238
|
href: updateInfo.url,
|
|
4170
4239
|
target: "_blank",
|
|
4171
4240
|
rel: "noreferrer",
|
|
4172
|
-
className: "inline-flex items-center gap-0.5
|
|
4173
|
-
title: "
|
|
4241
|
+
className: "inline-flex items-center gap-0.5 text-muted-foreground hover:text-foreground hover:underline",
|
|
4242
|
+
title: "Open the npm package page",
|
|
4174
4243
|
children: [
|
|
4175
4244
|
"npm",
|
|
4176
4245
|
/* @__PURE__ */ jsx3(ExternalLink, { className: "h-3 w-3" })
|
|
@@ -4179,6 +4248,16 @@ function StepOnboarding() {
|
|
|
4179
4248
|
)
|
|
4180
4249
|
] })
|
|
4181
4250
|
] }),
|
|
4251
|
+
pluginUpdateMsg && /* @__PURE__ */ jsx3(
|
|
4252
|
+
"span",
|
|
4253
|
+
{
|
|
4254
|
+
className: cn(
|
|
4255
|
+
"basis-full text-center text-xs",
|
|
4256
|
+
pluginUpdateMsg.includes("failed") || pluginUpdateMsg.includes("Could not") ? "text-destructive" : "text-muted-foreground"
|
|
4257
|
+
),
|
|
4258
|
+
children: pluginUpdateMsg
|
|
4259
|
+
}
|
|
4260
|
+
),
|
|
4182
4261
|
refreshMsg && /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: refreshMsg })
|
|
4183
4262
|
] })
|
|
4184
4263
|
] });
|
|
@@ -6184,10 +6263,10 @@ function StepSummary() {
|
|
|
6184
6263
|
import { useState as useState8, useRef as useRef4, useEffect as useEffect5 } from "react";
|
|
6185
6264
|
import { usePluginAction as usePluginAction4 } from "@paperclipai/plugin-sdk/ui";
|
|
6186
6265
|
|
|
6187
|
-
// raw:/paperclip/paperclip-plugin-company-wizard/src/ui/prompts/interview-system.md
|
|
6266
|
+
// raw:/home/runner/work/paperclip-plugin-company-wizard/paperclip-plugin-company-wizard/src/ui/prompts/interview-system.md
|
|
6188
6267
|
var interview_system_default = 'You are the Company Wizard \u2014 an expert at assembling AI agent teams. You\'re enthusiastic but concise. Company Wizard bootstraps AI-agent company workspaces from composable templates.\n\nYou are conducting a guided interview to understand what company to set up.\n\n{{CATALOG}}\n\n## How Roles Work\n\n- **Base roles** (marked "always included") are auto-added. You do NOT list them in the JSON.\n- **All other roles** (listed under "Available Extra Roles") are OPTIONAL and must be EXPLICITLY listed in your JSON `roles` array if you want them.\n- **Critically: `engineer` is NOT a base role.** Most software projects need an engineer. If the project involves writing code, building software, or maintaining a repository, you MUST include `engineer` in your `roles` array. The preset does NOT auto-add roles \u2014 you must list every non-base role the company needs.\n- When in doubt, include the engineer. A company that builds software without an engineer agent will have no one to write code.\n\n## Interview Rules\n\n- Ask exactly ONE question per turn. Keep it short and energetic (1-2 sentences). Use a conversational tone.\n- Do NOT output JSON during questions \u2014 just ask the question as plain text.\n- Tailor each question based on previous answers. Show you understood what they said.\n- After 3 questions, summarize what you understood in a brief, enthusiastic paragraph. End with: "Ready to generate your configuration?"\n- When the user confirms, output a human-readable recommendation with reasoning, then the JSON config.\n\n## What to Ask About\n\nAcross your 3 questions, try to cover as many of these as the user\'s initial description left unclear:\n\n1. **What they\'re building** \u2014 Product type, target users, domain (fintech, SaaS, game, etc.)\n2. **Current stage** \u2014 Greenfield, existing codebase, research phase, relaunch?\n3. **Quality vs speed** \u2014 Ship fast, iterate? Or production-grade, high quality from the start?\n4. **Team needs** \u2014 Do they need code review, security, design, marketing, docs, DevOps?\n5. **Special requirements** \u2014 Compliance, accessibility, specific tech stack, CI/CD, game engine?\n6. **Repository** \u2014 Should Paperclip create a new Git repository/workspace, or should the agents use an existing external repo such as GitHub/GitLab? If external, ask for URL and branch/ref; never ask for tokens.\n\nDon\'t ask about things already clear from the initial description. Skip to what\'s missing.\n\n## Information Preservation\n\nThe user\'s interview answers are the primary source of context for the company. When generating the configuration:\n\n- **`companyDescription`**: Write a comprehensive 2-4 paragraph description that captures EVERYTHING learned during the interview \u2014 what the company does, what it\'s building, who it\'s for, key technical decisions, constraints, priorities, and any special context. This is the company\'s permanent record. Be thorough. Do NOT summarize into a single vague sentence.\n- **`goals`**: Array of goals. The first goal is the main user-specific company goal \u2014 its description is the most important field. Keep it outcome-first and product-first: the title and opening sentence must state the primary deliverable or operating outcome, not a supporting constraint. Write a THOROUGH, DETAILED description that includes EVERYTHING the user shared: full requirements, technical specs, acceptance criteria, constraints, edge cases, API contracts, user stories, design decisions, performance targets. Put compliance/security/accessibility/performance constraints in a clearly labelled "Constraints / quality bars" section unless the user explicitly says that constraint is the primary project. If the user\'s wording mixes a main outcome with secondary facts, determine which thing the agents should build/operate first and write that as the top-level goal; put side facts into acceptance criteria, risks, or sub-goals only when they are independent workstreams. Preset/module template goals are added by the wizard after your JSON, so do NOT replace the user\'s objective with generic preset goals like "Build a REST API" or "Set up CI/CD" unless the user explicitly asked only for that.\n- **`projects`**: Array of projects. Each has a `name`, `description`, `goals` array (goal titles it\'s linked to), and repository workspace metadata. If the user chose an external repo, use `workspace.sourceType: "git_repo"` with `repoUrl`, plus `repoRef`/`defaultRef` exactly when the user or repository context provides one; do not force a branch name or remote prefix. If no external repo was provided, use a fresh local Git repository with `workspace.sourceType: "local_path"`, `workspace.defaultRef: "main"` unless the user requested another initial branch, `workspace.setupCommand: "git init -b <defaultRef>"`, and `workspace.isPrimary: true`. Do not include `executionWorkspacePolicy`; the assembler applies isolated worktrees only when Paperclip\'s experimental isolated-workspaces setting is enabled and a usable project base ref exists.\n- **`issues`**: Array of 6-12 CONCRETE, domain-specific initial work items taken straight from what you learned in the interview \u2014 the real features, components, and integrations the user actually described, each with a `title`, a `description` with acceptance criteria, a `priority` (`critical`/`high`/`medium`/`low`), and `assignTo` set to a role on the team. These seed the backlog so the project starts in its actual domain. Issue titles should lead with the core product capability; secondary constraints belong in acceptance criteria or risk notes unless the issue is specifically about that constraint. Do NOT put generic scaffolding here (vision docs, linters, CI, branch protection) \u2014 the wizard adds those automatically.\n\n## RECOMMENDATION Format (when generating config)\n\n- One paragraph explaining your reasoning: why this preset, why these modules, why these roles.\n- A bullet list of the key choices.\n\nThen output the JSON (no markdown fences):\n{{CONFIG_FORMAT}}\n\n## Rules\n\n- `modules` should list ALL modules to activate (including preset ones).\n- `roles` should list ALL non-base roles the company needs. This includes roles that come with the preset. The system does not auto-add preset roles \u2014 you must list them explicitly.\n- If the project involves building software, `engineer` MUST be in `roles`.\n- The primary project MUST state whether it uses a fresh local Git repository or an external Git repository. Do not put credentials or tokens in repository fields.\n- Be pragmatic \u2014 don\'t over-engineer. Match the config to actual needs.\n';
|
|
6189
6268
|
|
|
6190
|
-
// raw:/paperclip/paperclip-plugin-company-wizard/src/ui/prompts/single-shot-system.md
|
|
6269
|
+
// raw:/home/runner/work/paperclip-plugin-company-wizard/paperclip-plugin-company-wizard/src/ui/prompts/single-shot-system.md
|
|
6191
6270
|
var single_shot_system_default = 'You are the Company Wizard. Company Wizard bootstraps AI-agent company workspaces from composable templates.\n\nGiven a natural language description of what the user wants to build, you select the best configuration.\n\n{{CATALOG}}\n\n## How Roles Work\n\n- **Base roles** (marked "always included") are auto-added. You do NOT list them in the JSON.\n- **All other roles** (listed under "Available Extra Roles") are OPTIONAL and must be EXPLICITLY listed in your JSON `roles` array if you want them.\n- **Critically: `engineer` is NOT a base role.** Most software projects need an engineer. If the project involves writing code, building software, or maintaining a repository, you MUST include `engineer` in your `roles` array. The preset does NOT auto-add roles \u2014 you must list every non-base role the company needs.\n- When in doubt, include the engineer. A company that builds software without an engineer agent will have no one to write code.\n\n## Instructions\n\n1. Analyze the user\'s description to understand: what they\'re building, their team size preference, quality vs speed priority, and any specific needs.\n2. Select the best preset as a starting point.\n3. List ALL modules to activate (including preset ones). Add extra modules beyond the preset if the description warrants them.\n4. List ALL non-base roles the company needs. This includes roles from the preset. If the project involves software, include `engineer`.\n5. Suggest a company name (PascalCase-friendly, short, memorable) if not obvious from the description.\n6. Write a thorough company description (2-4 paragraphs) capturing everything the user described \u2014 product, audience, tech stack, constraints, priorities, stage, and special context. This is the company\'s permanent record.\n7. Define goals as an array. The first goal is the main user-specific company goal \u2014 its description is the most important field. Keep it **outcome-first and product-first**: the title and opening sentence must state the primary deliverable or operating outcome, not a supporting constraint. Preserve compliance, security, accessibility, performance, tech-stack, and domain constraints inside the description under a clear "Constraints / quality bars" section unless the user explicitly says that constraint is the primary project. If the user\'s wording mixes a main outcome with secondary facts, ask yourself which thing the agents should build/operate first and write that as the top-level goal; put side facts into acceptance criteria, risks, or sub-goals only when they are independent workstreams. Include EVERYTHING the user described: full requirements, technical specs, acceptance criteria, constraints, edge cases, API contracts, user stories, performance targets. If the user provided a detailed spec, reproduce it in full, but do not let one constraint dominate the goal or initial issues. Preset/module template goals are added by the wizard after your JSON, so do NOT replace the user\'s objective with generic preset goals like "Build a REST API" or "Set up CI/CD" unless the user explicitly asked only for that.\n8. Define projects as an array. Most setups need one project linked to all goals. Name and describe the project concretely.\n9. Always decide the repository setup for the primary project:\n - If the user gives an existing GitHub/GitLab/remote Git repo, set `workspace.sourceType: "git_repo"`, include `repoUrl`, and set `repoRef`/`defaultRef` exactly when the user or repository context provides one. Do not force a branch name or remote prefix; Paperclip\'s project/worktree settings decide the worktree base ref.\n - If no external repository is given, assume Paperclip should create a fresh local Git repository. Set `workspace.sourceType: "local_path"`, `workspace.defaultRef: "main"` unless the user requested another initial branch, `workspace.setupCommand: "git init -b <defaultRef>"`, and `workspace.isPrimary: true`. Do NOT include an `executionWorkspacePolicy`; the assembler applies isolated worktrees only when Paperclip\'s experimental isolated-workspaces setting is enabled and a usable project base ref exists.\n - Never include credentials or tokens in repository URLs or project text.\n10. Define an `issues` array of 6-12 CONCRETE, domain-specific initial work items taken straight from the description \u2014 the real features, components, and integrations the user actually described, each with a `title`, a `description` with acceptance criteria, a `priority`, and `assignTo` set to a role on the team. These seed the backlog so the project starts in its actual domain instead of only doing generic setup. Issue titles should lead with the core product capability; secondary constraints belong in acceptance criteria or risk notes unless the issue is specifically about that constraint. Do NOT put generic scaffolding here (vision docs, linters, CI, branch protection) \u2014 the wizard adds those automatically.\n\nFirst write one paragraph explaining your reasoning: why this preset, why these modules, why these roles.\n\nThen output the JSON (no markdown fences):\n{{CONFIG_FORMAT}}\n';
|
|
6192
6271
|
|
|
6193
6272
|
// src/ui/prompts/messages.json
|
|
@@ -7555,6 +7634,30 @@ var STEP_COMPONENTS = {
|
|
|
7555
7634
|
provision: StepProvision,
|
|
7556
7635
|
done: StepDone
|
|
7557
7636
|
};
|
|
7637
|
+
var WIZARD_HISTORY_MARKER = "company-wizard";
|
|
7638
|
+
function isObject(value) {
|
|
7639
|
+
return typeof value === "object" && value !== null;
|
|
7640
|
+
}
|
|
7641
|
+
function isStep(value) {
|
|
7642
|
+
return typeof value === "string" && value in STEP_COMPONENTS;
|
|
7643
|
+
}
|
|
7644
|
+
function isWizardPath(value) {
|
|
7645
|
+
return value === null || value === "manual" || value === "ai" || value === "update";
|
|
7646
|
+
}
|
|
7647
|
+
function readWizardHistoryState(value) {
|
|
7648
|
+
if (!isObject(value)) return null;
|
|
7649
|
+
if (value.__paperclipPlugin !== WIZARD_HISTORY_MARKER) return null;
|
|
7650
|
+
if (!isStep(value.step) || !isWizardPath(value.path)) return null;
|
|
7651
|
+
return { step: value.step, path: value.path };
|
|
7652
|
+
}
|
|
7653
|
+
function buildWizardHistoryState(currentState, path, step) {
|
|
7654
|
+
return {
|
|
7655
|
+
...isObject(currentState) ? currentState : {},
|
|
7656
|
+
__paperclipPlugin: WIZARD_HISTORY_MARKER,
|
|
7657
|
+
path,
|
|
7658
|
+
step
|
|
7659
|
+
};
|
|
7660
|
+
}
|
|
7558
7661
|
function StepIndicator() {
|
|
7559
7662
|
const state = useWizard();
|
|
7560
7663
|
const current = getUserStepIndex(state);
|
|
@@ -7579,10 +7682,46 @@ function StepIndicator() {
|
|
|
7579
7682
|
function WizardShell() {
|
|
7580
7683
|
const state = useWizard();
|
|
7581
7684
|
const dispatch = useWizardDispatch();
|
|
7685
|
+
const restoredFromHistory = useRef8(false);
|
|
7686
|
+
const seededHistory = useRef8(false);
|
|
7582
7687
|
const StepComponent = STEP_COMPONENTS[state.step];
|
|
7583
7688
|
useEffect9(() => {
|
|
7584
7689
|
window.scrollTo({ top: 0 });
|
|
7585
7690
|
}, [state.step]);
|
|
7691
|
+
useEffect9(() => {
|
|
7692
|
+
const handlePopState = (event) => {
|
|
7693
|
+
const historyState = readWizardHistoryState(event.state);
|
|
7694
|
+
if (!historyState?.step) return;
|
|
7695
|
+
restoredFromHistory.current = true;
|
|
7696
|
+
dispatch({
|
|
7697
|
+
type: "RESTORE_NAV",
|
|
7698
|
+
path: historyState.path ?? null,
|
|
7699
|
+
step: historyState.step
|
|
7700
|
+
});
|
|
7701
|
+
};
|
|
7702
|
+
window.addEventListener("popstate", handlePopState);
|
|
7703
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
7704
|
+
}, [dispatch]);
|
|
7705
|
+
useEffect9(() => {
|
|
7706
|
+
if (!seededHistory.current) {
|
|
7707
|
+
seededHistory.current = true;
|
|
7708
|
+
window.history.replaceState(
|
|
7709
|
+
buildWizardHistoryState(window.history.state, state.path, state.step),
|
|
7710
|
+
"",
|
|
7711
|
+
window.location.href
|
|
7712
|
+
);
|
|
7713
|
+
return;
|
|
7714
|
+
}
|
|
7715
|
+
if (restoredFromHistory.current) {
|
|
7716
|
+
restoredFromHistory.current = false;
|
|
7717
|
+
return;
|
|
7718
|
+
}
|
|
7719
|
+
window.history.pushState(
|
|
7720
|
+
buildWizardHistoryState(window.history.state, state.path, state.step),
|
|
7721
|
+
"",
|
|
7722
|
+
window.location.href
|
|
7723
|
+
);
|
|
7724
|
+
}, [state.path, state.step]);
|
|
7586
7725
|
return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col", children: [
|
|
7587
7726
|
getUserStepIndex(state) >= 1 && state.step !== "provision" && state.step !== "done" && /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-end px-6 py-3", children: /* @__PURE__ */ jsx21(StepIndicator, {}) }),
|
|
7588
7727
|
/* @__PURE__ */ jsx21("main", { className: "flex-1 flex items-start justify-center p-6", children: /* @__PURE__ */ jsx21("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsx21(StepComponent, {}) }) }),
|