@xyne/workflow-ui 1.3.18 → 1.3.20

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.
Files changed (86) hide show
  1. package/dist/components/dashboard/WorkflowDashboard.d.ts +7 -1
  2. package/dist/components/dashboard/WorkflowDashboard.d.ts.map +1 -1
  3. package/dist/components/dashboard/WorkflowDashboard.js +16 -7
  4. package/dist/components/dashboard/WorkflowDashboard.js.map +1 -1
  5. package/dist/components/execution/ApprovalsView.d.ts +4 -1
  6. package/dist/components/execution/ApprovalsView.d.ts.map +1 -1
  7. package/dist/components/execution/ApprovalsView.js +23 -17
  8. package/dist/components/execution/ApprovalsView.js.map +1 -1
  9. package/dist/components/execution/CitationSourcePanel.d.ts +3 -13
  10. package/dist/components/execution/CitationSourcePanel.d.ts.map +1 -1
  11. package/dist/components/execution/CitationSourcePanel.js +35 -3
  12. package/dist/components/execution/CitationSourcePanel.js.map +1 -1
  13. package/dist/components/execution/ExecutionTabs.d.ts +2 -2
  14. package/dist/components/execution/ExecutionTabs.d.ts.map +1 -1
  15. package/dist/components/execution/ExecutionTabs.js +90 -16
  16. package/dist/components/execution/ExecutionTabs.js.map +1 -1
  17. package/dist/components/execution/ExecutionViewer.d.ts +7 -1
  18. package/dist/components/execution/ExecutionViewer.d.ts.map +1 -1
  19. package/dist/components/execution/ExecutionViewer.js +23 -7
  20. package/dist/components/execution/ExecutionViewer.js.map +1 -1
  21. package/dist/components/execution/origin/OriginTrace.d.ts.map +1 -1
  22. package/dist/components/execution/origin/OriginTrace.js +8 -1
  23. package/dist/components/execution/origin/OriginTrace.js.map +1 -1
  24. package/dist/components/execution/origin/citation-resolver.d.ts +50 -9
  25. package/dist/components/execution/origin/citation-resolver.d.ts.map +1 -1
  26. package/dist/components/execution/origin/citation-resolver.js +98 -18
  27. package/dist/components/execution/origin/citation-resolver.js.map +1 -1
  28. package/dist/components/execution/origin/origin-resolver.d.ts +6 -0
  29. package/dist/components/execution/origin/origin-resolver.d.ts.map +1 -1
  30. package/dist/components/execution/origin/origin-resolver.js +25 -0
  31. package/dist/components/execution/origin/origin-resolver.js.map +1 -1
  32. package/dist/components/index.d.ts +2 -0
  33. package/dist/components/index.d.ts.map +1 -1
  34. package/dist/components/index.js +1 -0
  35. package/dist/components/index.js.map +1 -1
  36. package/dist/components/shared/AttachmentCard.d.ts +4 -5
  37. package/dist/components/shared/AttachmentCard.d.ts.map +1 -1
  38. package/dist/components/shared/AttachmentCard.js +2 -2
  39. package/dist/components/shared/AttachmentCard.js.map +1 -1
  40. package/dist/components/shared/CitationArrow.d.ts.map +1 -1
  41. package/dist/components/shared/CitationArrow.js +67 -11
  42. package/dist/components/shared/CitationArrow.js.map +1 -1
  43. package/dist/components/shared/DocumentViewer.d.ts +3 -4
  44. package/dist/components/shared/DocumentViewer.d.ts.map +1 -1
  45. package/dist/components/shared/DocumentViewer.js +14 -6
  46. package/dist/components/shared/DocumentViewer.js.map +1 -1
  47. package/dist/components/shared/MarkdownCitation.js +1 -1
  48. package/dist/components/shared/MarkdownCitation.js.map +1 -1
  49. package/dist/components/shared/viewers/CsvView.d.ts +3 -1
  50. package/dist/components/shared/viewers/CsvView.d.ts.map +1 -1
  51. package/dist/components/shared/viewers/CsvView.js +16 -3
  52. package/dist/components/shared/viewers/CsvView.js.map +1 -1
  53. package/dist/components/shared/viewers/DocxView.d.ts +3 -1
  54. package/dist/components/shared/viewers/DocxView.d.ts.map +1 -1
  55. package/dist/components/shared/viewers/DocxView.js +5 -1
  56. package/dist/components/shared/viewers/DocxView.js.map +1 -1
  57. package/dist/components/shared/viewers/SheetView.d.ts +3 -1
  58. package/dist/components/shared/viewers/SheetView.d.ts.map +1 -1
  59. package/dist/components/shared/viewers/SheetView.js +18 -3
  60. package/dist/components/shared/viewers/SheetView.js.map +1 -1
  61. package/dist/components/shared/viewers/TextView.d.ts +3 -1
  62. package/dist/components/shared/viewers/TextView.d.ts.map +1 -1
  63. package/dist/components/shared/viewers/TextView.js +9 -4
  64. package/dist/components/shared/viewers/TextView.js.map +1 -1
  65. package/dist/components/shared/viewers/anchor-match.d.ts +44 -0
  66. package/dist/components/shared/viewers/anchor-match.d.ts.map +1 -0
  67. package/dist/components/shared/viewers/anchor-match.js +147 -0
  68. package/dist/components/shared/viewers/anchor-match.js.map +1 -0
  69. package/dist/components/shared/viewers/useDomAnchor.d.ts +41 -0
  70. package/dist/components/shared/viewers/useDomAnchor.d.ts.map +1 -0
  71. package/dist/components/shared/viewers/useDomAnchor.js +125 -0
  72. package/dist/components/shared/viewers/useDomAnchor.js.map +1 -0
  73. package/dist/components/workflows/WorkflowApp.d.ts +19 -0
  74. package/dist/components/workflows/WorkflowApp.d.ts.map +1 -0
  75. package/dist/components/workflows/WorkflowApp.js +121 -0
  76. package/dist/components/workflows/WorkflowApp.js.map +1 -0
  77. package/dist/components/workflows/WorkflowHome.d.ts +8 -2
  78. package/dist/components/workflows/WorkflowHome.d.ts.map +1 -1
  79. package/dist/components/workflows/WorkflowHome.js +11 -5
  80. package/dist/components/workflows/WorkflowHome.js.map +1 -1
  81. package/dist/index.d.ts +2 -2
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +1 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/styles.css +1 -1
  86. package/package.json +1 -1
@@ -1,13 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useEffect, useState } from 'react';
2
+ import { useEffect, useRef, useState } from 'react';
3
3
  import { MarkdownView } from '../MarkdownView.js';
4
4
  import { ViewerLoading } from './chrome.js';
5
+ import { useDomAnchor } from './useDomAnchor.js';
5
6
  // Plain-text / JSON / Markdown renderer. Fetches the file as text (same-origin,
6
7
  // so the auth cookie rides along) and renders by mode. On load failure it
7
8
  // throws during render so the parent ViewerBoundary shows the download fallback.
8
- export default function TextView({ url, mode }) {
9
+ export default function TextView({ url, mode, anchor, }) {
9
10
  const [text, setText] = useState(null);
10
11
  const [failed, setFailed] = useState(false);
12
+ const bodyRef = useRef(null);
13
+ // `text` gates the search: the content only exists in the DOM once it has
14
+ // loaded, and `mode` because switching renderer rebuilds the subtree.
15
+ useDomAnchor(bodyRef, anchor, `${mode}:${String(text?.length ?? -1)}`);
11
16
  useEffect(() => {
12
17
  let cancelled = false;
13
18
  setText(null);
@@ -29,10 +34,10 @@ export default function TextView({ url, mode }) {
29
34
  if (text === null)
30
35
  return _jsx(ViewerLoading, {});
31
36
  if (mode === 'markdown') {
32
- return (_jsx("div", { className: "px-5 py-4 text-[14px] text-[var(--wui-fg)]", children: _jsx(MarkdownView, { children: text }) }));
37
+ return (_jsx("div", { ref: bodyRef, className: "px-5 py-4 text-[14px] text-[var(--wui-fg)]", children: _jsx(MarkdownView, { children: text }) }));
33
38
  }
34
39
  const body = mode === 'json' ? prettyJson(text) : text;
35
- return (_jsx("pre", { className: "whitespace-pre-wrap break-words px-5 py-4 font-mono text-[12.5px] leading-relaxed text-[var(--wui-fg)]", children: body }));
40
+ return (_jsx("div", { ref: bodyRef, children: _jsx("pre", { className: "whitespace-pre-wrap break-words px-5 py-4 font-mono text-[12.5px] leading-relaxed text-[var(--wui-fg)]", children: body }) }));
36
41
  }
37
42
  function prettyJson(t) {
38
43
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"TextView.js","sourceRoot":"","sources":["../../../../src/components/shared/viewers/TextView.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,gFAAgF;AAChF,0EAA0E;AAC1E,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,EAAuD;IACjG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,KAAK,KAAK,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5C,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,IAAI,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAC,aAAa,KAAG,CAAC;IAE5C,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,CACL,cAAK,SAAS,EAAC,4CAA4C,YACzD,KAAC,YAAY,cAAE,IAAI,GAAgB,GAC/B,CACP,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,OAAO,CACL,cAAK,SAAS,EAAC,wGAAwG,YACpH,IAAI,GACD,CACP,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"TextView.js","sourceRoot":"","sources":["../../../../src/components/shared/viewers/TextView.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAe,MAAM,mBAAmB,CAAC;AAE9D,gFAAgF;AAChF,0EAA0E;AAC1E,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,GAAG,EACH,IAAI,EACJ,MAAM,GAKP;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IACpD,0EAA0E;IAC1E,sEAAsE;IACtE,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEvE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,KAAK,KAAK,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5C,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,IAAI,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAC,aAAa,KAAG,CAAC;IAE5C,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,CACL,cAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAC,4CAA4C,YACvE,KAAC,YAAY,cAAE,IAAI,GAAgB,GAC/B,CACP,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,OAAO,CACL,cAAK,GAAG,EAAE,OAAO,YACf,cAAK,SAAS,EAAC,wGAAwG,YACpH,IAAI,GACD,GACF,CACP,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Finding a cited passage inside rendered text — the format-agnostic half of
3
+ * citation anchoring.
4
+ *
5
+ * A citation's `quote` is what the **agent read**, which is rarely byte-identical
6
+ * to what the **viewer renders**: OCR drops or doubles spaces, smart quotes and
7
+ * ligatures differ between the extractor and the renderer, and a passage can be
8
+ * split across elements. An exact `indexOf` therefore fails on precisely the
9
+ * documents citations exist for, and fails *silently* — the reader just sees an
10
+ * unhighlighted page and assumes the citation is wrong.
11
+ *
12
+ * So matching is normalized and laddered: compare on a canonical form, and when
13
+ * the whole phrase misses, fall back to progressively shorter prefixes. The
14
+ * *start* of a quote is reliable even when its middle drifted.
15
+ *
16
+ * Used by every DOM-rendered viewer (text, markdown, json, docx, csv, xlsx) via
17
+ * `useDomAnchor`, and by `PdfView` for its own pdf.js find controller.
18
+ */
19
+ /**
20
+ * Canonical form for comparison: folded characters, whitespace runs collapsed to
21
+ * a single space, trimmed. Used on both haystack and needle so they meet in the
22
+ * middle.
23
+ */
24
+ export declare function normalizeForMatch(s: string): string;
25
+ /**
26
+ * Progressively shorter prefixes of a phrase, longest first.
27
+ *
28
+ * The fallback when a whole quote won't match — because it spans a page break,
29
+ * or its middle drifted in OCR. The start of the value is on the cited page by
30
+ * definition, so a shorter head still lands the reader in the right place.
31
+ *
32
+ * Guards against matching noise: never fewer than 2 words or 4 characters, since
33
+ * a 1-word ladder rung would highlight the first "the" on the page.
34
+ */
35
+ export declare function buildQueryLadder(value: string): string[];
36
+ /**
37
+ * Find `quote` inside `root`'s rendered text and return a `Range` over it.
38
+ *
39
+ * Tries the whole phrase first, then the prefix ladder. Returns `null` when
40
+ * nothing matches — callers should degrade to "opened, not highlighted" rather
41
+ * than pretending.
42
+ */
43
+ export declare function findRange(root: HTMLElement, quote: string): Range | null;
44
+ //# sourceMappingURL=anchor-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-match.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/viewers/anchor-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAiBH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAenD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASxD;AAiDD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAyBxE"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Finding a cited passage inside rendered text — the format-agnostic half of
3
+ * citation anchoring.
4
+ *
5
+ * A citation's `quote` is what the **agent read**, which is rarely byte-identical
6
+ * to what the **viewer renders**: OCR drops or doubles spaces, smart quotes and
7
+ * ligatures differ between the extractor and the renderer, and a passage can be
8
+ * split across elements. An exact `indexOf` therefore fails on precisely the
9
+ * documents citations exist for, and fails *silently* — the reader just sees an
10
+ * unhighlighted page and assumes the citation is wrong.
11
+ *
12
+ * So matching is normalized and laddered: compare on a canonical form, and when
13
+ * the whole phrase misses, fall back to progressively shorter prefixes. The
14
+ * *start* of a quote is reliable even when its middle drifted.
15
+ *
16
+ * Used by every DOM-rendered viewer (text, markdown, json, docx, csv, xlsx) via
17
+ * `useDomAnchor`, and by `PdfView` for its own pdf.js find controller.
18
+ */
19
+ /** Characters that differ between text extractors and renderers but read the same. */
20
+ const CHAR_FOLD = {
21
+ '‘': "'", '’': "'", '‚': "'", '‛': "'", // ‘ ’ ‚ ‛
22
+ '“': '"', '”': '"', '„': '"', '‟': '"', // “ ” „ ‟
23
+ '–': '-', '—': '-', '−': '-', // – — −
24
+ ' ': ' ', ' ': ' ', ' ': ' ', ' ': ' ', // nbsp & friends
25
+ 'ff': 'ff', 'fi': 'fi', 'fl': 'fl', // ff fi fl
26
+ 'ffi': 'ffi', 'ffl': 'ffl',
27
+ };
28
+ /** Fold one character to its canonical form (may expand, e.g. a ligature). */
29
+ function foldChar(ch) {
30
+ return CHAR_FOLD[ch] ?? ch.toLowerCase();
31
+ }
32
+ /**
33
+ * Canonical form for comparison: folded characters, whitespace runs collapsed to
34
+ * a single space, trimmed. Used on both haystack and needle so they meet in the
35
+ * middle.
36
+ */
37
+ export function normalizeForMatch(s) {
38
+ let out = '';
39
+ let pendingSpace = false;
40
+ for (const ch of s) {
41
+ if (/\s/.test(ch)) {
42
+ pendingSpace = out.length > 0;
43
+ continue;
44
+ }
45
+ if (pendingSpace) {
46
+ out += ' ';
47
+ pendingSpace = false;
48
+ }
49
+ out += foldChar(ch);
50
+ }
51
+ return out;
52
+ }
53
+ /**
54
+ * Progressively shorter prefixes of a phrase, longest first.
55
+ *
56
+ * The fallback when a whole quote won't match — because it spans a page break,
57
+ * or its middle drifted in OCR. The start of the value is on the cited page by
58
+ * definition, so a shorter head still lands the reader in the right place.
59
+ *
60
+ * Guards against matching noise: never fewer than 2 words or 4 characters, since
61
+ * a 1-word ladder rung would highlight the first "the" on the page.
62
+ */
63
+ export function buildQueryLadder(value) {
64
+ const words = value.trim().split(/\s+/);
65
+ const ladder = [];
66
+ for (const n of [words.length, 6, 4, 3, 2]) {
67
+ if (n < 2 || n > words.length)
68
+ continue;
69
+ const q = words.slice(0, n).join(' ');
70
+ if (q.length >= 4 && !ladder.includes(q))
71
+ ladder.push(q);
72
+ }
73
+ return ladder.length ? ladder : [value.trim()];
74
+ }
75
+ /**
76
+ * Flatten a subtree's text into its normalized form plus, for each normalized
77
+ * character, the text node and offset it came from.
78
+ *
79
+ * The index map is what lets a match on the *normalized* string become a real
80
+ * `Range` over the *original* DOM — without it we could detect a hit but not
81
+ * highlight it.
82
+ */
83
+ function flatten(root) {
84
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
85
+ let text = '';
86
+ const map = [];
87
+ let pendingSpace = false;
88
+ for (let n = walker.nextNode(); n; n = walker.nextNode()) {
89
+ const node = n;
90
+ const raw = node.data;
91
+ for (let i = 0; i < raw.length; i++) {
92
+ const ch = raw[i];
93
+ if (/\s/.test(ch)) {
94
+ pendingSpace = text.length > 0;
95
+ continue;
96
+ }
97
+ if (pendingSpace) {
98
+ // The space belongs to this character's position, so a match starting
99
+ // here still points at a real node offset.
100
+ text += ' ';
101
+ map.push({ node, offset: i });
102
+ pendingSpace = false;
103
+ }
104
+ const folded = foldChar(ch);
105
+ // A ligature folds to several characters; each maps back to the same source.
106
+ for (const f of folded) {
107
+ text += f;
108
+ map.push({ node, offset: i });
109
+ }
110
+ }
111
+ }
112
+ return { text, map };
113
+ }
114
+ /**
115
+ * Find `quote` inside `root`'s rendered text and return a `Range` over it.
116
+ *
117
+ * Tries the whole phrase first, then the prefix ladder. Returns `null` when
118
+ * nothing matches — callers should degrade to "opened, not highlighted" rather
119
+ * than pretending.
120
+ */
121
+ export function findRange(root, quote) {
122
+ const needleRaw = quote.trim();
123
+ if (!needleRaw)
124
+ return null;
125
+ const { text, map } = flatten(root);
126
+ if (!text)
127
+ return null;
128
+ for (const candidate of buildQueryLadder(needleRaw)) {
129
+ const needle = normalizeForMatch(candidate);
130
+ if (needle.length < 2)
131
+ continue;
132
+ const at = text.indexOf(needle);
133
+ if (at === -1)
134
+ continue;
135
+ const start = map[at];
136
+ const end = map[at + needle.length - 1];
137
+ if (!start || !end)
138
+ continue;
139
+ const range = document.createRange();
140
+ range.setStart(start.node, start.offset);
141
+ // `end` is the last matched character — the range must close after it.
142
+ range.setEnd(end.node, Math.min(end.offset + 1, end.node.data.length));
143
+ return range;
144
+ }
145
+ return null;
146
+ }
147
+ //# sourceMappingURL=anchor-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-match.js","sourceRoot":"","sources":["../../../../src/components/shared/viewers/anchor-match.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Scroll to a cited passage and highlight it — for any viewer that renders its
3
+ * content into the DOM (text, markdown, json, docx, csv, xlsx).
4
+ *
5
+ * One hook serves all of them because, once rendered, those formats are just
6
+ * text in a subtree. Only PDF (canvas + its own text layer) and images need
7
+ * bespoke handling. So "support a new format" means *render it and stamp a few
8
+ * data attributes* — not write new anchoring logic.
9
+ *
10
+ * The resolution ladder is deliberately the same everywhere:
11
+ * locator (structural, exact) → quote (fuzzy text search) → nothing
12
+ * and "nothing" is a real outcome: the document still opens, just unhighlighted.
13
+ * Guessing a location would be worse than admitting we couldn't find it.
14
+ */
15
+ import { type RefObject } from 'react';
16
+ import type { Locator } from '@xyne/workflow-sdk/common';
17
+ export type { Locator } from '@xyne/workflow-sdk/common';
18
+ export interface Anchor {
19
+ /** The cited text. The portable anchor — works in any text-bearing renderer. */
20
+ quote?: string | undefined;
21
+ /** Exact structural address, when the source exposed one. */
22
+ locator?: Locator | undefined;
23
+ }
24
+ export interface UseDomAnchorResult {
25
+ /** Whether the anchor was located. `false` ⇒ the doc opened unhighlighted. */
26
+ hit: boolean;
27
+ }
28
+ /**
29
+ * The container must render its content as React children or be written
30
+ * imperatively (as docx-preview does). A container using
31
+ * `dangerouslySetInnerHTML` re-applies that HTML on re-render and would discard
32
+ * the overlay — a property of that API, not of this hook.
33
+ *
34
+ * @param containerRef the element wrapping the viewer's rendered content
35
+ * @param anchor what to locate; `undefined` ⇒ do nothing at all
36
+ * @param ready re-runs the search when this changes — pass whatever
37
+ * signals the content has painted (parsed rows, loaded text).
38
+ * Searching before paint finds nothing.
39
+ */
40
+ export declare function useDomAnchor(containerRef: RefObject<HTMLElement | null>, anchor: Anchor | undefined, ready?: unknown): UseDomAnchorResult;
41
+ //# sourceMappingURL=useDomAnchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDomAnchor.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/viewers/useDomAnchor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAKzD,YAAY,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD,MAAM,WAAW,MAAM;IACrB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AA8DD,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAC3C,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,CAAC,EAAE,OAAO,GACd,kBAAkB,CA+CpB"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Scroll to a cited passage and highlight it — for any viewer that renders its
3
+ * content into the DOM (text, markdown, json, docx, csv, xlsx).
4
+ *
5
+ * One hook serves all of them because, once rendered, those formats are just
6
+ * text in a subtree. Only PDF (canvas + its own text layer) and images need
7
+ * bespoke handling. So "support a new format" means *render it and stamp a few
8
+ * data attributes* — not write new anchoring logic.
9
+ *
10
+ * The resolution ladder is deliberately the same everywhere:
11
+ * locator (structural, exact) → quote (fuzzy text search) → nothing
12
+ * and "nothing" is a real outcome: the document still opens, just unhighlighted.
13
+ * Guessing a location would be worse than admitting we couldn't find it.
14
+ */
15
+ import { useEffect, useState } from 'react';
16
+ import { findRange } from './anchor-match.js';
17
+ const LAYER_ATTR = 'data-wui-anchor-layer';
18
+ /** The element a structural locator addresses, via attributes viewers stamp. */
19
+ function findByLocator(root, locator) {
20
+ switch (locator.at) {
21
+ case 'cell':
22
+ return root.querySelector(`[data-row="${String(locator.row)}"][data-col="${String(locator.col)}"]`);
23
+ case 'line':
24
+ return root.querySelector(`[data-line="${String(locator.from)}"]`);
25
+ case 'page':
26
+ // Paged rendering is pdf.js's own concern; DOM viewers have no pages.
27
+ return null;
28
+ }
29
+ }
30
+ function clearOverlay(container) {
31
+ container.querySelectorAll(`[${LAYER_ATTR}]`).forEach((n) => { n.remove(); });
32
+ }
33
+ /**
34
+ * Paint highlight rectangles over a range.
35
+ *
36
+ * An overlay rather than wrapping the match in `<mark>`: several viewers render
37
+ * content they own (docx-preview rebuilds its subtree, tables re-render), and
38
+ * mutating that DOM corrupts it and gets wiped on the next paint. Rectangles
39
+ * layered on top are non-destructive and behave identically everywhere.
40
+ */
41
+ function paintOverlay(container, rects) {
42
+ if (rects.length === 0)
43
+ return;
44
+ // The layer is positioned against the container's padding box, so the
45
+ // container must establish a containing block.
46
+ if (getComputedStyle(container).position === 'static') {
47
+ container.style.position = 'relative';
48
+ }
49
+ const base = container.getBoundingClientRect();
50
+ const layer = document.createElement('div');
51
+ layer.setAttribute(LAYER_ATTR, 'true');
52
+ layer.style.cssText = 'position:absolute;inset:0;pointer-events:none;z-index:5;';
53
+ for (const r of rects) {
54
+ if (r.width === 0 || r.height === 0)
55
+ continue;
56
+ const mark = document.createElement('div');
57
+ mark.style.cssText = [
58
+ 'position:absolute',
59
+ `left:${String(r.left - base.left + container.scrollLeft)}px`,
60
+ `top:${String(r.top - base.top + container.scrollTop)}px`,
61
+ `width:${String(r.width)}px`,
62
+ `height:${String(r.height)}px`,
63
+ 'background:color-mix(in srgb, var(--wui-primary) 26%, transparent)',
64
+ 'border-radius:2px',
65
+ 'mix-blend-mode:multiply',
66
+ ].join(';');
67
+ layer.appendChild(mark);
68
+ }
69
+ container.appendChild(layer);
70
+ }
71
+ /**
72
+ * The container must render its content as React children or be written
73
+ * imperatively (as docx-preview does). A container using
74
+ * `dangerouslySetInnerHTML` re-applies that HTML on re-render and would discard
75
+ * the overlay — a property of that API, not of this hook.
76
+ *
77
+ * @param containerRef the element wrapping the viewer's rendered content
78
+ * @param anchor what to locate; `undefined` ⇒ do nothing at all
79
+ * @param ready re-runs the search when this changes — pass whatever
80
+ * signals the content has painted (parsed rows, loaded text).
81
+ * Searching before paint finds nothing.
82
+ */
83
+ export function useDomAnchor(containerRef, anchor, ready) {
84
+ const [hit, setHit] = useState(false);
85
+ const quote = anchor?.quote;
86
+ const locator = anchor?.locator;
87
+ // Locators are small and flat; a stable string keeps the effect from re-running
88
+ // on every render just because the object identity changed.
89
+ const locatorKey = locator ? JSON.stringify(locator) : '';
90
+ useEffect(() => {
91
+ const container = containerRef.current;
92
+ if (!container)
93
+ return;
94
+ clearOverlay(container);
95
+ if (!quote && !locator) {
96
+ setHit(false);
97
+ return;
98
+ }
99
+ let target = null;
100
+ if (locator) {
101
+ const el = findByLocator(container, locator);
102
+ if (el)
103
+ target = { scrollTo: el, rects: [el.getBoundingClientRect()] };
104
+ }
105
+ if (!target && quote) {
106
+ const range = findRange(container, quote);
107
+ if (range) {
108
+ const rects = Array.from(range.getClientRects());
109
+ const first = range.startContainer.parentElement;
110
+ if (first)
111
+ target = { scrollTo: first, rects };
112
+ }
113
+ }
114
+ if (!target) {
115
+ setHit(false);
116
+ return;
117
+ }
118
+ paintOverlay(container, target.rects);
119
+ target.scrollTo.scrollIntoView({ block: 'center', inline: 'nearest' });
120
+ setHit(true);
121
+ return () => { clearOverlay(container); };
122
+ }, [containerRef, quote, locatorKey, ready]);
123
+ return { hit };
124
+ }
125
+ //# sourceMappingURL=useDomAnchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDomAnchor.js","sourceRoot":"","sources":["../../../../src/components/shared/viewers/useDomAnchor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { AiBuilderClient } from '@xyne/workflow-sdk/ai-builder';
2
+ export interface WorkflowSearch {
3
+ view?: 'tabs' | 'graph' | undefined;
4
+ }
5
+ export interface WorkflowAppProps {
6
+ /** Sub-path after the host's /workflows mount: '', 'executions', 'approvals',
7
+ * 'folder/<id>', 'w/<id>', 'runs/<id>'. */
8
+ path: string;
9
+ /** Query params (view state within a page — e.g. the run viewer's tab/node). */
10
+ search?: WorkflowSearch | undefined;
11
+ /** Push a new sub-path (+ optional query); the host wires this to its router so
12
+ * back/forward work. `replace` avoids a history entry for in-page view changes. */
13
+ onNavigate: (path: string, search?: WorkflowSearch, replace?: boolean) => void;
14
+ aiBuilderClient?: AiBuilderClient | undefined;
15
+ onToast?: (kind: 'success' | 'error', message: string) => void;
16
+ className?: string;
17
+ }
18
+ export declare function WorkflowApp({ path, search, onNavigate, aiBuilderClient, onToast, className, }: WorkflowAppProps): import("react").JSX.Element;
19
+ //# sourceMappingURL=WorkflowApp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowApp.d.ts","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowApp.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAOrE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B;gDAC4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;wFACoF;IACpF,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/E,eAAe,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,UAAU,EACV,eAAe,EACf,OAAO,EACP,SAAS,GACV,EAAE,gBAAgB,+BAyMlB"}
@@ -0,0 +1,121 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState, } from 'react';
3
+ import { ArrowLeft } from 'lucide-react';
4
+ import { useWorkflowClient } from '../../hooks/use-workflow-client.js';
5
+ import { WorkflowHome } from './WorkflowHome.js';
6
+ import {} from './WorkflowBrowser.js';
7
+ import { WorkflowDashboard } from '../dashboard/WorkflowDashboard.js';
8
+ import { ExecutionViewer } from '../execution/ExecutionViewer.js';
9
+ const parseRoute = (raw) => {
10
+ const clean = raw.replace(/^\/+|\/+$/g, '');
11
+ if (clean === '')
12
+ return { kind: 'home', tab: 'workflows' };
13
+ const [head, ...rest] = clean.split('/');
14
+ const arg = rest.join('/');
15
+ if (head === 'executions')
16
+ return { kind: 'home', tab: 'executions' };
17
+ if (head === 'approvals')
18
+ return { kind: 'home', tab: 'approvals', ...(arg ? { approvalId: arg } : {}) };
19
+ if (head === 'folder' && arg)
20
+ return { kind: 'home', tab: 'workflows', folderId: arg };
21
+ if (head === 'w' && arg) {
22
+ const [wfId, sub] = arg.split('/');
23
+ if (wfId)
24
+ return { kind: 'workflow', workflowId: wfId, view: sub === 'edit' ? 'builder' : 'runs' };
25
+ }
26
+ if (head === 'runs' && arg) {
27
+ const [execId, ...nodeParts] = arg.split('/');
28
+ const nodeId = nodeParts.join('/');
29
+ if (execId)
30
+ return { kind: 'run', executionId: execId, ...(nodeId ? { nodeId } : {}) };
31
+ }
32
+ return { kind: 'home', tab: 'workflows' };
33
+ };
34
+ const tabToPath = (tab) => (tab === 'workflows' ? '' : tab);
35
+ const folderToPath = (crumbs) => {
36
+ const leaf = crumbs[crumbs.length - 1];
37
+ return leaf ? `folder/${leaf.id}` : '';
38
+ };
39
+ const runToPath = (executionId, nodeId) => nodeId ? `runs/${executionId}/${nodeId}` : `runs/${executionId}`;
40
+ export function WorkflowApp({ path, search, onNavigate, aiBuilderClient, onToast, className, }) {
41
+ const client = useWorkflowClient();
42
+ const route = parseRoute(path);
43
+ // The URL carries only the leaf folder id; the full breadcrumb lives here and is
44
+ // reconciled with the id on back/forward/deep-link below.
45
+ const [folderCrumbs, setFolderCrumbs] = useState([]);
46
+ const [detail, setDetail] = useState(null);
47
+ const folderId = route.kind === 'home' ? route.folderId : undefined;
48
+ useEffect(() => {
49
+ setFolderCrumbs((prev) => {
50
+ if (!folderId)
51
+ return prev.length ? [] : prev;
52
+ if (prev[prev.length - 1]?.id === folderId)
53
+ return prev;
54
+ const idx = prev.findIndex((c) => c.id === folderId);
55
+ if (idx >= 0)
56
+ return prev.slice(0, idx + 1);
57
+ return [{ id: folderId, name: 'Folder' }];
58
+ });
59
+ }, [folderId]);
60
+ const workflowId = route.kind === 'workflow' ? route.workflowId : undefined;
61
+ const fetchSeq = useRef(0);
62
+ useEffect(() => {
63
+ if (!workflowId) {
64
+ setDetail(null);
65
+ return;
66
+ }
67
+ const seq = ++fetchSeq.current;
68
+ void (async () => {
69
+ const wf = await client.workflows.get(workflowId);
70
+ if (seq !== fetchSeq.current)
71
+ return;
72
+ const meta = wf.metadata
73
+ ? JSON.parse(wf.metadata)
74
+ : {};
75
+ const config = wf.config
76
+ ? JSON.parse(wf.config)
77
+ : undefined;
78
+ setDetail({
79
+ workflowId,
80
+ name: meta.name ?? workflowId,
81
+ config,
82
+ ...(wf.summary != null ? { summary: wf.summary } : {}),
83
+ ...(wf.permittedActions ? { permittedActions: wf.permittedActions } : {}),
84
+ });
85
+ })();
86
+ }, [workflowId, client]);
87
+ const goTab = useCallback((tab) => onNavigate(tabToPath(tab)), [onNavigate]);
88
+ const goFolder = useCallback((crumbs) => {
89
+ setFolderCrumbs(crumbs);
90
+ onNavigate(folderToPath(crumbs));
91
+ }, [onNavigate]);
92
+ const openWorkflow = useCallback((id, crumbs) => {
93
+ setFolderCrumbs(crumbs);
94
+ onNavigate(`w/${id}`);
95
+ }, [onNavigate]);
96
+ const openRun = useCallback((executionId) => onNavigate(`runs/${executionId}`), [onNavigate]);
97
+ const backToBrowser = useCallback(() => onNavigate(folderToPath(folderCrumbs)), [folderCrumbs, onNavigate]);
98
+ const goToCrumb = (index) => goFolder(index < 0 ? [] : folderCrumbs.slice(0, index + 1));
99
+ const handleSave = useCallback(async (config, summary) => {
100
+ if (!detail)
101
+ return;
102
+ await client.workflows.update(detail.workflowId, { config });
103
+ setDetail((prev) => prev ? { ...prev, config, ...(summary != null ? { summary } : {}) } : prev);
104
+ }, [client, detail]);
105
+ let detailView = null;
106
+ if (route.kind === 'run') {
107
+ detailView = (_jsx(ExecutionViewer, { executionId: route.executionId, selectedStepId: route.nodeId ?? null, viewMode: search?.view ?? 'tabs', onViewModeChange: (m) => onNavigate(runToPath(route.executionId, route.nodeId), { view: m === 'graph' ? 'graph' : undefined }, true), onSelectStep: (node, replace) => onNavigate(runToPath(route.executionId, node ?? undefined), { view: search?.view }, replace ?? false), onBack: () => {
108
+ if (typeof window !== 'undefined')
109
+ window.history.back();
110
+ }, onRerunSuccess: (newId) => openRun(newId) }));
111
+ }
112
+ else if (route.kind === 'workflow') {
113
+ detailView =
114
+ detail?.workflowId === route.workflowId ? (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 border-b border-[var(--wui-border)] bg-[var(--wui-bg)] px-5 py-2.5", children: [_jsx("button", { type: "button", "aria-label": "Back", onClick: backToBrowser, className: "grid h-7 w-7 place-items-center rounded-md text-[var(--wui-fg-muted)] transition-colors hover:bg-[color-mix(in_srgb,var(--wui-fg)_6%,transparent)] hover:text-[var(--wui-fg)]", children: _jsx(ArrowLeft, { className: "h-3.5 w-3.5", strokeWidth: 1.75 }) }), _jsxs("nav", { className: "flex min-w-0 items-center gap-1 text-[13px] text-[var(--wui-fg-muted)]", children: [_jsx("button", { type: "button", onClick: () => goToCrumb(-1), className: "rounded-md px-1.5 py-0.5 transition-colors hover:bg-[color-mix(in_srgb,var(--wui-fg)_6%,transparent)] hover:text-[var(--wui-fg)]", children: "Workflows" }), folderCrumbs.map((seg, i) => (_jsxs("span", { className: "flex min-w-0 items-center gap-1", children: [_jsx("span", { className: "select-none text-[var(--wui-fg-muted)]/60", children: "\u203A" }), _jsx("button", { type: "button", onClick: () => goToCrumb(i), className: "max-w-[24ch] truncate rounded-md px-1.5 py-0.5 transition-colors hover:bg-[color-mix(in_srgb,var(--wui-fg)_6%,transparent)] hover:text-[var(--wui-fg)]", title: seg.name, children: seg.name })] }, seg.id))), _jsxs("span", { className: "flex min-w-0 items-center gap-1", children: [_jsx("span", { className: "select-none text-[var(--wui-fg-muted)]/60", children: "\u203A" }), _jsx("span", { className: "max-w-[32ch] truncate rounded-md px-1.5 py-0.5 font-medium text-[var(--wui-fg)]", title: detail.name, children: detail.name })] })] })] }), _jsx("div", { className: "flex-1 overflow-hidden", children: _jsx(WorkflowDashboard, { view: route.view, onViewChange: (v) => onNavigate(v === 'builder' ? `w/${route.workflowId}/edit` : `w/${route.workflowId}`), onViewRun: openRun, workflowId: detail.workflowId, workflowConfig: detail.config, summary: detail.summary, onSave: handleSave, ...(aiBuilderClient ? { aiBuilderClient } : {}), ...(detail.permittedActions
115
+ ? { permittedActions: detail.permittedActions }
116
+ : {}) }) })] })) : (_jsx("div", { className: "flex h-full items-center justify-center text-[13px] text-[var(--wui-fg-muted)]", children: "Loading\u2026" }));
117
+ }
118
+ const tab = route.kind === 'home' ? route.tab : 'workflows';
119
+ return (_jsx(WorkflowHome, { ...(className ? { className } : {}), tab: tab, onTabChange: goTab, path: folderCrumbs, onPathChange: goFolder, onSelectWorkflow: openWorkflow, onViewRun: (id) => openRun(id), approvalId: route.kind === 'home' && route.tab === 'approvals' ? (route.approvalId ?? null) : null, onApprovalSelect: (id) => onNavigate(id ? `approvals/${id}` : 'approvals'), ...(onToast ? { onToast } : {}), ...(detailView ? { detailView } : {}) }));
120
+ }
121
+ //# sourceMappingURL=WorkflowApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowApp.js","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowApp.tsx"],"names":[],"mappings":"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"}
@@ -7,9 +7,15 @@ export interface WorkflowHomeProps {
7
7
  onPathChange: (path: FolderCrumb[]) => void;
8
8
  onSelectWorkflow: (workflowId: string, path: FolderCrumb[]) => void;
9
9
  onViewRun: (executionId: string, workflowName: string) => void;
10
+ /** Controlled approval selection (for URL sync) — threaded to the Approvals tab. */
11
+ approvalId?: string | null | undefined;
12
+ onApprovalSelect?: ((id: string | null) => void) | undefined;
10
13
  onToast?: (kind: 'success' | 'error', message: string) => void;
11
- /** Which tab opens first. */
14
+ /** Which tab opens first (uncontrolled). */
12
15
  defaultTab?: WorkflowHomeTab;
16
+ /** Controlled active tab; with onTabChange the parent (router) owns it. */
17
+ tab?: WorkflowHomeTab;
18
+ onTabChange?: (tab: WorkflowHomeTab) => void;
13
19
  /** When provided, fills the content area (below the tab bar) instead of the active tab. */
14
20
  detailView?: ReactNode | undefined;
15
21
  /** Called when a tab is clicked while a detailView is open, so the host can close it. */
@@ -23,5 +29,5 @@ export interface WorkflowHomeProps {
23
29
  * pending-approval count surfaces as a badge on the Approvals tab rather
24
30
  * than an in-list banner.
25
31
  */
26
- export declare function WorkflowHome({ path, onPathChange, onSelectWorkflow, onViewRun, onToast, defaultTab, detailView, onLeaveDetail, className, }: WorkflowHomeProps): import("react").JSX.Element;
32
+ export declare function WorkflowHome({ path, onPathChange, onSelectWorkflow, onViewRun, approvalId, onApprovalSelect, onToast, defaultTab, tab: controlledTab, onTabChange, detailView, onLeaveDetail, className, }: WorkflowHomeProps): import("react").JSX.Element;
27
33
  //# sourceMappingURL=WorkflowHome.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkflowHome.d.ts","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowHome.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzE,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC5C,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,6BAA6B;IAC7B,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACnC,yFAAyF;IACzF,aAAa,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,OAAO,EACP,UAAwB,EACxB,UAAU,EACV,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BA4EnB"}
1
+ {"version":3,"file":"WorkflowHome.d.ts","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowHome.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzE,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC5C,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,4CAA4C;IAC5C,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,2EAA2E;IAC3E,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,2FAA2F;IAC3F,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACnC,yFAAyF;IACzF,aAAa,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,UAAwB,EACxB,GAAG,EAAE,aAAa,EAClB,WAAW,EACX,UAAU,EACV,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BAoFnB"}