@opentrace/components 0.1.1-rc.77 → 0.1.1-rc.78

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.
@@ -165,6 +165,26 @@ function FolderIcon() {
165
165
  }
166
166
  );
167
167
  }
168
+ function ImportIcon() {
169
+ return /* @__PURE__ */ jsxs(
170
+ "svg",
171
+ {
172
+ width: "38",
173
+ height: "38",
174
+ viewBox: "0 0 24 24",
175
+ fill: "none",
176
+ stroke: "currentColor",
177
+ strokeWidth: "1.5",
178
+ strokeLinecap: "round",
179
+ strokeLinejoin: "round",
180
+ children: [
181
+ /* @__PURE__ */ jsx("ellipse", { cx: "12", cy: "5", rx: "9", ry: "3" }),
182
+ /* @__PURE__ */ jsx("path", { d: "M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" }),
183
+ /* @__PURE__ */ jsx("path", { d: "M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" })
184
+ ]
185
+ }
186
+ );
187
+ }
168
188
  const PROVIDER_DISPLAY_NAME = {
169
189
  github: "GitHub",
170
190
  gitlab: "GitLab",
@@ -225,7 +245,10 @@ function AddRepoModal({
225
245
  const [loading, setLoading] = useState(false);
226
246
  const [error, setError] = useState(null);
227
247
  const [selectedFiles, setSelectedFiles] = useState(null);
248
+ const [importFile, setImportFile] = useState(null);
249
+ const [dragging, setDragging] = useState(false);
228
250
  const fileInputRef = useRef(null);
251
+ const importInputRef = useRef(null);
229
252
  const urlInputRef = useRef(null);
230
253
  const dropdownRef = useRef(null);
231
254
  useEffect(() => {
@@ -263,6 +286,20 @@ function AddRepoModal({
263
286
  }, [source]);
264
287
  function handleSubmit(e) {
265
288
  e.preventDefault();
289
+ if (source === "import") {
290
+ if (!importFile) {
291
+ setError("Select a .db file first.");
292
+ return;
293
+ }
294
+ setError(null);
295
+ setLoading(true);
296
+ onSubmit({
297
+ type: "import-file",
298
+ file: importFile,
299
+ name: importFile.name.replace(/\.json$/i, "")
300
+ });
301
+ return;
302
+ }
266
303
  if (source === "directory") {
267
304
  if (!selectedFiles || selectedFiles.length === 0) {
268
305
  setError("Select a directory first.");
@@ -300,9 +337,9 @@ function AddRepoModal({
300
337
  ref: ref || void 0
301
338
  });
302
339
  }
303
- const heroIcon = source === "directory" ? /* @__PURE__ */ jsx("div", { className: "hero-icon hero-icon--provider", children: /* @__PURE__ */ jsx(FolderIcon, {}) }) : /* @__PURE__ */ jsx(ProviderIconStrip, { selected: provider });
304
- const title = source === "directory" ? "Add Local Directory" : provider ? `Add from ${PROVIDER_DISPLAY_NAME[provider]}` : "Add Repository";
305
- const subtitle = source === "directory" ? "Select a directory to index its structure into the graph" : provider ? `Enter a ${PROVIDER_DISPLAY_NAME[provider]} repository URL to index` : "Enter a repository URL to index its structure into the graph";
340
+ const heroIcon = source === "import" ? /* @__PURE__ */ jsx("div", { className: "hero-icon hero-icon--provider", children: /* @__PURE__ */ jsx(ImportIcon, {}) }) : source === "directory" ? /* @__PURE__ */ jsx("div", { className: "hero-icon hero-icon--provider", children: /* @__PURE__ */ jsx(FolderIcon, {}) }) : /* @__PURE__ */ jsx(ProviderIconStrip, { selected: provider });
341
+ const title = source === "import" ? "Import Graph" : source === "directory" ? "Add Local Directory" : provider ? `Add from ${PROVIDER_DISPLAY_NAME[provider]}` : "Add Repository";
342
+ const subtitle = source === "import" ? "Upload a LadybugDB file to load into the graph" : source === "directory" ? "Select a directory to index its structure into the graph" : provider ? `Enter a ${PROVIDER_DISPLAY_NAME[provider]} repository URL to index` : "Enter a repository URL to index its structure into the graph";
306
343
  return /* @__PURE__ */ jsx("div", { className: "modal-backdrop", onClick: dismissable ? onClose : void 0, children: /* @__PURE__ */ jsxs("div", { className: "modal-card", onClick: (e) => e.stopPropagation(), children: [
307
344
  /* @__PURE__ */ jsx("div", { className: "source-toggle", children: /* @__PURE__ */ jsxs("div", { className: "chip-toggle", children: [
308
345
  /* @__PURE__ */ jsx(
@@ -322,6 +359,15 @@ function AddRepoModal({
322
359
  onClick: () => setSource("directory"),
323
360
  children: "Directory"
324
361
  }
362
+ ),
363
+ /* @__PURE__ */ jsx(
364
+ "button",
365
+ {
366
+ type: "button",
367
+ className: `chip-toggle-btn${source === "import" ? " active" : ""}`,
368
+ onClick: () => setSource("import"),
369
+ children: "Import"
370
+ }
325
371
  )
326
372
  ] }) }),
327
373
  /* @__PURE__ */ jsxs("div", { className: "form-hero", children: [
@@ -330,7 +376,120 @@ function AddRepoModal({
330
376
  /* @__PURE__ */ jsx("p", { className: "hero-subtitle", children: subtitle })
331
377
  ] }),
332
378
  /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
333
- /* @__PURE__ */ jsx("div", { className: "form-fields", children: source === "url" ? /* @__PURE__ */ jsxs(Fragment, { children: [
379
+ /* @__PURE__ */ jsx("div", { className: "form-fields", children: source === "import" ? /* @__PURE__ */ jsxs("div", { className: "import-picker", children: [
380
+ /* @__PURE__ */ jsx(
381
+ "input",
382
+ {
383
+ ref: importInputRef,
384
+ type: "file",
385
+ accept: ".db",
386
+ className: "directory-input",
387
+ onChange: (e) => setImportFile(e.target.files?.[0] ?? null)
388
+ }
389
+ ),
390
+ /* @__PURE__ */ jsx(
391
+ "div",
392
+ {
393
+ className: `import-dropzone${dragging ? " import-dropzone--active" : ""}${importFile ? " import-dropzone--has-file" : ""}`,
394
+ onClick: () => importInputRef.current?.click(),
395
+ onDragOver: (e) => {
396
+ e.preventDefault();
397
+ e.stopPropagation();
398
+ setDragging(true);
399
+ },
400
+ onDragEnter: (e) => {
401
+ e.preventDefault();
402
+ e.stopPropagation();
403
+ setDragging(true);
404
+ },
405
+ onDragLeave: (e) => {
406
+ e.preventDefault();
407
+ e.stopPropagation();
408
+ setDragging(false);
409
+ },
410
+ onDrop: (e) => {
411
+ e.preventDefault();
412
+ e.stopPropagation();
413
+ setDragging(false);
414
+ const file = e.dataTransfer.files?.[0];
415
+ if (file) setImportFile(file);
416
+ },
417
+ children: importFile ? /* @__PURE__ */ jsxs(Fragment, { children: [
418
+ /* @__PURE__ */ jsxs(
419
+ "svg",
420
+ {
421
+ className: "import-dropzone-icon",
422
+ width: "20",
423
+ height: "20",
424
+ viewBox: "0 0 24 24",
425
+ fill: "none",
426
+ stroke: "currentColor",
427
+ strokeWidth: "2",
428
+ strokeLinecap: "round",
429
+ strokeLinejoin: "round",
430
+ children: [
431
+ /* @__PURE__ */ jsx("ellipse", { cx: "12", cy: "5", rx: "9", ry: "3" }),
432
+ /* @__PURE__ */ jsx("path", { d: "M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" }),
433
+ /* @__PURE__ */ jsx("path", { d: "M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" })
434
+ ]
435
+ }
436
+ ),
437
+ /* @__PURE__ */ jsx("span", { className: "import-dropzone-filename", children: importFile.name }),
438
+ /* @__PURE__ */ jsxs("span", { className: "import-dropzone-size", children: [
439
+ (importFile.size / 1024 / 1024).toFixed(1),
440
+ " MB"
441
+ ] })
442
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
443
+ /* @__PURE__ */ jsxs(
444
+ "svg",
445
+ {
446
+ className: "import-dropzone-icon",
447
+ width: "24",
448
+ height: "24",
449
+ viewBox: "0 0 24 24",
450
+ fill: "none",
451
+ stroke: "currentColor",
452
+ strokeWidth: "1.5",
453
+ strokeLinecap: "round",
454
+ strokeLinejoin: "round",
455
+ children: [
456
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
457
+ /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
458
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
459
+ ]
460
+ }
461
+ ),
462
+ /* @__PURE__ */ jsx("span", { className: "import-dropzone-label", children: "Drop .db file here or click to browse" })
463
+ ] })
464
+ }
465
+ ),
466
+ /* @__PURE__ */ jsxs("div", { className: "form-info", children: [
467
+ /* @__PURE__ */ jsxs(
468
+ "svg",
469
+ {
470
+ width: "14",
471
+ height: "14",
472
+ viewBox: "0 0 24 24",
473
+ fill: "none",
474
+ stroke: "currentColor",
475
+ strokeWidth: "2",
476
+ strokeLinecap: "round",
477
+ strokeLinejoin: "round",
478
+ children: [
479
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
480
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
481
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
482
+ ]
483
+ }
484
+ ),
485
+ /* @__PURE__ */ jsxs("span", { children: [
486
+ "Upload a LadybugDB database file (typically",
487
+ " ",
488
+ /* @__PURE__ */ jsx("code", { className: "form-info-code", children: ".opentrace/index.db" }),
489
+ ") generated by the OpenTrace agent."
490
+ ] })
491
+ ] })
492
+ ] }) : source === "url" ? /* @__PURE__ */ jsxs(Fragment, { children: [
334
493
  /* @__PURE__ */ jsxs("div", { className: "form-info", children: [
335
494
  /* @__PURE__ */ jsxs(
336
495
  "svg",
@@ -641,9 +800,9 @@ function AddRepoModal({
641
800
  disabled: loading || !!validationMessage,
642
801
  children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
643
802
  /* @__PURE__ */ jsx("span", { className: "btn-spinner" }),
644
- "Indexing..."
803
+ source === "import" ? "Importing..." : "Indexing..."
645
804
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
646
- "Add & Index",
805
+ source === "import" ? "Import" : "Add & Index",
647
806
  /* @__PURE__ */ jsxs(
648
807
  "svg",
649
808
  {
@@ -987,4 +1146,4 @@ export {
987
1146
  detectProvider as d,
988
1147
  normalizeRepoUrl as n
989
1148
  };
990
- //# sourceMappingURL=urlNormalize-KY4ngwCQ.js.map
1149
+ //# sourceMappingURL=urlNormalize-D4tuih2G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlNormalize-D4tuih2G.js","sources":["../src/indexing/AddRepoModal.tsx","../src/indexing/IndexingProgress.tsx","../src/indexing/urlNormalize.ts"],"sourcesContent":["/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type FormEvent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { AddRepoModalProps } from './types';\nimport './indexing-base.css';\nimport './AddRepoModal.css';\n\ntype SourceMode = 'url' | 'directory' | 'import';\n\nexport function detectProvider(\n url: string,\n): 'github' | 'gitlab' | 'bitbucket' | 'azuredevops' | null {\n const lower = url.toLowerCase();\n if (lower.includes('github')) return 'github';\n if (lower.includes('gitlab')) return 'gitlab';\n if (lower.includes('bitbucket')) return 'bitbucket';\n if (lower.includes('dev.azure.com') || lower.includes('visualstudio.com'))\n return 'azuredevops';\n return null;\n}\n\nconst HISTORY_KEY = 'ot_repo_history';\nconst MAX_HISTORY = 5;\n\nfunction loadHistory(): string[] {\n try {\n const raw = localStorage.getItem(HISTORY_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed)\n ? parsed.filter((item): item is string => typeof item === 'string')\n : [];\n } catch {\n return [];\n }\n}\n\nfunction saveToHistory(url: string) {\n const history = loadHistory().filter((u) => u !== url);\n history.unshift(url);\n localStorage.setItem(\n HISTORY_KEY,\n JSON.stringify(history.slice(0, MAX_HISTORY)),\n );\n}\n\nfunction removeFromHistory(url: string): string[] {\n const updated = loadHistory().filter((u) => u !== url);\n localStorage.setItem(HISTORY_KEY, JSON.stringify(updated));\n return updated;\n}\n\nconst PROVIDER_ORDER = [\n 'github',\n 'gitlab',\n 'bitbucket',\n 'azuredevops',\n] as const;\n\n/**\n * Clip-path polygons for each provider's quadrant.\n * All use 4-point polygons so CSS can interpolate between states.\n *\n * Layout: GitHub=top, GitLab=right, Bitbucket=bottom, AzureDevOps=left\n */\nconst QUADRANT_CLIPS: Record<\n string,\n { quarter: string; full: string; hidden: string }\n> = {\n github: {\n // top triangle\n quarter: 'polygon(0% 0%, 100% 0%, 50% 50%, 50% 50%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n gitlab: {\n // right triangle\n quarter: 'polygon(50% 50%, 100% 0%, 100% 100%, 50% 50%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n bitbucket: {\n // bottom triangle\n quarter: 'polygon(50% 50%, 50% 50%, 100% 100%, 0% 100%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n azuredevops: {\n // left triangle\n quarter: 'polygon(0% 0%, 50% 50%, 50% 50%, 0% 100%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n};\n\n/** Full-size SVGs (fill their container) for the clip-path composite. */\nconst PROVIDER_FULL_SVG: Record<string, () => ReactNode> = {\n github: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z\" />\n </svg>\n ),\n gitlab: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 380 380\" fill=\"currentColor\">\n <path d=\"M190 353.9L131.1 172.8h117.8L190 353.9z\" opacity=\"0.85\" />\n <path d=\"M190 353.9L131.1 172.8H15.6L190 353.9z\" opacity=\"0.7\" />\n <path\n d=\"M15.6 172.8L0.4 219.5c-1.4 4.3 0.1 9 3.8 11.7L190 353.9 15.6 172.8z\"\n opacity=\"0.55\"\n />\n <path\n d=\"M15.6 172.8h115.5L87.6 26.5c-1.6-4.9-8.5-4.9-10.1 0L15.6 172.8z\"\n opacity=\"0.85\"\n />\n <path d=\"M190 353.9l58.9-181.1h115.5L190 353.9z\" opacity=\"0.7\" />\n <path\n d=\"M364.4 172.8l15.2 46.7c1.4 4.3-0.1 9-3.8 11.7L190 353.9l174.4-181.1z\"\n opacity=\"0.55\"\n />\n <path\n d=\"M364.4 172.8H248.9l43.5-146.3c1.6-4.9 8.5-4.9 10.1 0l61.9 146.3z\"\n opacity=\"0.85\"\n />\n </svg>\n ),\n bitbucket: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 32 32\" fill=\"currentColor\">\n <path d=\"M2.278 2.133a1.07 1.07 0 00-1.07 1.236l4.058 24.637a1.45 1.45 0 001.417 1.195h19.1a1.07 1.07 0 001.07-.903l4.058-24.93a1.07 1.07 0 00-1.07-1.236zm16.7 17.757h-6.1l-1.647-8.613h9.2z\" />\n </svg>\n ),\n azuredevops: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M15 3.622v8.512L11.5 15l-5.425-1.975v1.958L3.004 10.97l8.951.7V4.005L15 3.622zm-2.984.428L6.994 1v2.001L2.382 4.356 1 6.13v4.029l1.978.873V5.869l9.038-1.819z\" />\n </svg>\n ),\n};\n\nfunction ProviderIconStrip({ selected }: { selected: string | null }) {\n return (\n <div className={'hero-icon' + (selected ? ' hero-icon--provider' : '')}>\n {/* X-shaped divider lines */}\n <svg\n className={`quad-dividers${selected ? ' quad-dividers--hidden' : ''}`}\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 64 64\"\n >\n <line\n x1=\"0\"\n y1=\"0\"\n x2=\"64\"\n y2=\"64\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n opacity=\"0.2\"\n />\n <line\n x1=\"64\"\n y1=\"0\"\n x2=\"0\"\n y2=\"64\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n opacity=\"0.2\"\n />\n </svg>\n {/* Four icon layers, each clipped to a quadrant */}\n {PROVIDER_ORDER.map((key) => {\n const Icon = PROVIDER_FULL_SVG[key];\n const clips = QUADRANT_CLIPS[key];\n const clip = !selected\n ? clips.quarter\n : key === selected\n ? clips.full\n : clips.hidden;\n return (\n <div key={key} className=\"quad-layer\" style={{ clipPath: clip }}>\n <Icon />\n </div>\n );\n })}\n </div>\n );\n}\n\nfunction FolderIcon() {\n return (\n <svg\n width=\"38\"\n height=\"38\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\nfunction ImportIcon() {\n return (\n <svg\n width=\"38\"\n height=\"38\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n );\n}\n\nconst PROVIDER_DISPLAY_NAME: Record<string, string> = {\n github: 'GitHub',\n gitlab: 'GitLab',\n bitbucket: 'Bitbucket',\n azuredevops: 'Azure DevOps',\n};\n\n// --- Example Repositories ---\n\ntype RepoSize = 'S' | 'M' | 'L';\n\nconst EXAMPLE_REPOS: {\n name: string;\n url: string;\n description: string;\n size: RepoSize;\n}[] = [\n {\n name: 'OpenTrace',\n url: 'https://github.com/opentrace/opentrace',\n description: 'Knowledge graph for system architecture and code structure',\n size: 'M',\n },\n {\n name: 'OpenTelemetry Demo',\n url: 'https://github.com/open-telemetry/opentelemetry-demo',\n description: 'Microservices demo with OTel instrumentation',\n size: 'M',\n },\n {\n name: 'Express.js',\n url: 'https://github.com/expressjs/express',\n description: 'Fast, minimalist web framework for Node.js',\n size: 'S',\n },\n {\n name: 'Podinfo',\n url: 'https://github.com/stefanprodan/podinfo',\n description: 'Go microservice template for Kubernetes',\n size: 'S',\n },\n {\n name: 'Grafana',\n url: 'https://github.com/grafana/grafana',\n description: 'Open-source observability and monitoring platform',\n size: 'L',\n },\n {\n name: 'Linux',\n url: 'https://github.com/torvalds/linux',\n description: 'Linux kernel source tree',\n size: 'L',\n },\n];\n\n// --- Main Component ---\n\nexport default function AddRepoModal({\n onClose,\n onSubmit,\n dismissable = true,\n onValidate,\n}: AddRepoModalProps) {\n const [source, setSource] = useState<SourceMode>('url');\n const [repoUrl, setRepoUrl] = useState('');\n const [history, setHistory] = useState<string[]>(loadHistory);\n const [showHistory, setShowHistory] = useState(false);\n const [ref, setRef] = useState('');\n const [pat, setPat] = useState('');\n const [showPat, setShowPat] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [selectedFiles, setSelectedFiles] = useState<FileList | null>(null);\n const [importFile, setImportFile] = useState<File | null>(null);\n const [dragging, setDragging] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const importInputRef = useRef<HTMLInputElement>(null);\n const urlInputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Reliably focus the URL input when the modal mounts\n useEffect(() => {\n if (source === 'url') {\n urlInputRef.current?.focus();\n }\n }, [source]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClick(e: MouseEvent) {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(e.target as Node) &&\n e.target !== urlInputRef.current\n ) {\n setShowHistory(false);\n }\n }\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, []);\n\n const filteredHistory = history.filter(\n (url) => !repoUrl || url.toLowerCase().includes(repoUrl.toLowerCase()),\n );\n\n const provider = source === 'url' ? detectProvider(repoUrl) : null;\n const patStorageKey = provider ? `ot_${provider}_pat` : null;\n\n // Let the consumer validate the URL (e.g. duplicate detection)\n const validationMessage = useMemo(() => {\n if (source !== 'url' || !repoUrl.trim() || !onValidate) return null;\n return onValidate(repoUrl);\n }, [source, repoUrl, onValidate]);\n\n // Derive directory name from FileList\n const directoryName =\n selectedFiles?.[0]?.webkitRelativePath?.split('/')[0] ?? '';\n\n // Load saved PAT for the detected provider\n useEffect(() => {\n if (!provider || !patStorageKey) return;\n const saved = localStorage.getItem(patStorageKey);\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing from localStorage\n if (saved) setPat(saved);\n else setPat('');\n }, [provider, patStorageKey]);\n\n // Clear errors when switching source mode\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- reset on dep change\n setError(null);\n }, [source]);\n\n function handleSubmit(e: FormEvent) {\n e.preventDefault();\n\n if (source === 'import') {\n if (!importFile) {\n setError('Select a .db file first.');\n return;\n }\n setError(null);\n setLoading(true);\n onSubmit({\n type: 'import-file',\n file: importFile,\n name: importFile.name.replace(/\\.json$/i, ''),\n });\n return;\n }\n\n if (source === 'directory') {\n if (!selectedFiles || selectedFiles.length === 0) {\n setError('Select a directory first.');\n return;\n }\n setError(null);\n setLoading(true);\n onSubmit({\n type: 'index-directory',\n files: selectedFiles,\n name: directoryName || 'local',\n });\n return;\n }\n\n // URL mode\n if (!provider) {\n setError(\n 'Enter a GitHub, GitLab, Bitbucket, or Azure DevOps repository URL.',\n );\n return;\n }\n if (validationMessage) {\n return;\n }\n setError(null);\n setLoading(true);\n\n if (patStorageKey) {\n if (pat) localStorage.setItem(patStorageKey, pat);\n else localStorage.removeItem(patStorageKey);\n }\n\n saveToHistory(repoUrl);\n\n onSubmit({\n type: 'index-repo',\n repoUrl,\n token: pat || undefined,\n ref: ref || undefined,\n });\n }\n\n // --- Hero content based on source mode ---\n\n const heroIcon =\n source === 'import' ? (\n <div className=\"hero-icon hero-icon--provider\">\n <ImportIcon />\n </div>\n ) : source === 'directory' ? (\n <div className=\"hero-icon hero-icon--provider\">\n <FolderIcon />\n </div>\n ) : (\n <ProviderIconStrip selected={provider} />\n );\n\n const title =\n source === 'import'\n ? 'Import Graph'\n : source === 'directory'\n ? 'Add Local Directory'\n : provider\n ? `Add from ${PROVIDER_DISPLAY_NAME[provider]}`\n : 'Add Repository';\n\n const subtitle =\n source === 'import'\n ? 'Upload a LadybugDB file to load into the graph'\n : source === 'directory'\n ? 'Select a directory to index its structure into the graph'\n : provider\n ? `Enter a ${PROVIDER_DISPLAY_NAME[provider]} repository URL to index`\n : 'Enter a repository URL to index its structure into the graph';\n\n return (\n <div className=\"modal-backdrop\" onClick={dismissable ? onClose : undefined}>\n <div className=\"modal-card\" onClick={(e) => e.stopPropagation()}>\n {/* Source mode toggle */}\n <div className=\"source-toggle\">\n <div className=\"chip-toggle\">\n <button\n type=\"button\"\n className={`chip-toggle-btn${source === 'url' ? ' active' : ''}`}\n onClick={() => setSource('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`chip-toggle-btn${source === 'directory' ? ' active' : ''}`}\n onClick={() => setSource('directory')}\n >\n Directory\n </button>\n <button\n type=\"button\"\n className={`chip-toggle-btn${source === 'import' ? ' active' : ''}`}\n onClick={() => setSource('import')}\n >\n Import\n </button>\n </div>\n </div>\n\n <div className=\"form-hero\">\n {heroIcon}\n <h2>{title}</h2>\n <p className=\"hero-subtitle\">{subtitle}</p>\n </div>\n\n <form onSubmit={handleSubmit}>\n <div className=\"form-fields\">\n {source === 'import' ? (\n <div className=\"import-picker\">\n <input\n ref={importInputRef}\n type=\"file\"\n accept=\".db\"\n className=\"directory-input\"\n onChange={(e) => setImportFile(e.target.files?.[0] ?? null)}\n />\n <div\n className={`import-dropzone${dragging ? ' import-dropzone--active' : ''}${importFile ? ' import-dropzone--has-file' : ''}`}\n onClick={() => importInputRef.current?.click()}\n onDragOver={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setDragging(true);\n }}\n onDragEnter={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setDragging(true);\n }}\n onDragLeave={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setDragging(false);\n }}\n onDrop={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setDragging(false);\n const file = e.dataTransfer.files?.[0];\n if (file) setImportFile(file);\n }}\n >\n {importFile ? (\n <>\n <svg\n className=\"import-dropzone-icon\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n <span className=\"import-dropzone-filename\">\n {importFile.name}\n </span>\n <span className=\"import-dropzone-size\">\n {(importFile.size / 1024 / 1024).toFixed(1)} MB\n </span>\n </>\n ) : (\n <>\n <svg\n className=\"import-dropzone-icon\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n <span className=\"import-dropzone-label\">\n Drop .db file here or click to browse\n </span>\n </>\n )}\n </div>\n <div className=\"form-info\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n <span>\n Upload a LadybugDB database file (typically{' '}\n <code className=\"form-info-code\">.opentrace/index.db</code>)\n generated by the OpenTrace agent.\n </span>\n </div>\n </div>\n ) : source === 'url' ? (\n <>\n <div className=\"form-info\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n <span>\n Repository archives are fetched through the OpenTrace API\n server to avoid browser CORS restrictions. Your access token\n (if provided) is forwarded but never stored on the server.\n </span>\n </div>\n\n {!provider && (\n <div className=\"example-repos\">\n <span className=\"example-repos-label\">Examples:</span>\n {EXAMPLE_REPOS.map((repo) => (\n <button\n key={repo.url}\n type=\"button\"\n className=\"example-repo-chip\"\n onClick={() => setRepoUrl(repo.url)}\n title={repo.description}\n >\n {repo.name}\n <span\n className={`example-repo-size example-repo-size--${repo.size.toLowerCase()}`}\n >\n {repo.size}\n </span>\n </button>\n ))}\n </div>\n )}\n\n <div className=\"autocomplete-wrapper\">\n <input\n ref={urlInputRef}\n type=\"text\"\n required\n className=\"input-pill\"\n placeholder=\"https://github.com/owner/repo or https://bitbucket.org/ws/repo\"\n value={repoUrl}\n onChange={(e) => {\n setRepoUrl(e.target.value);\n if (!showHistory) setShowHistory(true);\n }}\n onFocus={() => setShowHistory(true)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setShowHistory(false);\n }}\n autoFocus\n autoComplete=\"off\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-testid=\"repo-url-input\"\n />\n {showHistory && filteredHistory.length > 0 && (\n <div ref={dropdownRef} className=\"autocomplete-dropdown\">\n <div className=\"autocomplete-label\">Recent</div>\n {filteredHistory.map((url) => (\n <div\n key={url}\n className=\"autocomplete-item\"\n role=\"option\"\n onMouseDown={(e) => {\n e.preventDefault();\n setRepoUrl(url);\n setShowHistory(false);\n urlInputRef.current?.focus();\n }}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"1 4 1 10 7 10\" />\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\n </svg>\n <span className=\"autocomplete-item-text\">\n {url\n .replace(/^https?:\\/\\/(www\\.)?/, '')\n .replace(/\\.git$/, '')}\n </span>\n <button\n type=\"button\"\n className=\"autocomplete-item-remove\"\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHistory(removeFromHistory(url));\n }}\n aria-label=\"Remove from history\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {provider && (\n <div className=\"input-pill-row\">\n <svg\n className=\"input-icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <input\n type={showPat ? 'text' : 'password'}\n className=\"input-pill input-pill--icon\"\n placeholder={`${provider ? PROVIDER_DISPLAY_NAME[provider] : ''} access token (optional, for private repos)`}\n value={pat}\n onChange={(e) => setPat(e.target.value)}\n />\n <button\n type=\"button\"\n className=\"input-toggle\"\n onClick={() => setShowPat(!showPat)}\n tabIndex={-1}\n aria-label={showPat ? 'Hide token' : 'Show token'}\n >\n {showPat ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n </div>\n )}\n </>\n ) : (\n <div className=\"directory-picker\">\n <input\n ref={fileInputRef}\n type=\"file\"\n /* @ts-expect-error webkitdirectory is non-standard but widely supported */\n webkitdirectory=\"\"\n directory=\"\"\n multiple\n className=\"directory-input\"\n onChange={(e) => setSelectedFiles(e.target.files)}\n />\n <button\n type=\"button\"\n className=\"input-pill directory-browse-btn\"\n onClick={() => fileInputRef.current?.click()}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\n </svg>\n {directoryName ? (\n <span className=\"directory-name\">\n {directoryName}{' '}\n <span className=\"directory-count\">\n ({selectedFiles?.length ?? 0} files)\n </span>\n </span>\n ) : (\n 'Choose Directory...'\n )}\n </button>\n </div>\n )}\n </div>\n\n {error && (\n <div className=\"form-error\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n <span>{error}</span>\n </div>\n )}\n\n {validationMessage && (\n <div className=\"form-indexed\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n <span>{validationMessage}</span>\n </div>\n )}\n\n <button\n type=\"submit\"\n className=\"btn-cta\"\n disabled={loading || !!validationMessage}\n >\n {loading ? (\n <>\n <span className=\"btn-spinner\" />\n {source === 'import' ? 'Importing...' : 'Indexing...'}\n </>\n ) : (\n <>\n {source === 'import' ? 'Import' : 'Add & Index'}\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n <polyline points=\"12 5 19 12 12 19\" />\n </svg>\n </>\n )}\n </button>\n\n <div className=\"form-chips\">\n {source === 'url' && (\n <div className=\"chip\">\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\" />\n <circle cx=\"18\" cy=\"6\" r=\"3\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <path d=\"M18 9a9 9 0 0 1-9 9\" />\n </svg>\n <input\n type=\"text\"\n className=\"chip-input\"\n placeholder=\"Branch: main\"\n value={ref}\n onChange={(e) => setRef(e.target.value)}\n autoComplete=\"off\"\n data-1p-ignore\n data-lpignore=\"true\"\n />\n </div>\n )}\n {dismissable && (\n <button type=\"button\" className=\"chip\" onClick={onClose}>\n Cancel\n </button>\n )}\n </div>\n </form>\n </div>\n </div>\n );\n}\n","/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * IndexingProgress — overlay showing indexing status.\n *\n * Generic version: receives stage configuration as props instead of\n * relying on proto-generated JobPhase enum.\n */\n\nimport type {\n IndexingProgressProps,\n StageConfig,\n StageState,\n} from './types';\nimport './indexing-base.css';\nimport './IndexingProgress.css';\n\n// --- Multi-Stage Progress ---\n\n/** Format a byte count as a human-readable MB string. */\nfunction formatMB(bytes: number): string {\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction StageProgressRow({\n label,\n stage,\n removing,\n}: {\n label: string;\n stage: StageState;\n removing?: boolean;\n}) {\n const isCompleted = stage.status === 'completed';\n const isActive = stage.status === 'active';\n const indeterminate = isActive && stage.total === 0;\n const pct =\n stage.total > 0 ? Math.min(100, (stage.current / stage.total) * 100) : 0;\n const isBytes = stage.format === 'bytes';\n\n let cls = 'stage-row';\n if (removing) cls += ' stage-row--removing';\n else if (isCompleted) cls += ' stage-row--completed';\n else if (isActive) cls += ' stage-row--active';\n\n // Show completed message or active detail\n const detail = isCompleted\n ? stage.message\n : isActive && stage.message\n ? stage.message\n : '';\n\n return (\n <div className={cls}>\n <div className=\"stage-header\">\n <span className=\"stage-label\">{label}</span>\n <span className=\"stage-count\">\n {stage.total > 0\n ? isBytes\n ? `${formatMB(stage.current)} / ${formatMB(stage.total)}`\n : `${stage.current}/${stage.total}`\n : stage.current > 0\n ? isBytes\n ? formatMB(stage.current)\n : `${stage.current}`\n : ''}\n </span>\n </div>\n {detail && <span className=\"stage-detail\">{detail}</span>}\n <span\n className={`stage-bar${indeterminate ? ' stage-bar--indeterminate' : ''}`}\n >\n <span\n className=\"stage-bar-fill\"\n style={\n indeterminate ? undefined : { width: `${isCompleted ? 100 : pct}%` }\n }\n />\n </span>\n </div>\n );\n}\n\nfunction MultiStageProgress({\n stages,\n stageConfig,\n}: {\n stages: Record<string, StageState>;\n stageConfig: StageConfig[];\n}) {\n // Build visible entries, filtering out stages that haven't started\n const entries = stageConfig\n .map(({ key, label }) => ({\n key,\n label,\n stage: stages[key],\n }))\n .filter((e): e is typeof e & { stage: StageState } => !!e.stage);\n\n // Find the last completed stage — all completed stages before it are \"stale\"\n let lastCompletedIdx = -1;\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].stage.status === 'completed') {\n lastCompletedIdx = i;\n break;\n }\n }\n\n return (\n <div className=\"multi-stage-progress\">\n {entries.map(({ key, label, stage }, i) => (\n <StageProgressRow\n key={key}\n label={label}\n stage={stage}\n removing={stage.status === 'completed' && i < lastCompletedIdx}\n />\n ))}\n </div>\n );\n}\n\n// --- Stats Grid ---\n\nfunction StatsGrid({\n nodes,\n relationships,\n}: {\n nodes: number;\n relationships: number;\n}) {\n return (\n <div className=\"indexing-stats-grid\">\n <div className=\"stat-card\">\n <span className=\"stat-value\">{nodes}</span>\n <span className=\"stat-label\">Nodes</span>\n </div>\n <div className=\"stat-card\">\n <span className=\"stat-value\">{relationships}</span>\n <span className=\"stat-label\">Edges</span>\n </div>\n </div>\n );\n}\n\n// --- Main Component ---\n\nexport default function IndexingProgress({\n state,\n stages: stageConfig,\n icon,\n onClose,\n onCancel,\n onMinimize,\n title,\n message,\n}: IndexingProgressProps) {\n // --- Error ---\n if (state.status === 'error') {\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n\n <div className=\"failed-content\">\n <div className=\"failed-icon\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\">\n <circle\n cx=\"16\"\n cy=\"16\"\n r=\"14\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n fill=\"color-mix(in oklch, currentColor 10%, transparent)\"\n />\n <line\n x1=\"11\"\n y1=\"11\"\n x2=\"21\"\n y2=\"21\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n />\n <line\n x1=\"21\"\n y1=\"11\"\n x2=\"11\"\n y2=\"21\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </div>\n <h2>{title ?? 'Indexing Failed'}</h2>\n {state.error && <p className=\"failed-message\">{state.error}</p>}\n </div>\n\n {(state.nodesCreated > 0 || state.relationshipsCreated > 0) && (\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n )}\n\n <button className=\"btn-cta btn-cta--secondary\" onClick={onClose}>\n Close\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n // --- Done ---\n if (state.status === 'done') {\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n\n <div className=\"done-content\">\n <div className=\"done-checkmark\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\">\n <circle\n cx=\"16\"\n cy=\"16\"\n r=\"14\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n fill=\"color-mix(in oklch, currentColor 15%, transparent)\"\n />\n <polyline\n className=\"done-check-path\"\n points=\"10,16.5 14,20.5 22,12\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </div>\n <h2>{title ?? 'Complete'}</h2>\n </div>\n\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n\n {message && <p className=\"indexing-message\">{message}</p>}\n\n <button\n className=\"btn-cta btn-cta--secondary\"\n onClick={onMinimize ?? onClose}\n >\n {onMinimize ? 'Minimize' : 'Close'}\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n // --- Running ---\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-header\">\n {icon && <span className=\"indexing-header-icon\">{icon}</span>}\n <h2>{title ?? 'Indexing Repository'}</h2>\n </div>\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n {message && <p className=\"indexing-message\">{message}</p>}\n <button\n className=\"btn-cta btn-cta--secondary\"\n onClick={onMinimize ?? onCancel}\n >\n {onMinimize ? 'Minimize' : 'Cancel'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Normalize Git remote URLs to HTTPS format.\n *\n * Converts SSH URLs (SCP-style and ssh:// protocol) to their HTTPS\n * equivalents so existing GitHub/GitLab URL parsers can handle them.\n */\n\n/**\n * Convert any common Git remote URL to an HTTPS URL.\n *\n * Handles:\n * - SCP-style: git@host:owner/repo[.git] → https://host/owner/repo\n * - SSH protocol: ssh://git@host/owner/repo[.git] → https://host/owner/repo\n * - HTTPS/other: passed through unchanged (with .git suffix stripped)\n */\nexport function normalizeRepoUrl(raw: string): string {\n const trimmed = raw.trim();\n\n // SCP-style: git@github.com:owner/repo.git\n const scpMatch = trimmed.match(/^[\\w.-]+@([^:]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n const path = stripDotGit(scpMatch[2]);\n return `https://${host}/${path}`;\n }\n\n // SSH protocol: ssh://git@github.com/owner/repo.git\n const sshMatch = trimmed.match(/^ssh:\\/\\/[\\w.-]+@([^/]+)\\/(.+)$/);\n if (sshMatch) {\n const host = sshMatch[1];\n const path = stripDotGit(sshMatch[2]);\n return `https://${host}/${path}`;\n }\n\n // Everything else: strip .git suffix if present, pass through\n return stripDotGit(trimmed);\n}\n\nfunction stripDotGit(s: string): string {\n return s.endsWith('.git') ? s.slice(0, -4) : s;\n}\n"],"names":[],"mappings":";;AA8BO,SAAS,eACd,KAC0D;AAC1D,QAAM,QAAQ,IAAI,YAAA;AAClB,MAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,MAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,MAAI,MAAM,SAAS,WAAW,EAAG,QAAO;AACxC,MAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,kBAAkB;AACtE,WAAO;AACT,SAAO;AACT;AAEA,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,SAAS,cAAwB;AAC/B,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW;AAC5C,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO,MAAM,QAAQ,MAAM,IACvB,OAAO,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,IAChE,CAAA;AAAA,EACN,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAAa;AAClC,QAAM,UAAU,cAAc,OAAO,CAAC,MAAM,MAAM,GAAG;AACrD,UAAQ,QAAQ,GAAG;AACnB,eAAa;AAAA,IACX;AAAA,IACA,KAAK,UAAU,QAAQ,MAAM,GAAG,WAAW,CAAC;AAAA,EAAA;AAEhD;AAEA,SAAS,kBAAkB,KAAuB;AAChD,QAAM,UAAU,cAAc,OAAO,CAAC,MAAM,MAAM,GAAG;AACrD,eAAa,QAAQ,aAAa,KAAK,UAAU,OAAO,CAAC;AACzD,SAAO;AACT;AAEA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQA,MAAM,iBAGF;AAAA,EACF,QAAQ;AAAA;AAAA,IAEN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,QAAQ;AAAA;AAAA,IAEN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,WAAW;AAAA;AAAA,IAET,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,aAAa;AAAA;AAAA,IAEX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;AAGA,MAAM,oBAAqD;AAAA,EACzD,QAAQ,MACN,oBAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAA,oBAAC,QAAA,EAAK,GAAE,4jBAA2jB,GACrkB;AAAA,EAEF,QAAQ,MACN,qBAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,eAAc,MAAK,gBACzD,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,2CAA0C,SAAQ,QAAO;AAAA,IACjE,oBAAC,QAAA,EAAK,GAAE,0CAAyC,SAAQ,OAAM;AAAA,IAC/D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEV;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEV,oBAAC,QAAA,EAAK,GAAE,0CAAyC,SAAQ,OAAM;AAAA,IAC/D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEV;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,EACV,GACF;AAAA,EAEF,WAAW,MACT,oBAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAA,oBAAC,QAAA,EAAK,GAAE,wLAAuL,GACjM;AAAA,EAEF,aAAa,MACX,oBAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAA,oBAAC,QAAA,EAAK,GAAE,iKAAgK,EAAA,CAC1K;AAEJ;AAEA,SAAS,kBAAkB,EAAE,YAAyC;AACpE,8BACG,OAAA,EAAI,WAAW,eAAe,WAAW,yBAAyB,KAEjE,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,gBAAgB,WAAW,2BAA2B,EAAE;AAAA,QACnE,OAAM;AAAA,QACN,QAAO;AAAA,QACP,SAAQ;AAAA,QAER,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,SAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAEV;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,SAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA;AAAA,IAGD,eAAe,IAAI,CAAC,QAAQ;AAC3B,YAAM,OAAO,kBAAkB,GAAG;AAClC,YAAM,QAAQ,eAAe,GAAG;AAChC,YAAM,OAAO,CAAC,WACV,MAAM,UACN,QAAQ,WACN,MAAM,OACN,MAAM;AACZ,aACE,oBAAC,OAAA,EAAc,WAAU,cAAa,OAAO,EAAE,UAAU,KAAA,GACvD,UAAA,oBAAC,MAAA,CAAA,CAAK,EAAA,GADE,GAEV;AAAA,IAEJ,CAAC;AAAA,EAAA,GACH;AAEJ;AAEA,SAAS,aAAa;AACpB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MAEf,UAAA,oBAAC,QAAA,EAAK,GAAE,8EAAA,CAA8E;AAAA,IAAA;AAAA,EAAA;AAG5F;AAEA,SAAS,aAAa;AACpB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MAEf,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAQ,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,QACtC,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,QAC5C,oBAAC,QAAA,EAAK,GAAE,sCAAA,CAAsC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGpD;AAEA,MAAM,wBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,aAAa;AACf;AAMA,MAAM,gBAKA;AAAA,EACJ;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAEV;AAIA,SAAwB,aAAa;AAAA,EACnC;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAsB;AACpB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,KAAK;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,EAAE;AACzC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAmB,WAAW;AAC5D,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,EAAE;AACjC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,EAAE;AACjC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAA0B,IAAI;AACxE,QAAM,CAAC,YAAY,aAAa,IAAI,SAAsB,IAAI;AAC9D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,eAAe,OAAyB,IAAI;AAClD,QAAM,iBAAiB,OAAyB,IAAI;AACpD,QAAM,cAAc,OAAyB,IAAI;AACjD,QAAM,cAAc,OAAuB,IAAI;AAG/C,YAAU,MAAM;AACd,QAAI,WAAW,OAAO;AACpB,kBAAY,SAAS,MAAA;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGX,YAAU,MAAM;AACd,aAAS,YAAY,GAAe;AAClC,UACE,YAAY,WACZ,CAAC,YAAY,QAAQ,SAAS,EAAE,MAAc,KAC9C,EAAE,WAAW,YAAY,SACzB;AACA,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,WAAW;AAClD,WAAO,MAAM,SAAS,oBAAoB,aAAa,WAAW;AAAA,EACpE,GAAG,CAAA,CAAE;AAEL,QAAM,kBAAkB,QAAQ;AAAA,IAC9B,CAAC,QAAQ,CAAC,WAAW,IAAI,cAAc,SAAS,QAAQ,YAAA,CAAa;AAAA,EAAA;AAGvE,QAAM,WAAW,WAAW,QAAQ,eAAe,OAAO,IAAI;AAC9D,QAAM,gBAAgB,WAAW,MAAM,QAAQ,SAAS;AAGxD,QAAM,oBAAoB,QAAQ,MAAM;AACtC,QAAI,WAAW,SAAS,CAAC,QAAQ,UAAU,CAAC,WAAY,QAAO;AAC/D,WAAO,WAAW,OAAO;AAAA,EAC3B,GAAG,CAAC,QAAQ,SAAS,UAAU,CAAC;AAGhC,QAAM,gBACJ,gBAAgB,CAAC,GAAG,oBAAoB,MAAM,GAAG,EAAE,CAAC,KAAK;AAG3D,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,cAAe;AACjC,UAAM,QAAQ,aAAa,QAAQ,aAAa;AAEhD,QAAI,cAAc,KAAK;AAAA,gBACX,EAAE;AAAA,EAChB,GAAG,CAAC,UAAU,aAAa,CAAC;AAG5B,YAAU,MAAM;AAEd,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,MAAM,CAAC;AAEX,WAAS,aAAa,GAAc;AAClC,MAAE,eAAA;AAEF,QAAI,WAAW,UAAU;AACvB,UAAI,CAAC,YAAY;AACf,iBAAS,0BAA0B;AACnC;AAAA,MACF;AACA,eAAS,IAAI;AACb,iBAAW,IAAI;AACf,eAAS;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM,WAAW,KAAK,QAAQ,YAAY,EAAE;AAAA,MAAA,CAC7C;AACD;AAAA,IACF;AAEA,QAAI,WAAW,aAAa;AAC1B,UAAI,CAAC,iBAAiB,cAAc,WAAW,GAAG;AAChD,iBAAS,2BAA2B;AACpC;AAAA,MACF;AACA,eAAS,IAAI;AACb,iBAAW,IAAI;AACf,eAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM,iBAAiB;AAAA,MAAA,CACxB;AACD;AAAA,IACF;AAGA,QAAI,CAAC,UAAU;AACb;AAAA,QACE;AAAA,MAAA;AAEF;AAAA,IACF;AACA,QAAI,mBAAmB;AACrB;AAAA,IACF;AACA,aAAS,IAAI;AACb,eAAW,IAAI;AAEf,QAAI,eAAe;AACjB,UAAI,IAAK,cAAa,QAAQ,eAAe,GAAG;AAAA,UAC3C,cAAa,WAAW,aAAa;AAAA,IAC5C;AAEA,kBAAc,OAAO;AAErB,aAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,MACA,OAAO,OAAO;AAAA,MACd,KAAK,OAAO;AAAA,IAAA,CACb;AAAA,EACH;AAIA,QAAM,WACJ,WAAW,WACT,oBAAC,OAAA,EAAI,WAAU,iCACb,UAAA,oBAAC,YAAA,CAAA,CAAW,EAAA,CACd,IACE,WAAW,cACb,oBAAC,OAAA,EAAI,WAAU,iCACb,UAAA,oBAAC,YAAA,CAAA,CAAW,GACd,IAEA,oBAAC,mBAAA,EAAkB,UAAU,SAAA,CAAU;AAG3C,QAAM,QACJ,WAAW,WACP,iBACA,WAAW,cACT,wBACA,WACE,YAAY,sBAAsB,QAAQ,CAAC,KAC3C;AAEV,QAAM,WACJ,WAAW,WACP,mDACA,WAAW,cACT,6DACA,WACE,WAAW,sBAAsB,QAAQ,CAAC,6BAC1C;AAEV,6BACG,OAAA,EAAI,WAAU,kBAAiB,SAAS,cAAc,UAAU,QAC/D,UAAA,qBAAC,OAAA,EAAI,WAAU,cAAa,SAAS,CAAC,MAAM,EAAE,mBAE5C,UAAA;AAAA,IAAA,oBAAC,SAAI,WAAU,iBACb,UAAA,qBAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,kBAAkB,WAAW,QAAQ,YAAY,EAAE;AAAA,UAC9D,SAAS,MAAM,UAAU,KAAK;AAAA,UAC/B,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,kBAAkB,WAAW,cAAc,YAAY,EAAE;AAAA,UACpE,SAAS,MAAM,UAAU,WAAW;AAAA,UACrC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,kBAAkB,WAAW,WAAW,YAAY,EAAE;AAAA,UACjE,SAAS,MAAM,UAAU,QAAQ;AAAA,UAClC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACF,EAAA,CACF;AAAA,IAEA,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAI,UAAA,MAAA,CAAM;AAAA,MACX,oBAAC,KAAA,EAAE,WAAU,iBAAiB,UAAA,SAAA,CAAS;AAAA,IAAA,GACzC;AAAA,IAEA,qBAAC,QAAA,EAAK,UAAU,cACd,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,eACZ,UAAA,WAAW,WACV,qBAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,QAAO;AAAA,YACP,WAAU;AAAA,YACV,UAAU,CAAC,MAAM,cAAc,EAAE,OAAO,QAAQ,CAAC,KAAK,IAAI;AAAA,UAAA;AAAA,QAAA;AAAA,QAE5D;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,kBAAkB,WAAW,6BAA6B,EAAE,GAAG,aAAa,+BAA+B,EAAE;AAAA,YACxH,SAAS,MAAM,eAAe,SAAS,MAAA;AAAA,YACvC,YAAY,CAAC,MAAM;AACjB,gBAAE,eAAA;AACF,gBAAE,gBAAA;AACF,0BAAY,IAAI;AAAA,YAClB;AAAA,YACA,aAAa,CAAC,MAAM;AAClB,gBAAE,eAAA;AACF,gBAAE,gBAAA;AACF,0BAAY,IAAI;AAAA,YAClB;AAAA,YACA,aAAa,CAAC,MAAM;AAClB,gBAAE,eAAA;AACF,gBAAE,gBAAA;AACF,0BAAY,KAAK;AAAA,YACnB;AAAA,YACA,QAAQ,CAAC,MAAM;AACb,gBAAE,eAAA;AACF,gBAAE,gBAAA;AACF,0BAAY,KAAK;AACjB,oBAAM,OAAO,EAAE,aAAa,QAAQ,CAAC;AACrC,kBAAI,oBAAoB,IAAI;AAAA,YAC9B;AAAA,YAEC,uBACC,qBAAA,UAAA,EACE,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAA,oBAAC,WAAA,EAAQ,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,oBACtC,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,oBAC5C,oBAAC,QAAA,EAAK,GAAE,sCAAA,CAAsC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEhD,oBAAC,QAAA,EAAK,WAAU,4BACb,qBAAW,MACd;AAAA,cACA,qBAAC,QAAA,EAAK,WAAU,wBACZ,UAAA;AAAA,iBAAA,WAAW,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,gBAAE;AAAA,cAAA,EAAA,CAC9C;AAAA,YAAA,EAAA,CACF,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,GAAE,4CAAA,CAA4C;AAAA,oBACpD,oBAAC,YAAA,EAAS,QAAO,gBAAA,CAAgB;AAAA,oBACjC,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEvC,oBAAC,QAAA,EAAK,WAAU,yBAAwB,UAAA,wCAAA,CAExC;AAAA,YAAA,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAGJ,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,gBAC/B,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,gBACtC,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,SAAQ,IAAG,IAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,+BAExC,QAAA,EAAK,UAAA;AAAA,YAAA;AAAA,YACwC;AAAA,YAC5C,oBAAC,QAAA,EAAK,WAAU,kBAAiB,UAAA,uBAAmB;AAAA,YAAO;AAAA,UAAA,EAAA,CAE7D;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,EAAA,CACF,IACE,WAAW,QACb,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,gBAC/B,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,gBACtC,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,SAAQ,IAAG,IAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEzC,oBAAC,UAAK,UAAA,oLAAA,CAIN;AAAA,QAAA,GACF;AAAA,QAEC,CAAC,YACA,qBAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,uBAAsB,UAAA,aAAS;AAAA,UAC9C,cAAc,IAAI,CAAC,SAClB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,WAAW,KAAK,GAAG;AAAA,cAClC,OAAO,KAAK;AAAA,cAEX,UAAA;AAAA,gBAAA,KAAK;AAAA,gBACN;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW,wCAAwC,KAAK,KAAK,aAAa;AAAA,oBAEzE,UAAA,KAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACR;AAAA,YAAA;AAAA,YAXK,KAAK;AAAA,UAAA,CAab;AAAA,QAAA,GACH;AAAA,QAGF,qBAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,UAAQ;AAAA,cACR,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,MAAM;AACf,2BAAW,EAAE,OAAO,KAAK;AACzB,oBAAI,CAAC,YAAa,gBAAe,IAAI;AAAA,cACvC;AAAA,cACA,SAAS,MAAM,eAAe,IAAI;AAAA,cAClC,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,SAAU,gBAAe,KAAK;AAAA,cAC9C;AAAA,cACA,WAAS;AAAA,cACT,cAAa;AAAA,cACb,kBAAc;AAAA,cACd,iBAAc;AAAA,cACd,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAEb,eAAe,gBAAgB,SAAS,0BACtC,OAAA,EAAI,KAAK,aAAa,WAAU,yBAC/B,UAAA;AAAA,YAAA,oBAAC,OAAA,EAAI,WAAU,sBAAqB,UAAA,UAAM;AAAA,YACzC,gBAAgB,IAAI,CAAC,QACpB;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,aAAa,CAAC,MAAM;AAClB,oBAAE,eAAA;AACF,6BAAW,GAAG;AACd,iCAAe,KAAK;AACpB,8BAAY,SAAS,MAAA;AAAA,gBACvB;AAAA,gBAEA,UAAA;AAAA,kBAAA;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,OAAM;AAAA,sBACN,QAAO;AAAA,sBACP,SAAQ;AAAA,sBACR,MAAK;AAAA,sBACL,QAAO;AAAA,sBACP,aAAY;AAAA,sBACZ,eAAc;AAAA,sBACd,gBAAe;AAAA,sBAEf,UAAA;AAAA,wBAAA,oBAAC,YAAA,EAAS,QAAO,gBAAA,CAAgB;AAAA,wBACjC,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAE9C,oBAAC,QAAA,EAAK,WAAU,0BACb,UAAA,IACE,QAAQ,wBAAwB,EAAE,EAClC,QAAQ,UAAU,EAAE,EAAA,CACzB;AAAA,kBACA;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,aAAa,CAAC,MAAM;AAClB,0BAAE,eAAA;AACF,0BAAE,gBAAA;AACF,mCAAW,kBAAkB,GAAG,CAAC;AAAA,sBACnC;AAAA,sBACA,cAAW;AAAA,sBAEX,UAAA;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,OAAM;AAAA,0BACN,QAAO;AAAA,0BACP,SAAQ;AAAA,0BACR,MAAK;AAAA,0BACL,QAAO;AAAA,0BACP,aAAY;AAAA,0BACZ,eAAc;AAAA,0BACd,gBAAe;AAAA,0BAEf,UAAA;AAAA,4BAAA,oBAAC,YAAA,EAAS,QAAO,eAAA,CAAe;AAAA,4BAChC,oBAAC,QAAA,EAAK,GAAE,gDAAA,CAAgD;AAAA,4BACxD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,4BACnB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACrB;AAAA,kBAAA;AAAA,gBACF;AAAA,cAAA;AAAA,cArDK;AAAA,YAAA,CAuDR;AAAA,UAAA,EAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QAEC,YACC,qBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,IAAG,KAAI;AAAA,gBACxD,oBAAC,QAAA,EAAK,GAAE,2BAAA,CAA2B;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAErC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,UAAU,SAAS;AAAA,cACzB,WAAU;AAAA,cACV,aAAa,GAAG,WAAW,sBAAsB,QAAQ,IAAI,EAAE;AAAA,cAC/D,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAExC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,WAAW,CAAC,OAAO;AAAA,cAClC,UAAU;AAAA,cACV,cAAY,UAAU,eAAe;AAAA,cAEpC,UAAA,UACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,GAAE,kFAAA,CAAkF;AAAA,oBAC1F,oBAAC,QAAA,EAAK,GAAE,yEAAA,CAAyE;AAAA,oBACjF,oBAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,oBACpC,oBAAC,QAAA,EAAK,GAAE,mCAAA,CAAmC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA,IAG7C;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,GAAE,+CAAA,CAA+C;AAAA,wCACtD,UAAA,EAAO,IAAG,MAAK,IAAG,MAAK,GAAE,IAAA,CAAI;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YAChC;AAAA,UAAA;AAAA,QAEJ,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ,IAEA,qBAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YAEL,iBAAgB;AAAA,YAChB,WAAU;AAAA,YACV,UAAQ;AAAA,YACR,WAAU;AAAA,YACV,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAElD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM,aAAa,SAAS,MAAA;AAAA,YAErC,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA,oBAAC,QAAA,EAAK,GAAE,8EAAA,CAA8E;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEvF,gBACC,qBAAC,QAAA,EAAK,WAAU,kBACb,UAAA;AAAA,gBAAA;AAAA,gBAAe;AAAA,gBAChB,qBAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA;AAAA,kBAAA;AAAA,kBAC9B,eAAe,UAAU;AAAA,kBAAE;AAAA,gBAAA,EAAA,CAC/B;AAAA,cAAA,EAAA,CACF,IAEA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF,EAAA,CAEJ;AAAA,MAEC,SACC,qBAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,gBAAe;AAAA,YAEf,UAAA;AAAA,cAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,cAC/B,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,cACpC,oBAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEtC,oBAAC,UAAM,UAAA,MAAA,CAAM;AAAA,MAAA,GACf;AAAA,MAGD,qBACC,qBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,gBAAe;AAAA,YAEf,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,GAAE,qCAAA,CAAqC;AAAA,cAC7C,oBAAC,YAAA,EAAS,QAAO,wBAAA,CAAwB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAE3C,oBAAC,UAAM,UAAA,kBAAA,CAAkB;AAAA,MAAA,GAC3B;AAAA,MAGF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,UAAU,WAAW,CAAC,CAAC;AAAA,UAEtB,oBACC,qBAAA,UAAA,EACE,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAU,cAAA,CAAc;AAAA,YAC7B,WAAW,WAAW,iBAAiB;AAAA,UAAA,EAAA,CAC1C,IAEA,qBAAA,UAAA,EACG,UAAA;AAAA,YAAA,WAAW,WAAW,WAAW;AAAA,YAClC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,aAAY;AAAA,gBACZ,eAAc;AAAA,gBACd,gBAAe;AAAA,gBAEf,UAAA;AAAA,kBAAA,oBAAC,QAAA,EAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,kBACrC,oBAAC,YAAA,EAAS,QAAO,mBAAA,CAAmB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACtC,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,MAIJ,qBAAC,OAAA,EAAI,WAAU,cACZ,UAAA;AAAA,QAAA,WAAW,SACV,qBAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAA,oBAAC,QAAA,EAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,oCAClC,UAAA,EAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI;AAAA,oCAC5B,UAAA,EAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI;AAAA,gBAC7B,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEhC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,cACtC,cAAa;AAAA,cACb,kBAAc;AAAA,cACd,iBAAc;AAAA,YAAA;AAAA,UAAA;AAAA,QAChB,GACF;AAAA,QAED,mCACE,UAAA,EAAO,MAAK,UAAS,WAAU,QAAO,SAAS,SAAS,UAAA,SAAA,CAEzD;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;ACj6BA,SAAS,SAAS,OAAuB;AACvC,UAAQ,SAAS,OAAO,OAAO,QAAQ,CAAC,IAAI;AAC9C;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,MAAM,WAAW;AACrC,QAAM,WAAW,MAAM,WAAW;AAClC,QAAM,gBAAgB,YAAY,MAAM,UAAU;AAClD,QAAM,MACJ,MAAM,QAAQ,IAAI,KAAK,IAAI,KAAM,MAAM,UAAU,MAAM,QAAS,GAAG,IAAI;AACzE,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,MAAM;AACV,MAAI,SAAU,QAAO;AAAA,WACZ,YAAa,QAAO;AAAA,WACpB,SAAU,QAAO;AAG1B,QAAM,SAAS,cACX,MAAM,UACN,YAAY,MAAM,UAChB,MAAM,UACN;AAEN,SACE,qBAAC,OAAA,EAAI,WAAW,KACd,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,eAAe,UAAA,OAAM;AAAA,0BACpC,QAAA,EAAK,WAAU,eACb,UAAA,MAAM,QAAQ,IACX,UACE,GAAG,SAAS,MAAM,OAAO,CAAC,MAAM,SAAS,MAAM,KAAK,CAAC,KACrD,GAAG,MAAM,OAAO,IAAI,MAAM,KAAK,KACjC,MAAM,UAAU,IACd,UACE,SAAS,MAAM,OAAO,IACtB,GAAG,MAAM,OAAO,KAClB,GAAA,CACR;AAAA,IAAA,GACF;AAAA,IACC,UAAU,oBAAC,QAAA,EAAK,WAAU,gBAAgB,UAAA,QAAO;AAAA,IAClD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,YAAY,gBAAgB,8BAA8B,EAAE;AAAA,QAEvE,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OACE,gBAAgB,SAAY,EAAE,OAAO,GAAG,cAAc,MAAM,GAAG,IAAA;AAAA,UAAI;AAAA,QAAA;AAAA,MAEvE;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AAED,QAAM,UAAU,YACb,IAAI,CAAC,EAAE,KAAK,aAAa;AAAA,IACxB;AAAA,IACA;AAAA,IACA,OAAO,OAAO,GAAG;AAAA,EAAA,EACjB,EACD,OAAO,CAAC,MAA6C,CAAC,CAAC,EAAE,KAAK;AAGjE,MAAI,mBAAmB;AACvB,WAAS,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;AAC5C,QAAI,QAAQ,CAAC,EAAE,MAAM,WAAW,aAAa;AAC3C,yBAAmB;AACnB;AAAA,IACF;AAAA,EACF;AAEA,SACE,oBAAC,OAAA,EAAI,WAAU,wBACZ,UAAA,QAAQ,IAAI,CAAC,EAAE,KAAK,OAAO,MAAA,GAAS,MACnC;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA,UAAU,MAAM,WAAW,eAAe,IAAI;AAAA,IAAA;AAAA,IAHzC;AAAA,EAAA,CAKR,GACH;AAEJ;AAIA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AACF,GAGG;AACD,SACE,qBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,cAAc,UAAA,OAAM;AAAA,MACpC,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,QAAA,CAAK;AAAA,IAAA,GACpC;AAAA,IACA,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,cAAc,UAAA,eAAc;AAAA,MAC5C,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,QAAA,CAAK;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,GACF;AAEJ;AAIA,SAAwB,iBAAiB;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AAExB,MAAI,MAAM,WAAW,SAAS;AAC5B,WACE,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,QAElB,UAAA,qBAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAGF,qBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAA,oBAAC,OAAA,EAAI,WAAU,eACb,UAAA,qBAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACnD,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEP;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEhB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,YAChB,EAAA,CACF,EAAA,CACF;AAAA,YACA,oBAAC,MAAA,EAAI,UAAA,SAAS,kBAAA,CAAkB;AAAA,YAC/B,MAAM,SAAS,oBAAC,OAAE,WAAU,kBAAkB,gBAAM,MAAA,CAAM;AAAA,UAAA,GAC7D;AAAA,WAEE,MAAM,eAAe,KAAK,MAAM,uBAAuB,MACvD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,8BAIxB,UAAA,EAAO,WAAU,8BAA6B,SAAS,SAAS,UAAA,QAAA,CAEjE;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,EAEJ;AAGA,MAAI,MAAM,WAAW,QAAQ;AAC3B,WACE,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,QAElB,UAAA,qBAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAGF,qBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,YAAA,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA,qBAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACnD,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEP;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,QAAO;AAAA,kBACP,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,YACP,EAAA,CACF,EAAA,CACF;AAAA,YACA,oBAAC,MAAA,EAAI,UAAA,SAAS,WAAA,CAAW;AAAA,UAAA,GAC3B;AAAA,UAEA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAGtB,WAAW,oBAAC,KAAA,EAAE,WAAU,oBAAoB,UAAA,SAAQ;AAAA,UAErD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,cAAc;AAAA,cAEtB,uBAAa,aAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAC7B,EAAA,CACF;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,EAEJ;AAGA,SACE,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,MAElB,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,mBACZ,UAAA;AAAA,UAAA,QAAQ,oBAAC,QAAA,EAAK,WAAU,wBAAwB,UAAA,MAAK;AAAA,UACtD,oBAAC,MAAA,EAAI,UAAA,SAAS,sBAAA,CAAsB;AAAA,QAAA,GACtC;AAAA,QACA,qBAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAEF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAEtB,WAAW,oBAAC,KAAA,EAAE,WAAU,oBAAoB,UAAA,SAAQ;AAAA,UACrD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,cAAc;AAAA,cAEtB,uBAAa,aAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAC7B,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;ACtSO,SAAS,iBAAiB,KAAqB;AACpD,QAAM,UAAU,IAAI,KAAA;AAGpB,QAAM,WAAW,QAAQ,MAAM,wBAAwB;AACvD,MAAI,UAAU;AACZ,UAAM,OAAO,SAAS,CAAC;AACvB,UAAM,OAAO,YAAY,SAAS,CAAC,CAAC;AACpC,WAAO,WAAW,IAAI,IAAI,IAAI;AAAA,EAChC;AAGA,QAAM,WAAW,QAAQ,MAAM,iCAAiC;AAChE,MAAI,UAAU;AACZ,UAAM,OAAO,SAAS,CAAC;AACvB,UAAM,OAAO,YAAY,SAAS,CAAC,CAAC;AACpC,WAAO,WAAW,IAAI,IAAI,IAAI;AAAA,EAChC;AAGA,SAAO,YAAY,OAAO;AAC5B;AAEA,SAAS,YAAY,GAAmB;AACtC,SAAO,EAAE,SAAS,MAAM,IAAI,EAAE,MAAM,GAAG,EAAE,IAAI;AAC/C;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentrace/components",
3
- "version": "0.1.1-rc.77",
3
+ "version": "0.1.1-rc.78",
4
4
  "type": "module",
5
5
  "description": "React components for graph visualization — powered by Sigma.js and Graphology",
6
6
  "license": "Apache-2.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"urlNormalize-DL0SAEQS.cjs","sources":["../src/indexing/AddRepoModal.tsx","../src/indexing/IndexingProgress.tsx","../src/indexing/urlNormalize.ts"],"sourcesContent":["/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type FormEvent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { AddRepoModalProps } from './types';\nimport './indexing-base.css';\nimport './AddRepoModal.css';\n\ntype SourceMode = 'url' | 'directory';\n\nexport function detectProvider(\n url: string,\n): 'github' | 'gitlab' | 'bitbucket' | 'azuredevops' | null {\n const lower = url.toLowerCase();\n if (lower.includes('github')) return 'github';\n if (lower.includes('gitlab')) return 'gitlab';\n if (lower.includes('bitbucket')) return 'bitbucket';\n if (lower.includes('dev.azure.com') || lower.includes('visualstudio.com'))\n return 'azuredevops';\n return null;\n}\n\nconst HISTORY_KEY = 'ot_repo_history';\nconst MAX_HISTORY = 5;\n\nfunction loadHistory(): string[] {\n try {\n const raw = localStorage.getItem(HISTORY_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed)\n ? parsed.filter((item): item is string => typeof item === 'string')\n : [];\n } catch {\n return [];\n }\n}\n\nfunction saveToHistory(url: string) {\n const history = loadHistory().filter((u) => u !== url);\n history.unshift(url);\n localStorage.setItem(\n HISTORY_KEY,\n JSON.stringify(history.slice(0, MAX_HISTORY)),\n );\n}\n\nfunction removeFromHistory(url: string): string[] {\n const updated = loadHistory().filter((u) => u !== url);\n localStorage.setItem(HISTORY_KEY, JSON.stringify(updated));\n return updated;\n}\n\nconst PROVIDER_ORDER = [\n 'github',\n 'gitlab',\n 'bitbucket',\n 'azuredevops',\n] as const;\n\n/**\n * Clip-path polygons for each provider's quadrant.\n * All use 4-point polygons so CSS can interpolate between states.\n *\n * Layout: GitHub=top, GitLab=right, Bitbucket=bottom, AzureDevOps=left\n */\nconst QUADRANT_CLIPS: Record<\n string,\n { quarter: string; full: string; hidden: string }\n> = {\n github: {\n // top triangle\n quarter: 'polygon(0% 0%, 100% 0%, 50% 50%, 50% 50%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n gitlab: {\n // right triangle\n quarter: 'polygon(50% 50%, 100% 0%, 100% 100%, 50% 50%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n bitbucket: {\n // bottom triangle\n quarter: 'polygon(50% 50%, 50% 50%, 100% 100%, 0% 100%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n azuredevops: {\n // left triangle\n quarter: 'polygon(0% 0%, 50% 50%, 50% 50%, 0% 100%)',\n full: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',\n hidden: 'polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%)',\n },\n};\n\n/** Full-size SVGs (fill their container) for the clip-path composite. */\nconst PROVIDER_FULL_SVG: Record<string, () => ReactNode> = {\n github: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z\" />\n </svg>\n ),\n gitlab: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 380 380\" fill=\"currentColor\">\n <path d=\"M190 353.9L131.1 172.8h117.8L190 353.9z\" opacity=\"0.85\" />\n <path d=\"M190 353.9L131.1 172.8H15.6L190 353.9z\" opacity=\"0.7\" />\n <path\n d=\"M15.6 172.8L0.4 219.5c-1.4 4.3 0.1 9 3.8 11.7L190 353.9 15.6 172.8z\"\n opacity=\"0.55\"\n />\n <path\n d=\"M15.6 172.8h115.5L87.6 26.5c-1.6-4.9-8.5-4.9-10.1 0L15.6 172.8z\"\n opacity=\"0.85\"\n />\n <path d=\"M190 353.9l58.9-181.1h115.5L190 353.9z\" opacity=\"0.7\" />\n <path\n d=\"M364.4 172.8l15.2 46.7c1.4 4.3-0.1 9-3.8 11.7L190 353.9l174.4-181.1z\"\n opacity=\"0.55\"\n />\n <path\n d=\"M364.4 172.8H248.9l43.5-146.3c1.6-4.9 8.5-4.9 10.1 0l61.9 146.3z\"\n opacity=\"0.85\"\n />\n </svg>\n ),\n bitbucket: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 32 32\" fill=\"currentColor\">\n <path d=\"M2.278 2.133a1.07 1.07 0 00-1.07 1.236l4.058 24.637a1.45 1.45 0 001.417 1.195h19.1a1.07 1.07 0 001.07-.903l4.058-24.93a1.07 1.07 0 00-1.07-1.236zm16.7 17.757h-6.1l-1.647-8.613h9.2z\" />\n </svg>\n ),\n azuredevops: () => (\n <svg width=\"100%\" height=\"100%\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M15 3.622v8.512L11.5 15l-5.425-1.975v1.958L3.004 10.97l8.951.7V4.005L15 3.622zm-2.984.428L6.994 1v2.001L2.382 4.356 1 6.13v4.029l1.978.873V5.869l9.038-1.819z\" />\n </svg>\n ),\n};\n\nfunction ProviderIconStrip({ selected }: { selected: string | null }) {\n return (\n <div className={'hero-icon' + (selected ? ' hero-icon--provider' : '')}>\n {/* X-shaped divider lines */}\n <svg\n className={`quad-dividers${selected ? ' quad-dividers--hidden' : ''}`}\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 64 64\"\n >\n <line\n x1=\"0\"\n y1=\"0\"\n x2=\"64\"\n y2=\"64\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n opacity=\"0.2\"\n />\n <line\n x1=\"64\"\n y1=\"0\"\n x2=\"0\"\n y2=\"64\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n opacity=\"0.2\"\n />\n </svg>\n {/* Four icon layers, each clipped to a quadrant */}\n {PROVIDER_ORDER.map((key) => {\n const Icon = PROVIDER_FULL_SVG[key];\n const clips = QUADRANT_CLIPS[key];\n const clip = !selected\n ? clips.quarter\n : key === selected\n ? clips.full\n : clips.hidden;\n return (\n <div key={key} className=\"quad-layer\" style={{ clipPath: clip }}>\n <Icon />\n </div>\n );\n })}\n </div>\n );\n}\n\nfunction FolderIcon() {\n return (\n <svg\n width=\"38\"\n height=\"38\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\nconst PROVIDER_DISPLAY_NAME: Record<string, string> = {\n github: 'GitHub',\n gitlab: 'GitLab',\n bitbucket: 'Bitbucket',\n azuredevops: 'Azure DevOps',\n};\n\n// --- Example Repositories ---\n\ntype RepoSize = 'S' | 'M' | 'L';\n\nconst EXAMPLE_REPOS: {\n name: string;\n url: string;\n description: string;\n size: RepoSize;\n}[] = [\n {\n name: 'OpenTrace',\n url: 'https://github.com/opentrace/opentrace',\n description: 'Knowledge graph for system architecture and code structure',\n size: 'M',\n },\n {\n name: 'OpenTelemetry Demo',\n url: 'https://github.com/open-telemetry/opentelemetry-demo',\n description: 'Microservices demo with OTel instrumentation',\n size: 'M',\n },\n {\n name: 'Express.js',\n url: 'https://github.com/expressjs/express',\n description: 'Fast, minimalist web framework for Node.js',\n size: 'S',\n },\n {\n name: 'Podinfo',\n url: 'https://github.com/stefanprodan/podinfo',\n description: 'Go microservice template for Kubernetes',\n size: 'S',\n },\n {\n name: 'Grafana',\n url: 'https://github.com/grafana/grafana',\n description: 'Open-source observability and monitoring platform',\n size: 'L',\n },\n {\n name: 'Linux',\n url: 'https://github.com/torvalds/linux',\n description: 'Linux kernel source tree',\n size: 'L',\n },\n];\n\n// --- Main Component ---\n\nexport default function AddRepoModal({\n onClose,\n onSubmit,\n dismissable = true,\n onValidate,\n}: AddRepoModalProps) {\n const [source, setSource] = useState<SourceMode>('url');\n const [repoUrl, setRepoUrl] = useState('');\n const [history, setHistory] = useState<string[]>(loadHistory);\n const [showHistory, setShowHistory] = useState(false);\n const [ref, setRef] = useState('');\n const [pat, setPat] = useState('');\n const [showPat, setShowPat] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [selectedFiles, setSelectedFiles] = useState<FileList | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const urlInputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Reliably focus the URL input when the modal mounts\n useEffect(() => {\n if (source === 'url') {\n urlInputRef.current?.focus();\n }\n }, [source]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClick(e: MouseEvent) {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(e.target as Node) &&\n e.target !== urlInputRef.current\n ) {\n setShowHistory(false);\n }\n }\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, []);\n\n const filteredHistory = history.filter(\n (url) => !repoUrl || url.toLowerCase().includes(repoUrl.toLowerCase()),\n );\n\n const provider = source === 'url' ? detectProvider(repoUrl) : null;\n const patStorageKey = provider ? `ot_${provider}_pat` : null;\n\n // Let the consumer validate the URL (e.g. duplicate detection)\n const validationMessage = useMemo(() => {\n if (source !== 'url' || !repoUrl.trim() || !onValidate) return null;\n return onValidate(repoUrl);\n }, [source, repoUrl, onValidate]);\n\n // Derive directory name from FileList\n const directoryName =\n selectedFiles?.[0]?.webkitRelativePath?.split('/')[0] ?? '';\n\n // Load saved PAT for the detected provider\n useEffect(() => {\n if (!provider || !patStorageKey) return;\n const saved = localStorage.getItem(patStorageKey);\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing from localStorage\n if (saved) setPat(saved);\n else setPat('');\n }, [provider, patStorageKey]);\n\n // Clear errors when switching source mode\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- reset on dep change\n setError(null);\n }, [source]);\n\n function handleSubmit(e: FormEvent) {\n e.preventDefault();\n\n if (source === 'directory') {\n if (!selectedFiles || selectedFiles.length === 0) {\n setError('Select a directory first.');\n return;\n }\n setError(null);\n setLoading(true);\n onSubmit({\n type: 'index-directory',\n files: selectedFiles,\n name: directoryName || 'local',\n });\n return;\n }\n\n // URL mode\n if (!provider) {\n setError(\n 'Enter a GitHub, GitLab, Bitbucket, or Azure DevOps repository URL.',\n );\n return;\n }\n if (validationMessage) {\n return;\n }\n setError(null);\n setLoading(true);\n\n if (patStorageKey) {\n if (pat) localStorage.setItem(patStorageKey, pat);\n else localStorage.removeItem(patStorageKey);\n }\n\n saveToHistory(repoUrl);\n\n onSubmit({\n type: 'index-repo',\n repoUrl,\n token: pat || undefined,\n ref: ref || undefined,\n });\n }\n\n // --- Hero content based on source mode ---\n\n const heroIcon =\n source === 'directory' ? (\n <div className=\"hero-icon hero-icon--provider\">\n <FolderIcon />\n </div>\n ) : (\n <ProviderIconStrip selected={provider} />\n );\n\n const title =\n source === 'directory'\n ? 'Add Local Directory'\n : provider\n ? `Add from ${PROVIDER_DISPLAY_NAME[provider]}`\n : 'Add Repository';\n\n const subtitle =\n source === 'directory'\n ? 'Select a directory to index its structure into the graph'\n : provider\n ? `Enter a ${PROVIDER_DISPLAY_NAME[provider]} repository URL to index`\n : 'Enter a repository URL to index its structure into the graph';\n\n return (\n <div className=\"modal-backdrop\" onClick={dismissable ? onClose : undefined}>\n <div className=\"modal-card\" onClick={(e) => e.stopPropagation()}>\n {/* Source mode toggle */}\n <div className=\"source-toggle\">\n <div className=\"chip-toggle\">\n <button\n type=\"button\"\n className={`chip-toggle-btn${source === 'url' ? ' active' : ''}`}\n onClick={() => setSource('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`chip-toggle-btn${source === 'directory' ? ' active' : ''}`}\n onClick={() => setSource('directory')}\n >\n Directory\n </button>\n </div>\n </div>\n\n <div className=\"form-hero\">\n {heroIcon}\n <h2>{title}</h2>\n <p className=\"hero-subtitle\">{subtitle}</p>\n </div>\n\n <form onSubmit={handleSubmit}>\n <div className=\"form-fields\">\n {source === 'url' ? (\n <>\n <div className=\"form-info\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n <span>\n Repository archives are fetched through the OpenTrace API\n server to avoid browser CORS restrictions. Your access token\n (if provided) is forwarded but never stored on the server.\n </span>\n </div>\n\n {!provider && (\n <div className=\"example-repos\">\n <span className=\"example-repos-label\">Examples:</span>\n {EXAMPLE_REPOS.map((repo) => (\n <button\n key={repo.url}\n type=\"button\"\n className=\"example-repo-chip\"\n onClick={() => setRepoUrl(repo.url)}\n title={repo.description}\n >\n {repo.name}\n <span\n className={`example-repo-size example-repo-size--${repo.size.toLowerCase()}`}\n >\n {repo.size}\n </span>\n </button>\n ))}\n </div>\n )}\n\n <div className=\"autocomplete-wrapper\">\n <input\n ref={urlInputRef}\n type=\"text\"\n required\n className=\"input-pill\"\n placeholder=\"https://github.com/owner/repo or https://bitbucket.org/ws/repo\"\n value={repoUrl}\n onChange={(e) => {\n setRepoUrl(e.target.value);\n if (!showHistory) setShowHistory(true);\n }}\n onFocus={() => setShowHistory(true)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setShowHistory(false);\n }}\n autoFocus\n autoComplete=\"off\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-testid=\"repo-url-input\"\n />\n {showHistory && filteredHistory.length > 0 && (\n <div ref={dropdownRef} className=\"autocomplete-dropdown\">\n <div className=\"autocomplete-label\">Recent</div>\n {filteredHistory.map((url) => (\n <div\n key={url}\n className=\"autocomplete-item\"\n role=\"option\"\n onMouseDown={(e) => {\n e.preventDefault();\n setRepoUrl(url);\n setShowHistory(false);\n urlInputRef.current?.focus();\n }}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"1 4 1 10 7 10\" />\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\n </svg>\n <span className=\"autocomplete-item-text\">\n {url\n .replace(/^https?:\\/\\/(www\\.)?/, '')\n .replace(/\\.git$/, '')}\n </span>\n <button\n type=\"button\"\n className=\"autocomplete-item-remove\"\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHistory(removeFromHistory(url));\n }}\n aria-label=\"Remove from history\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {provider && (\n <div className=\"input-pill-row\">\n <svg\n className=\"input-icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <input\n type={showPat ? 'text' : 'password'}\n className=\"input-pill input-pill--icon\"\n placeholder={`${provider ? PROVIDER_DISPLAY_NAME[provider] : ''} access token (optional, for private repos)`}\n value={pat}\n onChange={(e) => setPat(e.target.value)}\n />\n <button\n type=\"button\"\n className=\"input-toggle\"\n onClick={() => setShowPat(!showPat)}\n tabIndex={-1}\n aria-label={showPat ? 'Hide token' : 'Show token'}\n >\n {showPat ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n )}\n </button>\n </div>\n )}\n </>\n ) : (\n <div className=\"directory-picker\">\n <input\n ref={fileInputRef}\n type=\"file\"\n /* @ts-expect-error webkitdirectory is non-standard but widely supported */\n webkitdirectory=\"\"\n directory=\"\"\n multiple\n className=\"directory-input\"\n onChange={(e) => setSelectedFiles(e.target.files)}\n />\n <button\n type=\"button\"\n className=\"input-pill directory-browse-btn\"\n onClick={() => fileInputRef.current?.click()}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\" />\n </svg>\n {directoryName ? (\n <span className=\"directory-name\">\n {directoryName}{' '}\n <span className=\"directory-count\">\n ({selectedFiles?.length ?? 0} files)\n </span>\n </span>\n ) : (\n 'Choose Directory...'\n )}\n </button>\n </div>\n )}\n </div>\n\n {error && (\n <div className=\"form-error\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n <span>{error}</span>\n </div>\n )}\n\n {validationMessage && (\n <div className=\"form-indexed\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n <span>{validationMessage}</span>\n </div>\n )}\n\n <button\n type=\"submit\"\n className=\"btn-cta\"\n disabled={loading || !!validationMessage}\n >\n {loading ? (\n <>\n <span className=\"btn-spinner\" />\n Indexing...\n </>\n ) : (\n <>\n Add & Index\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n <polyline points=\"12 5 19 12 12 19\" />\n </svg>\n </>\n )}\n </button>\n\n <div className=\"form-chips\">\n {source === 'url' && (\n <div className=\"chip\">\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\" />\n <circle cx=\"18\" cy=\"6\" r=\"3\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <path d=\"M18 9a9 9 0 0 1-9 9\" />\n </svg>\n <input\n type=\"text\"\n className=\"chip-input\"\n placeholder=\"Branch: main\"\n value={ref}\n onChange={(e) => setRef(e.target.value)}\n autoComplete=\"off\"\n data-1p-ignore\n data-lpignore=\"true\"\n />\n </div>\n )}\n {dismissable && (\n <button type=\"button\" className=\"chip\" onClick={onClose}>\n Cancel\n </button>\n )}\n </div>\n </form>\n </div>\n </div>\n );\n}\n","/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * IndexingProgress — overlay showing indexing status.\n *\n * Generic version: receives stage configuration as props instead of\n * relying on proto-generated JobPhase enum.\n */\n\nimport type {\n IndexingProgressProps,\n StageConfig,\n StageState,\n} from './types';\nimport './indexing-base.css';\nimport './IndexingProgress.css';\n\n// --- Multi-Stage Progress ---\n\n/** Format a byte count as a human-readable MB string. */\nfunction formatMB(bytes: number): string {\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction StageProgressRow({\n label,\n stage,\n removing,\n}: {\n label: string;\n stage: StageState;\n removing?: boolean;\n}) {\n const isCompleted = stage.status === 'completed';\n const isActive = stage.status === 'active';\n const indeterminate = isActive && stage.total === 0;\n const pct =\n stage.total > 0 ? Math.min(100, (stage.current / stage.total) * 100) : 0;\n const isBytes = stage.format === 'bytes';\n\n let cls = 'stage-row';\n if (removing) cls += ' stage-row--removing';\n else if (isCompleted) cls += ' stage-row--completed';\n else if (isActive) cls += ' stage-row--active';\n\n // Show completed message or active detail\n const detail = isCompleted\n ? stage.message\n : isActive && stage.message\n ? stage.message\n : '';\n\n return (\n <div className={cls}>\n <div className=\"stage-header\">\n <span className=\"stage-label\">{label}</span>\n <span className=\"stage-count\">\n {stage.total > 0\n ? isBytes\n ? `${formatMB(stage.current)} / ${formatMB(stage.total)}`\n : `${stage.current}/${stage.total}`\n : stage.current > 0\n ? isBytes\n ? formatMB(stage.current)\n : `${stage.current}`\n : ''}\n </span>\n </div>\n {detail && <span className=\"stage-detail\">{detail}</span>}\n <span\n className={`stage-bar${indeterminate ? ' stage-bar--indeterminate' : ''}`}\n >\n <span\n className=\"stage-bar-fill\"\n style={\n indeterminate ? undefined : { width: `${isCompleted ? 100 : pct}%` }\n }\n />\n </span>\n </div>\n );\n}\n\nfunction MultiStageProgress({\n stages,\n stageConfig,\n}: {\n stages: Record<string, StageState>;\n stageConfig: StageConfig[];\n}) {\n // Build visible entries, filtering out stages that haven't started\n const entries = stageConfig\n .map(({ key, label }) => ({\n key,\n label,\n stage: stages[key],\n }))\n .filter((e): e is typeof e & { stage: StageState } => !!e.stage);\n\n // Find the last completed stage — all completed stages before it are \"stale\"\n let lastCompletedIdx = -1;\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].stage.status === 'completed') {\n lastCompletedIdx = i;\n break;\n }\n }\n\n return (\n <div className=\"multi-stage-progress\">\n {entries.map(({ key, label, stage }, i) => (\n <StageProgressRow\n key={key}\n label={label}\n stage={stage}\n removing={stage.status === 'completed' && i < lastCompletedIdx}\n />\n ))}\n </div>\n );\n}\n\n// --- Stats Grid ---\n\nfunction StatsGrid({\n nodes,\n relationships,\n}: {\n nodes: number;\n relationships: number;\n}) {\n return (\n <div className=\"indexing-stats-grid\">\n <div className=\"stat-card\">\n <span className=\"stat-value\">{nodes}</span>\n <span className=\"stat-label\">Nodes</span>\n </div>\n <div className=\"stat-card\">\n <span className=\"stat-value\">{relationships}</span>\n <span className=\"stat-label\">Edges</span>\n </div>\n </div>\n );\n}\n\n// --- Main Component ---\n\nexport default function IndexingProgress({\n state,\n stages: stageConfig,\n icon,\n onClose,\n onCancel,\n onMinimize,\n title,\n message,\n}: IndexingProgressProps) {\n // --- Error ---\n if (state.status === 'error') {\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n\n <div className=\"failed-content\">\n <div className=\"failed-icon\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\">\n <circle\n cx=\"16\"\n cy=\"16\"\n r=\"14\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n fill=\"color-mix(in oklch, currentColor 10%, transparent)\"\n />\n <line\n x1=\"11\"\n y1=\"11\"\n x2=\"21\"\n y2=\"21\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n />\n <line\n x1=\"21\"\n y1=\"11\"\n x2=\"11\"\n y2=\"21\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </div>\n <h2>{title ?? 'Indexing Failed'}</h2>\n {state.error && <p className=\"failed-message\">{state.error}</p>}\n </div>\n\n {(state.nodesCreated > 0 || state.relationshipsCreated > 0) && (\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n )}\n\n <button className=\"btn-cta btn-cta--secondary\" onClick={onClose}>\n Close\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n // --- Done ---\n if (state.status === 'done') {\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n\n <div className=\"done-content\">\n <div className=\"done-checkmark\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\">\n <circle\n cx=\"16\"\n cy=\"16\"\n r=\"14\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n fill=\"color-mix(in oklch, currentColor 15%, transparent)\"\n />\n <polyline\n className=\"done-check-path\"\n points=\"10,16.5 14,20.5 22,12\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </div>\n <h2>{title ?? 'Complete'}</h2>\n </div>\n\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n\n {message && <p className=\"indexing-message\">{message}</p>}\n\n <button\n className=\"btn-cta btn-cta--secondary\"\n onClick={onMinimize ?? onClose}\n >\n {onMinimize ? 'Minimize' : 'Close'}\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n // --- Running ---\n return (\n <div className=\"modal-backdrop\">\n <div\n className=\"modal-card modal-card-wide\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"indexing-header\">\n {icon && <span className=\"indexing-header-icon\">{icon}</span>}\n <h2>{title ?? 'Indexing Repository'}</h2>\n </div>\n <div className=\"indexing-progress\">\n <MultiStageProgress\n stages={state.stages}\n stageConfig={stageConfig}\n />\n <StatsGrid\n nodes={state.nodesCreated}\n relationships={state.relationshipsCreated}\n />\n {message && <p className=\"indexing-message\">{message}</p>}\n <button\n className=\"btn-cta btn-cta--secondary\"\n onClick={onMinimize ?? onCancel}\n >\n {onMinimize ? 'Minimize' : 'Cancel'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/*\n * Copyright 2026 OpenTrace Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Normalize Git remote URLs to HTTPS format.\n *\n * Converts SSH URLs (SCP-style and ssh:// protocol) to their HTTPS\n * equivalents so existing GitHub/GitLab URL parsers can handle them.\n */\n\n/**\n * Convert any common Git remote URL to an HTTPS URL.\n *\n * Handles:\n * - SCP-style: git@host:owner/repo[.git] → https://host/owner/repo\n * - SSH protocol: ssh://git@host/owner/repo[.git] → https://host/owner/repo\n * - HTTPS/other: passed through unchanged (with .git suffix stripped)\n */\nexport function normalizeRepoUrl(raw: string): string {\n const trimmed = raw.trim();\n\n // SCP-style: git@github.com:owner/repo.git\n const scpMatch = trimmed.match(/^[\\w.-]+@([^:]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n const path = stripDotGit(scpMatch[2]);\n return `https://${host}/${path}`;\n }\n\n // SSH protocol: ssh://git@github.com/owner/repo.git\n const sshMatch = trimmed.match(/^ssh:\\/\\/[\\w.-]+@([^/]+)\\/(.+)$/);\n if (sshMatch) {\n const host = sshMatch[1];\n const path = stripDotGit(sshMatch[2]);\n return `https://${host}/${path}`;\n }\n\n // Everything else: strip .git suffix if present, pass through\n return stripDotGit(trimmed);\n}\n\nfunction stripDotGit(s: string): string {\n return s.endsWith('.git') ? s.slice(0, -4) : s;\n}\n"],"names":["jsx","jsxs","useState","useRef","useEffect","useMemo","Fragment"],"mappings":";;;AA8BO,SAAS,eACd,KAC0D;AAC1D,QAAM,QAAQ,IAAI,YAAA;AAClB,MAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,MAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,MAAI,MAAM,SAAS,WAAW,EAAG,QAAO;AACxC,MAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,kBAAkB;AACtE,WAAO;AACT,SAAO;AACT;AAEA,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,SAAS,cAAwB;AAC/B,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW;AAC5C,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO,MAAM,QAAQ,MAAM,IACvB,OAAO,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,IAChE,CAAA;AAAA,EACN,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAAa;AAClC,QAAM,UAAU,cAAc,OAAO,CAAC,MAAM,MAAM,GAAG;AACrD,UAAQ,QAAQ,GAAG;AACnB,eAAa;AAAA,IACX;AAAA,IACA,KAAK,UAAU,QAAQ,MAAM,GAAG,WAAW,CAAC;AAAA,EAAA;AAEhD;AAEA,SAAS,kBAAkB,KAAuB;AAChD,QAAM,UAAU,cAAc,OAAO,CAAC,MAAM,MAAM,GAAG;AACrD,eAAa,QAAQ,aAAa,KAAK,UAAU,OAAO,CAAC;AACzD,SAAO;AACT;AAEA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQA,MAAM,iBAGF;AAAA,EACF,QAAQ;AAAA;AAAA,IAEN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,QAAQ;AAAA;AAAA,IAEN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,WAAW;AAAA;AAAA,IAET,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAAA,EAEV,aAAa;AAAA;AAAA,IAEX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;AAGA,MAAM,oBAAqD;AAAA,EACzD,QAAQ,MACNA,2BAAAA,IAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,4jBAA2jB,GACrkB;AAAA,EAEF,QAAQ,MACNC,2BAAAA,KAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,eAAc,MAAK,gBACzD,UAAA;AAAA,IAAAD,2BAAAA,IAAC,QAAA,EAAK,GAAE,2CAA0C,SAAQ,QAAO;AAAA,IACjEA,2BAAAA,IAAC,QAAA,EAAK,GAAE,0CAAyC,SAAQ,OAAM;AAAA,IAC/DA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEVA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEVA,2BAAAA,IAAC,QAAA,EAAK,GAAE,0CAAyC,SAAQ,OAAM;AAAA,IAC/DA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEVA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,GAAE;AAAA,QACF,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,EACV,GACF;AAAA,EAEF,WAAW,MACTA,2BAAAA,IAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,wLAAuL,GACjM;AAAA,EAEF,aAAa,MACXA,2BAAAA,IAAC,OAAA,EAAI,OAAM,QAAO,QAAO,QAAO,SAAQ,aAAY,MAAK,gBACvD,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,iKAAgK,EAAA,CAC1K;AAEJ;AAEA,SAAS,kBAAkB,EAAE,YAAyC;AACpE,yCACG,OAAA,EAAI,WAAW,eAAe,WAAW,yBAAyB,KAEjE,UAAA;AAAA,IAAAC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,gBAAgB,WAAW,2BAA2B,EAAE;AAAA,QACnE,OAAM;AAAA,QACN,QAAO;AAAA,QACP,SAAQ;AAAA,QAER,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,SAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAEVA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,IAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,SAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA;AAAA,IAGD,eAAe,IAAI,CAAC,QAAQ;AAC3B,YAAM,OAAO,kBAAkB,GAAG;AAClC,YAAM,QAAQ,eAAe,GAAG;AAChC,YAAM,OAAO,CAAC,WACV,MAAM,UACN,QAAQ,WACN,MAAM,OACN,MAAM;AACZ,aACEA,2BAAAA,IAAC,OAAA,EAAc,WAAU,cAAa,OAAO,EAAE,UAAU,KAAA,GACvD,UAAAA,2BAAAA,IAAC,MAAA,CAAA,CAAK,EAAA,GADE,GAEV;AAAA,IAEJ,CAAC;AAAA,EAAA,GACH;AAEJ;AAEA,SAAS,aAAa;AACpB,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MAEf,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,8EAAA,CAA8E;AAAA,IAAA;AAAA,EAAA;AAG5F;AAEA,MAAM,wBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,aAAa;AACf;AAMA,MAAM,gBAKA;AAAA,EACJ;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAAA,EAER;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAEV;AAIA,SAAwB,aAAa;AAAA,EACnC;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAsB;AACpB,QAAM,CAAC,QAAQ,SAAS,IAAIE,EAAAA,SAAqB,KAAK;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIA,EAAAA,SAAS,EAAE;AACzC,QAAM,CAAC,SAAS,UAAU,IAAIA,EAAAA,SAAmB,WAAW;AAC5D,QAAM,CAAC,aAAa,cAAc,IAAIA,EAAAA,SAAS,KAAK;AACpD,QAAM,CAAC,KAAK,MAAM,IAAIA,EAAAA,SAAS,EAAE;AACjC,QAAM,CAAC,KAAK,MAAM,IAAIA,EAAAA,SAAS,EAAE;AACjC,QAAM,CAAC,SAAS,UAAU,IAAIA,EAAAA,SAAS,KAAK;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAIA,EAAAA,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,EAAAA,SAAwB,IAAI;AACtD,QAAM,CAAC,eAAe,gBAAgB,IAAIA,EAAAA,SAA0B,IAAI;AACxE,QAAM,eAAeC,EAAAA,OAAyB,IAAI;AAClD,QAAM,cAAcA,EAAAA,OAAyB,IAAI;AACjD,QAAM,cAAcA,EAAAA,OAAuB,IAAI;AAG/CC,IAAAA,UAAU,MAAM;AACd,QAAI,WAAW,OAAO;AACpB,kBAAY,SAAS,MAAA;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGXA,IAAAA,UAAU,MAAM;AACd,aAAS,YAAY,GAAe;AAClC,UACE,YAAY,WACZ,CAAC,YAAY,QAAQ,SAAS,EAAE,MAAc,KAC9C,EAAE,WAAW,YAAY,SACzB;AACA,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,WAAW;AAClD,WAAO,MAAM,SAAS,oBAAoB,aAAa,WAAW;AAAA,EACpE,GAAG,CAAA,CAAE;AAEL,QAAM,kBAAkB,QAAQ;AAAA,IAC9B,CAAC,QAAQ,CAAC,WAAW,IAAI,cAAc,SAAS,QAAQ,YAAA,CAAa;AAAA,EAAA;AAGvE,QAAM,WAAW,WAAW,QAAQ,eAAe,OAAO,IAAI;AAC9D,QAAM,gBAAgB,WAAW,MAAM,QAAQ,SAAS;AAGxD,QAAM,oBAAoBC,EAAAA,QAAQ,MAAM;AACtC,QAAI,WAAW,SAAS,CAAC,QAAQ,UAAU,CAAC,WAAY,QAAO;AAC/D,WAAO,WAAW,OAAO;AAAA,EAC3B,GAAG,CAAC,QAAQ,SAAS,UAAU,CAAC;AAGhC,QAAM,gBACJ,gBAAgB,CAAC,GAAG,oBAAoB,MAAM,GAAG,EAAE,CAAC,KAAK;AAG3DD,IAAAA,UAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,cAAe;AACjC,UAAM,QAAQ,aAAa,QAAQ,aAAa;AAEhD,QAAI,cAAc,KAAK;AAAA,gBACX,EAAE;AAAA,EAChB,GAAG,CAAC,UAAU,aAAa,CAAC;AAG5BA,IAAAA,UAAU,MAAM;AAEd,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,MAAM,CAAC;AAEX,WAAS,aAAa,GAAc;AAClC,MAAE,eAAA;AAEF,QAAI,WAAW,aAAa;AAC1B,UAAI,CAAC,iBAAiB,cAAc,WAAW,GAAG;AAChD,iBAAS,2BAA2B;AACpC;AAAA,MACF;AACA,eAAS,IAAI;AACb,iBAAW,IAAI;AACf,eAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM,iBAAiB;AAAA,MAAA,CACxB;AACD;AAAA,IACF;AAGA,QAAI,CAAC,UAAU;AACb;AAAA,QACE;AAAA,MAAA;AAEF;AAAA,IACF;AACA,QAAI,mBAAmB;AACrB;AAAA,IACF;AACA,aAAS,IAAI;AACb,eAAW,IAAI;AAEf,QAAI,eAAe;AACjB,UAAI,IAAK,cAAa,QAAQ,eAAe,GAAG;AAAA,UAC3C,cAAa,WAAW,aAAa;AAAA,IAC5C;AAEA,kBAAc,OAAO;AAErB,aAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,MACA,OAAO,OAAO;AAAA,MACd,KAAK,OAAO;AAAA,IAAA,CACb;AAAA,EACH;AAIA,QAAM,WACJ,WAAW,cACTJ,2BAAAA,IAAC,SAAI,WAAU,iCACb,UAAAA,2BAAAA,IAAC,YAAA,CAAA,CAAW,EAAA,CACd,IAEAA,2BAAAA,IAAC,mBAAA,EAAkB,UAAU,UAAU;AAG3C,QAAM,QACJ,WAAW,cACP,wBACA,WACE,YAAY,sBAAsB,QAAQ,CAAC,KAC3C;AAER,QAAM,WACJ,WAAW,cACP,6DACA,WACE,WAAW,sBAAsB,QAAQ,CAAC,6BAC1C;AAER,wCACG,OAAA,EAAI,WAAU,kBAAiB,SAAS,cAAc,UAAU,QAC/D,UAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,cAAa,SAAS,CAAC,MAAM,EAAE,mBAE5C,UAAA;AAAA,IAAAD,2BAAAA,IAAC,SAAI,WAAU,iBACb,UAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAAD,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,kBAAkB,WAAW,QAAQ,YAAY,EAAE;AAAA,UAC9D,SAAS,MAAM,UAAU,KAAK;AAAA,UAC/B,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGDA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,kBAAkB,WAAW,cAAc,YAAY,EAAE;AAAA,UACpE,SAAS,MAAM,UAAU,WAAW;AAAA,UACrC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACF,EAAA,CACF;AAAA,IAEAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,MAAA;AAAA,MACDD,2BAAAA,IAAC,QAAI,UAAA,MAAA,CAAM;AAAA,MACXA,2BAAAA,IAAC,KAAA,EAAE,WAAU,iBAAiB,UAAA,SAAA,CAAS;AAAA,IAAA,GACzC;AAAA,IAEAC,2BAAAA,KAAC,QAAA,EAAK,UAAU,cACd,UAAA;AAAA,MAAAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,eACZ,UAAA,WAAW,QACVC,2BAAAA,KAAAK,WAAAA,UAAA,EACE,UAAA;AAAA,QAAAL,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAAA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAAD,+BAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,gBAC/BA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,gBACtCA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,SAAQ,IAAG,IAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEzCA,2BAAAA,IAAC,UAAK,UAAA,oLAAA,CAIN;AAAA,QAAA,GACF;AAAA,QAEC,CAAC,YACAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,UAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAU,uBAAsB,UAAA,aAAS;AAAA,UAC9C,cAAc,IAAI,CAAC,SAClBC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,WAAW,KAAK,GAAG;AAAA,cAClC,OAAO,KAAK;AAAA,cAEX,UAAA;AAAA,gBAAA,KAAK;AAAA,gBACND,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW,wCAAwC,KAAK,KAAK,aAAa;AAAA,oBAEzE,UAAA,KAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACR;AAAA,YAAA;AAAA,YAXK,KAAK;AAAA,UAAA,CAab;AAAA,QAAA,GACH;AAAA,QAGFC,2BAAAA,KAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,UAAQ;AAAA,cACR,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,MAAM;AACf,2BAAW,EAAE,OAAO,KAAK;AACzB,oBAAI,CAAC,YAAa,gBAAe,IAAI;AAAA,cACvC;AAAA,cACA,SAAS,MAAM,eAAe,IAAI;AAAA,cAClC,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,SAAU,gBAAe,KAAK;AAAA,cAC9C;AAAA,cACA,WAAS;AAAA,cACT,cAAa;AAAA,cACb,kBAAc;AAAA,cACd,iBAAc;AAAA,cACd,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAEb,eAAe,gBAAgB,SAAS,qCACtC,OAAA,EAAI,KAAK,aAAa,WAAU,yBAC/B,UAAA;AAAA,YAAAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,sBAAqB,UAAA,UAAM;AAAA,YACzC,gBAAgB,IAAI,CAAC,QACpBC,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,aAAa,CAAC,MAAM;AAClB,oBAAE,eAAA;AACF,6BAAW,GAAG;AACd,iCAAe,KAAK;AACpB,8BAAY,SAAS,MAAA;AAAA,gBACvB;AAAA,gBAEA,UAAA;AAAA,kBAAAA,2BAAAA;AAAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,OAAM;AAAA,sBACN,QAAO;AAAA,sBACP,SAAQ;AAAA,sBACR,MAAK;AAAA,sBACL,QAAO;AAAA,sBACP,aAAY;AAAA,sBACZ,eAAc;AAAA,sBACd,gBAAe;AAAA,sBAEf,UAAA;AAAA,wBAAAD,2BAAAA,IAAC,YAAA,EAAS,QAAO,gBAAA,CAAgB;AAAA,wBACjCA,2BAAAA,IAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAE9CA,2BAAAA,IAAC,QAAA,EAAK,WAAU,0BACb,UAAA,IACE,QAAQ,wBAAwB,EAAE,EAClC,QAAQ,UAAU,EAAE,EAAA,CACzB;AAAA,kBACAA,2BAAAA;AAAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,aAAa,CAAC,MAAM;AAClB,0BAAE,eAAA;AACF,0BAAE,gBAAA;AACF,mCAAW,kBAAkB,GAAG,CAAC;AAAA,sBACnC;AAAA,sBACA,cAAW;AAAA,sBAEX,UAAAC,2BAAAA;AAAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,OAAM;AAAA,0BACN,QAAO;AAAA,0BACP,SAAQ;AAAA,0BACR,MAAK;AAAA,0BACL,QAAO;AAAA,0BACP,aAAY;AAAA,0BACZ,eAAc;AAAA,0BACd,gBAAe;AAAA,0BAEf,UAAA;AAAA,4BAAAD,2BAAAA,IAAC,YAAA,EAAS,QAAO,eAAA,CAAe;AAAA,4BAChCA,2BAAAA,IAAC,QAAA,EAAK,GAAE,gDAAA,CAAgD;AAAA,4BACxDA,2BAAAA,IAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,4BACnBA,2BAAAA,IAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACrB;AAAA,kBAAA;AAAA,gBACF;AAAA,cAAA;AAAA,cArDK;AAAA,YAAA,CAuDR;AAAA,UAAA,EAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QAEC,YACCC,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAAA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAAD,2BAAAA,IAAC,QAAA,EAAK,GAAE,KAAI,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,IAAG,KAAI;AAAA,gBACxDA,2BAAAA,IAAC,QAAA,EAAK,GAAE,2BAAA,CAA2B;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAErCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,UAAU,SAAS;AAAA,cACzB,WAAU;AAAA,cACV,aAAa,GAAG,WAAW,sBAAsB,QAAQ,IAAI,EAAE;AAAA,cAC/D,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAExCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,WAAW,CAAC,OAAO;AAAA,cAClC,UAAU;AAAA,cACV,cAAY,UAAU,eAAe;AAAA,cAEpC,UAAA,UACCC,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAAD,2BAAAA,IAAC,QAAA,EAAK,GAAE,kFAAA,CAAkF;AAAA,oBAC1FA,2BAAAA,IAAC,QAAA,EAAK,GAAE,yEAAA,CAAyE;AAAA,oBACjFA,2BAAAA,IAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,oBACpCA,2BAAAA,IAAC,QAAA,EAAK,GAAE,mCAAA,CAAmC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA,IAG7CC,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAA;AAAA,oBAAAD,2BAAAA,IAAC,QAAA,EAAK,GAAE,+CAAA,CAA+C;AAAA,mDACtD,UAAA,EAAO,IAAG,MAAK,IAAG,MAAK,GAAE,IAAA,CAAI;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YAChC;AAAA,UAAA;AAAA,QAEJ,EAAA,CACF;AAAA,MAAA,EAAA,CAEJ,IAEAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAAD,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YAEL,iBAAgB;AAAA,YAChB,WAAU;AAAA,YACV,UAAQ;AAAA,YACR,WAAU;AAAA,YACV,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAElDC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM,aAAa,SAAS,MAAA;AAAA,YAErC,UAAA;AAAA,cAAAD,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAM;AAAA,kBACN,QAAO;AAAA,kBACP,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBAEf,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,8EAAA,CAA8E;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEvF,gBACCC,2BAAAA,KAAC,QAAA,EAAK,WAAU,kBACb,UAAA;AAAA,gBAAA;AAAA,gBAAe;AAAA,gBAChBA,2BAAAA,KAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA;AAAA,kBAAA;AAAA,kBAC9B,eAAe,UAAU;AAAA,kBAAE;AAAA,gBAAA,EAAA,CAC/B;AAAA,cAAA,EAAA,CACF,IAEA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF,EAAA,CAEJ;AAAA,MAEC,SACCA,2BAAAA,KAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAAA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,gBAAe;AAAA,YAEf,UAAA;AAAA,cAAAD,+BAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,cAC/BA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,cACpCA,2BAAAA,IAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEtCA,2BAAAA,IAAC,UAAM,UAAA,MAAA,CAAM;AAAA,MAAA,GACf;AAAA,MAGD,qBACCC,2BAAAA,KAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,QAAAA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,gBAAe;AAAA,YAEf,UAAA;AAAA,cAAAD,2BAAAA,IAAC,QAAA,EAAK,GAAE,qCAAA,CAAqC;AAAA,cAC7CA,2BAAAA,IAAC,YAAA,EAAS,QAAO,wBAAA,CAAwB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAE3CA,2BAAAA,IAAC,UAAM,UAAA,kBAAA,CAAkB;AAAA,MAAA,GAC3B;AAAA,MAGFA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,UAAU,WAAW,CAAC,CAAC;AAAA,UAEtB,oBACCC,2BAAAA,KAAAK,WAAAA,UAAA,EACE,UAAA;AAAA,YAAAN,2BAAAA,IAAC,QAAA,EAAK,WAAU,cAAA,CAAc;AAAA,YAAE;AAAA,UAAA,EAAA,CAElC,IAEAC,2BAAAA,KAAAK,WAAAA,UAAA,EAAE,UAAA;AAAA,YAAA;AAAA,YAEAL,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAM;AAAA,gBACN,QAAO;AAAA,gBACP,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,aAAY;AAAA,gBACZ,eAAc;AAAA,gBACd,gBAAe;AAAA,gBAEf,UAAA;AAAA,kBAAAD,2BAAAA,IAAC,QAAA,EAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,kBACrCA,2BAAAA,IAAC,YAAA,EAAS,QAAO,mBAAA,CAAmB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACtC,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,MAIJC,2BAAAA,KAAC,OAAA,EAAI,WAAU,cACZ,UAAA;AAAA,QAAA,WAAW,SACVA,gCAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,UAAAA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,UAAA;AAAA,gBAAAD,2BAAAA,IAAC,QAAA,EAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,+CAClC,UAAA,EAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI;AAAA,+CAC5B,UAAA,EAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI;AAAA,gBAC7BA,2BAAAA,IAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEhCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,cACtC,cAAa;AAAA,cACb,kBAAc;AAAA,cACd,iBAAc;AAAA,YAAA;AAAA,UAAA;AAAA,QAChB,GACF;AAAA,QAED,8CACE,UAAA,EAAO,MAAK,UAAS,WAAU,QAAO,SAAS,SAAS,UAAA,SAAA,CAEzD;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;ACrwBA,SAAS,SAAS,OAAuB;AACvC,UAAQ,SAAS,OAAO,OAAO,QAAQ,CAAC,IAAI;AAC9C;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,MAAM,WAAW;AACrC,QAAM,WAAW,MAAM,WAAW;AAClC,QAAM,gBAAgB,YAAY,MAAM,UAAU;AAClD,QAAM,MACJ,MAAM,QAAQ,IAAI,KAAK,IAAI,KAAM,MAAM,UAAU,MAAM,QAAS,GAAG,IAAI;AACzE,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,MAAM;AACV,MAAI,SAAU,QAAO;AAAA,WACZ,YAAa,QAAO;AAAA,WACpB,SAAU,QAAO;AAG1B,QAAM,SAAS,cACX,MAAM,UACN,YAAY,MAAM,UAChB,MAAM,UACN;AAEN,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAW,KACd,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,MAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAU,eAAe,UAAA,OAAM;AAAA,qCACpC,QAAA,EAAK,WAAU,eACb,UAAA,MAAM,QAAQ,IACX,UACE,GAAG,SAAS,MAAM,OAAO,CAAC,MAAM,SAAS,MAAM,KAAK,CAAC,KACrD,GAAG,MAAM,OAAO,IAAI,MAAM,KAAK,KACjC,MAAM,UAAU,IACd,UACE,SAAS,MAAM,OAAO,IACtB,GAAG,MAAM,OAAO,KAClB,GAAA,CACR;AAAA,IAAA,GACF;AAAA,IACC,UAAUA,2BAAAA,IAAC,QAAA,EAAK,WAAU,gBAAgB,UAAA,QAAO;AAAA,IAClDA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,YAAY,gBAAgB,8BAA8B,EAAE;AAAA,QAEvE,UAAAA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OACE,gBAAgB,SAAY,EAAE,OAAO,GAAG,cAAc,MAAM,GAAG,IAAA;AAAA,UAAI;AAAA,QAAA;AAAA,MAEvE;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AAED,QAAM,UAAU,YACb,IAAI,CAAC,EAAE,KAAK,aAAa;AAAA,IACxB;AAAA,IACA;AAAA,IACA,OAAO,OAAO,GAAG;AAAA,EAAA,EACjB,EACD,OAAO,CAAC,MAA6C,CAAC,CAAC,EAAE,KAAK;AAGjE,MAAI,mBAAmB;AACvB,WAAS,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;AAC5C,QAAI,QAAQ,CAAC,EAAE,MAAM,WAAW,aAAa;AAC3C,yBAAmB;AACnB;AAAA,IACF;AAAA,EACF;AAEA,SACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,wBACZ,UAAA,QAAQ,IAAI,CAAC,EAAE,KAAK,OAAO,MAAA,GAAS,MACnCA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA,UAAU,MAAM,WAAW,eAAe,IAAI;AAAA,IAAA;AAAA,IAHzC;AAAA,EAAA,CAKR,GACH;AAEJ;AAIA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AACF,GAGG;AACD,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAU,cAAc,UAAA,OAAM;AAAA,MACpCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,cAAa,UAAA,QAAA,CAAK;AAAA,IAAA,GACpC;AAAA,IACAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAU,cAAc,UAAA,eAAc;AAAA,MAC5CA,2BAAAA,IAAC,QAAA,EAAK,WAAU,cAAa,UAAA,QAAA,CAAK;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,GACF;AAEJ;AAIA,SAAwB,iBAAiB;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AAExB,MAAI,MAAM,WAAW,SAAS;AAC5B,WACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBACb,UAAAA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,QAElB,UAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAGFC,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,eACb,UAAAC,2BAAAA,KAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACnD,UAAA;AAAA,cAAAD,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEPA,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEhBA,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,gBAAA;AAAA,cAAA;AAAA,YAChB,EAAA,CACF,EAAA,CACF;AAAA,YACAA,2BAAAA,IAAC,MAAA,EAAI,UAAA,SAAS,kBAAA,CAAkB;AAAA,YAC/B,MAAM,SAASA,2BAAAA,IAAC,OAAE,WAAU,kBAAkB,gBAAM,MAAA,CAAM;AAAA,UAAA,GAC7D;AAAA,WAEE,MAAM,eAAe,KAAK,MAAM,uBAAuB,MACvDA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,yCAIxB,UAAA,EAAO,WAAU,8BAA6B,SAAS,SAAS,UAAA,QAAA,CAEjE;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,EAEJ;AAGA,MAAI,MAAM,WAAW,QAAQ;AAC3B,WACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBACb,UAAAA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,QAElB,UAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAGFC,2BAAAA,KAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,YAAAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBACb,UAAAC,2BAAAA,KAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACnD,UAAA;AAAA,cAAAD,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEPA,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,QAAO;AAAA,kBACP,QAAO;AAAA,kBACP,aAAY;AAAA,kBACZ,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,YACP,EAAA,CACF,EAAA,CACF;AAAA,YACAA,2BAAAA,IAAC,MAAA,EAAI,UAAA,SAAS,WAAA,CAAW;AAAA,UAAA,GAC3B;AAAA,UAEAA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAGtB,WAAWA,2BAAAA,IAAC,KAAA,EAAE,WAAU,oBAAoB,UAAA,SAAQ;AAAA,UAErDA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,cAAc;AAAA,cAEtB,uBAAa,aAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAC7B,EAAA,CACF;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,EAEJ;AAGA,SACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBACb,UAAAC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,MAElB,UAAA;AAAA,QAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,mBACZ,UAAA;AAAA,UAAA,QAAQD,2BAAAA,IAAC,QAAA,EAAK,WAAU,wBAAwB,UAAA,MAAK;AAAA,UACtDA,2BAAAA,IAAC,MAAA,EAAI,UAAA,SAAS,sBAAA,CAAsB;AAAA,QAAA,GACtC;AAAA,QACAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,QAAQ,MAAM;AAAA,cACd;AAAA,YAAA;AAAA,UAAA;AAAA,UAEFA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,MAAM;AAAA,cACb,eAAe,MAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAEtB,WAAWA,2BAAAA,IAAC,KAAA,EAAE,WAAU,oBAAoB,UAAA,SAAQ;AAAA,UACrDA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,cAAc;AAAA,cAEtB,uBAAa,aAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAC7B,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;ACtSO,SAAS,iBAAiB,KAAqB;AACpD,QAAM,UAAU,IAAI,KAAA;AAGpB,QAAM,WAAW,QAAQ,MAAM,wBAAwB;AACvD,MAAI,UAAU;AACZ,UAAM,OAAO,SAAS,CAAC;AACvB,UAAM,OAAO,YAAY,SAAS,CAAC,CAAC;AACpC,WAAO,WAAW,IAAI,IAAI,IAAI;AAAA,EAChC;AAGA,QAAM,WAAW,QAAQ,MAAM,iCAAiC;AAChE,MAAI,UAAU;AACZ,UAAM,OAAO,SAAS,CAAC;AACvB,UAAM,OAAO,YAAY,SAAS,CAAC,CAAC;AACpC,WAAO,WAAW,IAAI,IAAI,IAAI;AAAA,EAChC;AAGA,SAAO,YAAY,OAAO;AAC5B;AAEA,SAAS,YAAY,GAAmB;AACtC,SAAO,EAAE,SAAS,MAAM,IAAI,EAAE,MAAM,GAAG,EAAE,IAAI;AAC/C;;;;;"}