dishui 0.0.64 → 0.0.65

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 (177) hide show
  1. package/dist/components/Badge/index.js +12 -9
  2. package/dist/components/Badge/index.js.map +1 -1
  3. package/dist/components/Button/index.js +43 -40
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/Card/index.d.ts +11 -0
  6. package/dist/components/Card/index.js +62 -37
  7. package/dist/components/Card/index.js.map +1 -1
  8. package/dist/components/Chart/Chart.js.map +1 -1
  9. package/dist/components/Checkbox/index.js +32 -30
  10. package/dist/components/Checkbox/index.js.map +1 -1
  11. package/dist/components/Demo/index.js.map +1 -1
  12. package/dist/components/EmptyState/index.d.ts +4 -1
  13. package/dist/components/EmptyState/index.js +3 -3
  14. package/dist/components/EmptyState/index.js.map +1 -1
  15. package/dist/components/FileUploader/DropZone.js.map +1 -1
  16. package/dist/components/FileUploader/FileItem.js.map +1 -1
  17. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  18. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  19. package/dist/components/Input/index.js +30 -30
  20. package/dist/components/Input/index.js.map +1 -1
  21. package/dist/components/Label/index.js +41 -40
  22. package/dist/components/Label/index.js.map +1 -1
  23. package/dist/components/List/index.js +47 -32
  24. package/dist/components/List/index.js.map +1 -1
  25. package/dist/components/Markdown/Markdown.js +61 -57
  26. package/dist/components/Markdown/Markdown.js.map +1 -1
  27. package/dist/components/Markdown/markdownComponents.js +49 -49
  28. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  29. package/dist/components/Modal/index.d.ts +7 -3
  30. package/dist/components/Modal/index.js +77 -65
  31. package/dist/components/Modal/index.js.map +1 -1
  32. package/dist/components/Page/index.d.ts +58 -0
  33. package/dist/components/Page/index.js +74 -0
  34. package/dist/components/Page/index.js.map +1 -0
  35. package/dist/components/PageHeader/index.js.map +1 -1
  36. package/dist/components/Select/index.js +0 -3
  37. package/dist/components/Select/index.js.map +1 -1
  38. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  39. package/dist/components/StatCard/index.d.ts +3 -1
  40. package/dist/components/StatCard/index.js +39 -11
  41. package/dist/components/StatCard/index.js.map +1 -1
  42. package/dist/components/Table/index.js +103 -85
  43. package/dist/components/Table/index.js.map +1 -1
  44. package/dist/components/Tabs/index.d.ts +19 -5
  45. package/dist/components/Tabs/index.js +32 -13
  46. package/dist/components/Tabs/index.js.map +1 -1
  47. package/dist/components/Tree/Tree.js.map +1 -1
  48. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  49. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  50. package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
  51. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  52. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
  53. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  54. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  55. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  56. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  57. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  58. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  59. package/dist/components/pro/CodeEditor/themes.js +59 -59
  60. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  61. package/dist/components/pro/DataTable/DataTable.js +49 -48
  62. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  63. package/dist/components/pro/DataTable/Filters.js +42 -42
  64. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  65. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  66. package/dist/components/pro/DataTable/PivotView.js +35 -32
  67. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  68. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  69. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  70. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  71. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  72. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  73. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  74. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  75. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  76. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  77. package/dist/components/pro/DataTable/tanstack-table.js +37 -37
  78. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  79. package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
  80. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  81. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  82. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  83. package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
  84. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  85. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  86. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  87. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  88. package/dist/components/pro/Flow/Flow.js +496 -494
  89. package/dist/components/pro/Flow/Flow.js.map +1 -1
  90. package/dist/components/pro/Flow/FlowCanvas.js +916 -917
  91. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  92. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  93. package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
  94. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  95. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  96. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  97. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  98. package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
  99. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  100. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  101. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  102. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  103. package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
  104. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  105. package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
  106. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  107. package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
  108. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  109. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  110. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  111. package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
  112. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  113. package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
  114. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  115. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  116. package/dist/components/pro/Flow/nodes/shapes.js +1 -3
  117. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  118. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  119. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  120. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  121. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  122. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  123. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  124. package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
  125. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  126. package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
  127. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  128. package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
  129. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  130. package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
  131. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  132. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  133. package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
  134. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  135. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  136. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  137. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  138. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  139. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  140. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  141. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  142. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  143. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  144. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  145. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  146. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  147. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  148. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  149. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  150. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  151. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  152. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  153. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  154. package/dist/contexts/AppContext.js.map +1 -1
  155. package/dist/dishui.css +1 -1
  156. package/dist/hooks/useTableColumns.js +7 -8
  157. package/dist/hooks/useTableColumns.js.map +1 -1
  158. package/dist/index.d.ts +2 -0
  159. package/dist/index.js +227 -221
  160. package/dist/layouts/MainLayout.js +22 -22
  161. package/dist/layouts/MainLayout.js.map +1 -1
  162. package/dist/layouts/Navbar.js.map +1 -1
  163. package/dist/layouts/Sidebar.js +94 -73
  164. package/dist/layouts/Sidebar.js.map +1 -1
  165. package/dist/layouts/headbar/Headbar.js.map +1 -1
  166. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  167. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  168. package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
  169. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  170. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  171. package/dist/utils/i18n.js +10 -10
  172. package/dist/utils/i18n.js.map +1 -1
  173. package/dist/utils/menu.js.map +1 -1
  174. package/dist/utils/routerBuilder.js +17 -15
  175. package/dist/utils/routerBuilder.js.map +1 -1
  176. package/dist/utils/themes.js.map +1 -1
  177. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"dataUtils.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/dataUtils.ts"],"sourcesContent":["// Data-node helpers: CSV/XLSX parsing, column type inference, and building\n// TanStack Charts definitions from parsed rows. Kept dependency-light so the\n// base `dishui/flow` bundle stays small — `fflate` (already a transitive dep of\n// markmap) is the only heavy import and only loads when an .xlsx is opened.\n\nimport type {\n FlowDataColumn,\n FlowDataColumnType,\n FlowDataConfig,\n FlowDataChartConfig,\n} from '../types';\n\n/** Result of parsing a raw table into columns + row records. */\nexport interface ParsedTable {\n columns: FlowDataColumn[];\n rows: Array<Record<string, unknown>>;\n}\n\n// ── CSV parsing ────────────────────────────────────────────────────────────\n\n/**\n * Parse CSV text into a matrix of string cells. Handles quoted fields,\n * escaped quotes (\"\"), and embedded newlines/commas. Auto-detects `,` or `;`\n * as the delimiter from the first non-empty line.\n */\nexport function parseCsv(text: string): string[][] {\n const src = text.replace(/^\\uFEFF/, ''); // strip BOM\n const delimiter = detectDelimiter(src);\n const rows: string[][] = [];\n let field = '';\n let row: string[] = [];\n let inQuotes = false;\n\n for (let i = 0; i < src.length; i++) {\n const ch = src[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (src[i + 1] === '\"') {\n field += '\"';\n i++;\n } else {\n inQuotes = false;\n }\n } else {\n field += ch;\n }\n continue;\n }\n if (ch === '\"') {\n inQuotes = true;\n } else if (ch === delimiter) {\n row.push(field);\n field = '';\n } else if (ch === '\\n') {\n row.push(field);\n rows.push(row);\n field = '';\n row = [];\n } else if (ch === '\\r') {\n // ignore; handled by the following \\n (or end of input)\n } else {\n field += ch;\n }\n }\n // flush trailing field/row\n if (field.length > 0 || row.length > 0) {\n row.push(field);\n rows.push(row);\n }\n // drop fully-empty trailing rows\n return rows.filter((r) => !(r.length === 1 && r[0].trim() === ''));\n}\n\nfunction detectDelimiter(src: string): string {\n const firstLine = src.split(/\\r?\\n/, 1)[0] ?? '';\n const commas = (firstLine.match(/,/g) ?? []).length;\n const semis = (firstLine.match(/;/g) ?? []).length;\n const tabs = (firstLine.match(/\\t/g) ?? []).length;\n if (tabs > commas && tabs > semis) return '\\t';\n if (semis > commas) return ';';\n return ',';\n}\n\n/** Serialize columns + rows back to CSV text (for round-tripping/exports). */\nexport function toCsv(columns: FlowDataColumn[], rows: Array<Record<string, unknown>>): string {\n const esc = (v: unknown) => {\n const s = v == null ? '' : String(v);\n return /[\",\\n\\r]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n const header = columns.map((c) => esc(c.label ?? c.key)).join(',');\n const body = rows\n .map((r) => columns.map((c) => esc(r[c.key])).join(','))\n .join('\\n');\n return body ? `${header}\\n${body}` : header;\n}\n\n// ── XLSX parsing ─────────────────────────────────────────────────────────────\n\n/**\n * Parse the first worksheet of an XLSX workbook (an OOXML zip) into a string\n * matrix. Uses `fflate` to unzip and DOMParser to read the sheet XML + shared\n * strings. Loaded dynamically so it never enters the base bundle.\n */\nexport async function parseXlsx(buffer: ArrayBuffer): Promise<string[][]> {\n const { unzipSync, strFromU8 } = await import('fflate');\n const files = unzipSync(new Uint8Array(buffer));\n\n const parser = new DOMParser();\n const readXml = (path: string): Document | null => {\n const entry = files[path];\n if (!entry) return null;\n return parser.parseFromString(strFromU8(entry), 'application/xml');\n };\n\n // Shared strings table (cells of type \"s\" reference these by index).\n const sharedStrings: string[] = [];\n const sst = readXml('xl/sharedStrings.xml');\n if (sst) {\n for (const si of Array.from(sst.getElementsByTagName('si'))) {\n // Concatenate all <t> runs within the string item.\n const ts = Array.from(si.getElementsByTagName('t'));\n sharedStrings.push(ts.map((t) => t.textContent ?? '').join(''));\n }\n }\n\n // Resolve the first sheet's target from the workbook relationships.\n const sheetPath = resolveFirstSheetPath(files, readXml);\n const sheetDoc = readXml(sheetPath);\n if (!sheetDoc) throw new Error('无法读取 Excel 工作表');\n\n const rowsEls = Array.from(sheetDoc.getElementsByTagName('row'));\n const matrix: string[][] = [];\n for (const rowEl of rowsEls) {\n const cells = Array.from(rowEl.getElementsByTagName('c'));\n const rowArr: string[] = [];\n for (const c of cells) {\n const ref = c.getAttribute('r') ?? '';\n const colIdx = columnRefToIndex(ref);\n const type = c.getAttribute('t');\n let value = '';\n if (type === 's') {\n const idx = Number(c.getElementsByTagName('v')[0]?.textContent ?? '');\n value = Number.isFinite(idx) ? sharedStrings[idx] ?? '' : '';\n } else if (type === 'inlineStr') {\n value = c.getElementsByTagName('t')[0]?.textContent ?? '';\n } else {\n value = c.getElementsByTagName('v')[0]?.textContent ?? '';\n }\n if (colIdx >= 0) rowArr[colIdx] = value;\n }\n // normalize holes to empty strings\n for (let i = 0; i < rowArr.length; i++) if (rowArr[i] == null) rowArr[i] = '';\n matrix.push(rowArr);\n }\n return matrix.filter((r) => r.some((cell) => cell.trim() !== ''));\n}\n\nfunction resolveFirstSheetPath(\n files: Record<string, Uint8Array>,\n readXml: (path: string) => Document | null,\n): string {\n // Prefer following workbook.xml → rels; fall back to the conventional path.\n const workbook = readXml('xl/workbook.xml');\n const rels = readXml('xl/_rels/workbook.xml.rels');\n if (workbook && rels) {\n const sheet = workbook.getElementsByTagName('sheet')[0];\n const rid = sheet?.getAttribute('r:id') ?? sheet?.getAttributeNS(\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n 'id',\n );\n if (rid) {\n for (const rel of Array.from(rels.getElementsByTagName('Relationship'))) {\n if (rel.getAttribute('Id') === rid) {\n const target = rel.getAttribute('Target') ?? '';\n const norm = target.replace(/^\\//, '').replace(/^xl\\//, '');\n return `xl/${norm}`;\n }\n }\n }\n }\n if (files['xl/worksheets/sheet1.xml']) return 'xl/worksheets/sheet1.xml';\n // last resort: first worksheet entry found\n const first = Object.keys(files).find((p) => /^xl\\/worksheets\\/.*\\.xml$/.test(p));\n return first ?? 'xl/worksheets/sheet1.xml';\n}\n\n/** Convert an A1-style cell ref (e.g. \"C5\") to a zero-based column index. */\nfunction columnRefToIndex(ref: string): number {\n const letters = ref.match(/^[A-Z]+/i)?.[0];\n if (!letters) return -1;\n let idx = 0;\n for (const ch of letters.toUpperCase()) {\n idx = idx * 26 + (ch.charCodeAt(0) - 64);\n }\n return idx - 1;\n}\n\n// ── Matrix → table (columns + typed rows) ────────────────────────────────────\n\n/** Slugify a header label into a safe object key, deduping collisions. */\nfunction toKey(label: string, used: Set<string>): string {\n let base = label.trim().replace(/\\s+/g, '_').replace(/[^\\w\\u4e00-\\u9fa5]/g, '');\n if (!base) base = 'col';\n let key = base;\n let n = 1;\n while (used.has(key)) key = `${base}_${n++}`;\n used.add(key);\n return key;\n}\n\nconst DATE_RE = /^\\d{4}[-/]\\d{1,2}[-/]\\d{1,2}([ T]\\d{1,2}:\\d{2}(:\\d{2})?)?$/;\n\n/** Infer a column type from a sample of raw string cell values. */\nexport function inferColumnType(samples: string[]): FlowDataColumnType {\n const nonEmpty = samples.map((s) => s?.trim()).filter((s) => s);\n if (nonEmpty.length === 0) return 'string';\n const isBool = nonEmpty.every((s) => /^(true|false|yes|no|是|否)$/i.test(s));\n if (isBool) return 'boolean';\n const isNum = nonEmpty.every((s) => /^-?\\d+(\\.\\d+)?%?$/.test(s.replace(/,/g, '')));\n if (isNum) return 'number';\n const isDate = nonEmpty.every((s) => DATE_RE.test(s));\n if (isDate) return 'date';\n return 'string';\n}\n\n/** Coerce a raw string cell to a typed value based on the column type. */\nexport function coerceValue(raw: string, type: FlowDataColumnType): unknown {\n const s = (raw ?? '').trim();\n if (s === '') return type === 'number' ? null : '';\n switch (type) {\n case 'number': {\n const cleaned = s.replace(/,/g, '').replace(/%$/, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n case 'boolean':\n return /^(true|yes|是)$/i.test(s);\n case 'date':\n case 'string':\n default:\n return s;\n }\n}\n\n/**\n * Build a typed table from a raw string matrix. The first row is treated as the\n * header. Column types are inferred from the data rows.\n */\nexport function matrixToTable(matrix: string[][]): ParsedTable {\n if (matrix.length === 0) return { columns: [], rows: [] };\n const [header, ...dataRows] = matrix;\n const used = new Set<string>();\n const colCount = Math.max(header.length, ...dataRows.map((r) => r.length), 0);\n\n const columns: FlowDataColumn[] = [];\n for (let c = 0; c < colCount; c++) {\n const label = (header[c] ?? `列${c + 1}`).trim() || `列${c + 1}`;\n const samples = dataRows.slice(0, 50).map((r) => r[c] ?? '');\n columns.push({ key: toKey(label, used), label, type: inferColumnType(samples) });\n }\n\n const rows = dataRows.map((r) => {\n const record: Record<string, unknown> = {};\n columns.forEach((col, c) => {\n record[col.key] = coerceValue(r[c] ?? '', col.type);\n });\n return record;\n });\n\n return { columns, rows };\n}\n\n/** Parse a File (csv or xlsx) into a typed table. */\nexport async function parseDataFile(file: File): Promise<ParsedTable> {\n const name = file.name.toLowerCase();\n if (name.endsWith('.xlsx') || name.endsWith('.xlsm')) {\n const buffer = await file.arrayBuffer();\n return matrixToTable(await parseXlsx(buffer));\n }\n // treat everything else as delimited text (csv/tsv/txt)\n const text = await file.text();\n return matrixToTable(parseCsv(text));\n}\n\n// ── Config helpers ───────────────────────────────────────────────────────────\n\n/** Default palette for chart series, mirroring the demo examples. */\nexport const DATA_CHART_PALETTE = [\n '#6366f1', '#10b981', '#f59e0b', '#f43f5e', '#06b6d4',\n '#8b5cf6', '#84cc16', '#ec4899', '#0ea5e9', '#f97316',\n];\n\n/** Column key → display label lookup. */\nexport function labelFor(columns: FlowDataColumn[], key: string): string {\n return columns.find((c) => c.key === key)?.label ?? key;\n}\n\n/** First non-numeric column key (a sensible default X/category field). */\nexport function firstDimension(columns: FlowDataColumn[]): string | undefined {\n return (columns.find((c) => c.type !== 'number') ?? columns[0])?.key;\n}\n\n/** All numeric column keys (candidate measures/series). */\nexport function numericFields(columns: FlowDataColumn[]): string[] {\n return columns.filter((c) => c.type === 'number').map((c) => c.key);\n}\n\n/**\n * Produce a sensible default `FlowDataConfig` for a freshly parsed table:\n * table view, first numeric field charted against the first dimension.\n */\nexport function makeDefaultDataConfig(\n parsed: ParsedTable,\n sourceName?: string,\n): FlowDataConfig {\n const x = firstDimension(parsed.columns);\n const nums = numericFields(parsed.columns);\n return {\n columns: parsed.columns,\n rows: parsed.rows,\n view: 'table',\n sourceName,\n chart: {\n type: 'bar',\n xField: x,\n yFields: nums.slice(0, 1),\n },\n pivot: {\n enabled: false,\n rowFields: x ? [x] : [],\n colFields: [],\n values: nums[0] ? [{ field: nums[0], aggFn: 'sum' }] : [],\n },\n };\n}\n\n/**\n * Re-parse CSV text into an existing config, preserving column keys and types\n * for headers that match an existing column (by label or key). New headers get\n * fresh inferred columns; chart/pivot references to removed fields are pruned.\n */\nexport function applyCsvText(config: FlowDataConfig, text: string): FlowDataConfig {\n const matrix = parseCsv(text);\n if (matrix.length === 0) {\n return { ...config, columns: [], rows: [], chart: { type: 'bar' }, pivot: { enabled: false, rowFields: [], colFields: [], values: [] } };\n }\n const [header, ...dataRows] = matrix;\n const colCount = Math.max(header.length, ...dataRows.map((r) => r.length), 0);\n const used = new Set<string>();\n const byLabel = new Map(config.columns.map((c) => [c.label ?? c.key, c]));\n const byKey = new Map(config.columns.map((c) => [c.key, c]));\n\n const columns: FlowDataColumn[] = [];\n for (let c = 0; c < colCount; c++) {\n const label = (header[c] ?? `列${c + 1}`).trim() || `列${c + 1}`;\n const existing = byLabel.get(label) ?? byKey.get(label);\n if (existing) {\n used.add(existing.key);\n columns.push({ ...existing, label });\n } else {\n const samples = dataRows.slice(0, 50).map((r) => r[c] ?? '');\n columns.push({ key: toKey(label, used), label, type: inferColumnType(samples) });\n }\n }\n\n const rows = dataRows.map((r) => {\n const record: Record<string, unknown> = {};\n columns.forEach((col, c) => {\n record[col.key] = coerceValue(r[c] ?? '', col.type);\n });\n return record;\n });\n\n const keys = new Set(columns.map((c) => c.key));\n\n const chart = config.chart\n ? {\n ...config.chart,\n xField: config.chart.xField && keys.has(config.chart.xField)\n ? config.chart.xField\n : firstDimension(columns),\n yFields: (config.chart.yFields ?? []).filter((f) => keys.has(f)),\n seriesColors: config.chart.seriesColors\n ? Object.fromEntries(Object.entries(config.chart.seriesColors).filter(([f]) => keys.has(f)))\n : undefined,\n }\n : config.chart;\n\n const pivot = config.pivot\n ? {\n ...config.pivot,\n rowFields: config.pivot.rowFields.filter((f) => keys.has(f)),\n colFields: config.pivot.colFields.filter((f) => keys.has(f)),\n values: config.pivot.values.filter((v) => keys.has(v.field)),\n }\n : config.pivot;\n\n return { ...config, columns, rows, chart, pivot };\n}\n\n/** A small starter table used when creating an empty Data node from the palette. */\nexport function makeStarterDataConfig(): FlowDataConfig {\n const columns: FlowDataColumn[] = [\n { key: 'category', label: '类别', type: 'string' },\n { key: 'value', label: '数值', type: 'number' },\n ];\n const rows = [\n { category: 'A', value: 30 },\n { category: 'B', value: 45 },\n { category: 'C', value: 28 },\n ];\n return makeDefaultDataConfig({ columns, rows });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dataUtils.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/dataUtils.ts"],"sourcesContent":["// Data-node helpers: CSV/XLSX parsing, column type inference, and building\n// TanStack Charts definitions from parsed rows. Kept dependency-light so the\n// base `dishui/flow` bundle stays small — `fflate` (already a transitive dep of\n// markmap) is the only heavy import and only loads when an .xlsx is opened.\n\nimport type {\n FlowDataColumn,\n FlowDataColumnType,\n FlowDataConfig,\n FlowDataChartConfig,\n} from '../types';\n\n/** Result of parsing a raw table into columns + row records. */\nexport interface ParsedTable {\n columns: FlowDataColumn[];\n rows: Array<Record<string, unknown>>;\n}\n\n// ── CSV parsing ────────────────────────────────────────────────────────────\n\n/**\n * Parse CSV text into a matrix of string cells. Handles quoted fields,\n * escaped quotes (\"\"), and embedded newlines/commas. Auto-detects `,` or `;`\n * as the delimiter from the first non-empty line.\n */\nexport function parseCsv(text: string): string[][] {\n const src = text.replace(/^\\uFEFF/, ''); // strip BOM\n const delimiter = detectDelimiter(src);\n const rows: string[][] = [];\n let field = '';\n let row: string[] = [];\n let inQuotes = false;\n\n for (let i = 0; i < src.length; i++) {\n const ch = src[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (src[i + 1] === '\"') {\n field += '\"';\n i++;\n } else {\n inQuotes = false;\n }\n } else {\n field += ch;\n }\n continue;\n }\n if (ch === '\"') {\n inQuotes = true;\n } else if (ch === delimiter) {\n row.push(field);\n field = '';\n } else if (ch === '\\n') {\n row.push(field);\n rows.push(row);\n field = '';\n row = [];\n } else if (ch === '\\r') {\n // ignore; handled by the following \\n (or end of input)\n } else {\n field += ch;\n }\n }\n // flush trailing field/row\n if (field.length > 0 || row.length > 0) {\n row.push(field);\n rows.push(row);\n }\n // drop fully-empty trailing rows\n return rows.filter((r) => !(r.length === 1 && r[0].trim() === ''));\n}\n\nfunction detectDelimiter(src: string): string {\n const firstLine = src.split(/\\r?\\n/, 1)[0] ?? '';\n const commas = (firstLine.match(/,/g) ?? []).length;\n const semis = (firstLine.match(/;/g) ?? []).length;\n const tabs = (firstLine.match(/\\t/g) ?? []).length;\n if (tabs > commas && tabs > semis) return '\\t';\n if (semis > commas) return ';';\n return ',';\n}\n\n/** Serialize columns + rows back to CSV text (for round-tripping/exports). */\nexport function toCsv(columns: FlowDataColumn[], rows: Array<Record<string, unknown>>): string {\n const esc = (v: unknown) => {\n const s = v == null ? '' : String(v);\n return /[\",\\n\\r]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n const header = columns.map((c) => esc(c.label ?? c.key)).join(',');\n const body = rows\n .map((r) => columns.map((c) => esc(r[c.key])).join(','))\n .join('\\n');\n return body ? `${header}\\n${body}` : header;\n}\n\n// ── XLSX parsing ─────────────────────────────────────────────────────────────\n\n/**\n * Parse the first worksheet of an XLSX workbook (an OOXML zip) into a string\n * matrix. Uses `fflate` to unzip and DOMParser to read the sheet XML + shared\n * strings. Loaded dynamically so it never enters the base bundle.\n */\nexport async function parseXlsx(buffer: ArrayBuffer): Promise<string[][]> {\n const { unzipSync, strFromU8 } = await import('fflate');\n const files = unzipSync(new Uint8Array(buffer));\n\n const parser = new DOMParser();\n const readXml = (path: string): Document | null => {\n const entry = files[path];\n if (!entry) return null;\n return parser.parseFromString(strFromU8(entry), 'application/xml');\n };\n\n // Shared strings table (cells of type \"s\" reference these by index).\n const sharedStrings: string[] = [];\n const sst = readXml('xl/sharedStrings.xml');\n if (sst) {\n for (const si of Array.from(sst.getElementsByTagName('si'))) {\n // Concatenate all <t> runs within the string item.\n const ts = Array.from(si.getElementsByTagName('t'));\n sharedStrings.push(ts.map((t) => t.textContent ?? '').join(''));\n }\n }\n\n // Resolve the first sheet's target from the workbook relationships.\n const sheetPath = resolveFirstSheetPath(files, readXml);\n const sheetDoc = readXml(sheetPath);\n if (!sheetDoc) throw new Error('无法读取 Excel 工作表');\n\n const rowsEls = Array.from(sheetDoc.getElementsByTagName('row'));\n const matrix: string[][] = [];\n for (const rowEl of rowsEls) {\n const cells = Array.from(rowEl.getElementsByTagName('c'));\n const rowArr: string[] = [];\n for (const c of cells) {\n const ref = c.getAttribute('r') ?? '';\n const colIdx = columnRefToIndex(ref);\n const type = c.getAttribute('t');\n let value = '';\n if (type === 's') {\n const idx = Number(c.getElementsByTagName('v')[0]?.textContent ?? '');\n value = Number.isFinite(idx) ? sharedStrings[idx] ?? '' : '';\n } else if (type === 'inlineStr') {\n value = c.getElementsByTagName('t')[0]?.textContent ?? '';\n } else {\n value = c.getElementsByTagName('v')[0]?.textContent ?? '';\n }\n if (colIdx >= 0) rowArr[colIdx] = value;\n }\n // normalize holes to empty strings\n for (let i = 0; i < rowArr.length; i++) if (rowArr[i] == null) rowArr[i] = '';\n matrix.push(rowArr);\n }\n return matrix.filter((r) => r.some((cell) => cell.trim() !== ''));\n}\n\nfunction resolveFirstSheetPath(\n files: Record<string, Uint8Array>,\n readXml: (path: string) => Document | null,\n): string {\n // Prefer following workbook.xml → rels; fall back to the conventional path.\n const workbook = readXml('xl/workbook.xml');\n const rels = readXml('xl/_rels/workbook.xml.rels');\n if (workbook && rels) {\n const sheet = workbook.getElementsByTagName('sheet')[0];\n const rid = sheet?.getAttribute('r:id') ?? sheet?.getAttributeNS(\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',\n 'id',\n );\n if (rid) {\n for (const rel of Array.from(rels.getElementsByTagName('Relationship'))) {\n if (rel.getAttribute('Id') === rid) {\n const target = rel.getAttribute('Target') ?? '';\n const norm = target.replace(/^\\//, '').replace(/^xl\\//, '');\n return `xl/${norm}`;\n }\n }\n }\n }\n if (files['xl/worksheets/sheet1.xml']) return 'xl/worksheets/sheet1.xml';\n // last resort: first worksheet entry found\n const first = Object.keys(files).find((p) => /^xl\\/worksheets\\/.*\\.xml$/.test(p));\n return first ?? 'xl/worksheets/sheet1.xml';\n}\n\n/** Convert an A1-style cell ref (e.g. \"C5\") to a zero-based column index. */\nfunction columnRefToIndex(ref: string): number {\n const letters = ref.match(/^[A-Z]+/i)?.[0];\n if (!letters) return -1;\n let idx = 0;\n for (const ch of letters.toUpperCase()) {\n idx = idx * 26 + (ch.charCodeAt(0) - 64);\n }\n return idx - 1;\n}\n\n// ── Matrix → table (columns + typed rows) ────────────────────────────────────\n\n/** Slugify a header label into a safe object key, deduping collisions. */\nfunction toKey(label: string, used: Set<string>): string {\n let base = label.trim().replace(/\\s+/g, '_').replace(/[^\\w\\u4e00-\\u9fa5]/g, '');\n if (!base) base = 'col';\n let key = base;\n let n = 1;\n while (used.has(key)) key = `${base}_${n++}`;\n used.add(key);\n return key;\n}\n\nconst DATE_RE = /^\\d{4}[-/]\\d{1,2}[-/]\\d{1,2}([ T]\\d{1,2}:\\d{2}(:\\d{2})?)?$/;\n\n/** Infer a column type from a sample of raw string cell values. */\nexport function inferColumnType(samples: string[]): FlowDataColumnType {\n const nonEmpty = samples.map((s) => s?.trim()).filter((s) => s);\n if (nonEmpty.length === 0) return 'string';\n const isBool = nonEmpty.every((s) => /^(true|false|yes|no|是|否)$/i.test(s));\n if (isBool) return 'boolean';\n const isNum = nonEmpty.every((s) => /^-?\\d+(\\.\\d+)?%?$/.test(s.replace(/,/g, '')));\n if (isNum) return 'number';\n const isDate = nonEmpty.every((s) => DATE_RE.test(s));\n if (isDate) return 'date';\n return 'string';\n}\n\n/** Coerce a raw string cell to a typed value based on the column type. */\nexport function coerceValue(raw: string, type: FlowDataColumnType): unknown {\n const s = (raw ?? '').trim();\n if (s === '') return type === 'number' ? null : '';\n switch (type) {\n case 'number': {\n const cleaned = s.replace(/,/g, '').replace(/%$/, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n case 'boolean':\n return /^(true|yes|是)$/i.test(s);\n case 'date':\n case 'string':\n default:\n return s;\n }\n}\n\n/**\n * Build a typed table from a raw string matrix. The first row is treated as the\n * header. Column types are inferred from the data rows.\n */\nexport function matrixToTable(matrix: string[][]): ParsedTable {\n if (matrix.length === 0) return { columns: [], rows: [] };\n const [header, ...dataRows] = matrix;\n const used = new Set<string>();\n const colCount = Math.max(header.length, ...dataRows.map((r) => r.length), 0);\n\n const columns: FlowDataColumn[] = [];\n for (let c = 0; c < colCount; c++) {\n const label = (header[c] ?? `列${c + 1}`).trim() || `列${c + 1}`;\n const samples = dataRows.slice(0, 50).map((r) => r[c] ?? '');\n columns.push({ key: toKey(label, used), label, type: inferColumnType(samples) });\n }\n\n const rows = dataRows.map((r) => {\n const record: Record<string, unknown> = {};\n columns.forEach((col, c) => {\n record[col.key] = coerceValue(r[c] ?? '', col.type);\n });\n return record;\n });\n\n return { columns, rows };\n}\n\n/** Parse a File (csv or xlsx) into a typed table. */\nexport async function parseDataFile(file: File): Promise<ParsedTable> {\n const name = file.name.toLowerCase();\n if (name.endsWith('.xlsx') || name.endsWith('.xlsm')) {\n const buffer = await file.arrayBuffer();\n return matrixToTable(await parseXlsx(buffer));\n }\n // treat everything else as delimited text (csv/tsv/txt)\n const text = await file.text();\n return matrixToTable(parseCsv(text));\n}\n\n// ── Config helpers ───────────────────────────────────────────────────────────\n\n/** Default palette for chart series, mirroring the demo examples. */\nexport const DATA_CHART_PALETTE = [\n '#6366f1', '#10b981', '#f59e0b', '#f43f5e', '#06b6d4',\n '#8b5cf6', '#84cc16', '#ec4899', '#0ea5e9', '#f97316',\n];\n\n/** Column key → display label lookup. */\nexport function labelFor(columns: FlowDataColumn[], key: string): string {\n return columns.find((c) => c.key === key)?.label ?? key;\n}\n\n/** First non-numeric column key (a sensible default X/category field). */\nexport function firstDimension(columns: FlowDataColumn[]): string | undefined {\n return (columns.find((c) => c.type !== 'number') ?? columns[0])?.key;\n}\n\n/** All numeric column keys (candidate measures/series). */\nexport function numericFields(columns: FlowDataColumn[]): string[] {\n return columns.filter((c) => c.type === 'number').map((c) => c.key);\n}\n\n/**\n * Produce a sensible default `FlowDataConfig` for a freshly parsed table:\n * table view, first numeric field charted against the first dimension.\n */\nexport function makeDefaultDataConfig(\n parsed: ParsedTable,\n sourceName?: string,\n): FlowDataConfig {\n const x = firstDimension(parsed.columns);\n const nums = numericFields(parsed.columns);\n return {\n columns: parsed.columns,\n rows: parsed.rows,\n view: 'table',\n sourceName,\n chart: {\n type: 'bar',\n xField: x,\n yFields: nums.slice(0, 1),\n },\n pivot: {\n enabled: false,\n rowFields: x ? [x] : [],\n colFields: [],\n values: nums[0] ? [{ field: nums[0], aggFn: 'sum' }] : [],\n },\n };\n}\n\n/**\n * Re-parse CSV text into an existing config, preserving column keys and types\n * for headers that match an existing column (by label or key). New headers get\n * fresh inferred columns; chart/pivot references to removed fields are pruned.\n */\nexport function applyCsvText(config: FlowDataConfig, text: string): FlowDataConfig {\n const matrix = parseCsv(text);\n if (matrix.length === 0) {\n return { ...config, columns: [], rows: [], chart: { type: 'bar' }, pivot: { enabled: false, rowFields: [], colFields: [], values: [] } };\n }\n const [header, ...dataRows] = matrix;\n const colCount = Math.max(header.length, ...dataRows.map((r) => r.length), 0);\n const used = new Set<string>();\n const byLabel = new Map(config.columns.map((c) => [c.label ?? c.key, c]));\n const byKey = new Map(config.columns.map((c) => [c.key, c]));\n\n const columns: FlowDataColumn[] = [];\n for (let c = 0; c < colCount; c++) {\n const label = (header[c] ?? `列${c + 1}`).trim() || `列${c + 1}`;\n const existing = byLabel.get(label) ?? byKey.get(label);\n if (existing) {\n used.add(existing.key);\n columns.push({ ...existing, label });\n } else {\n const samples = dataRows.slice(0, 50).map((r) => r[c] ?? '');\n columns.push({ key: toKey(label, used), label, type: inferColumnType(samples) });\n }\n }\n\n const rows = dataRows.map((r) => {\n const record: Record<string, unknown> = {};\n columns.forEach((col, c) => {\n record[col.key] = coerceValue(r[c] ?? '', col.type);\n });\n return record;\n });\n\n const keys = new Set(columns.map((c) => c.key));\n\n const chart = config.chart\n ? {\n ...config.chart,\n xField: config.chart.xField && keys.has(config.chart.xField)\n ? config.chart.xField\n : firstDimension(columns),\n yFields: (config.chart.yFields ?? []).filter((f) => keys.has(f)),\n seriesColors: config.chart.seriesColors\n ? Object.fromEntries(Object.entries(config.chart.seriesColors).filter(([f]) => keys.has(f)))\n : undefined,\n }\n : config.chart;\n\n const pivot = config.pivot\n ? {\n ...config.pivot,\n rowFields: config.pivot.rowFields.filter((f) => keys.has(f)),\n colFields: config.pivot.colFields.filter((f) => keys.has(f)),\n values: config.pivot.values.filter((v) => keys.has(v.field)),\n }\n : config.pivot;\n\n return { ...config, columns, rows, chart, pivot };\n}\n\n/** A small starter table used when creating an empty Data node from the palette. */\nexport function makeStarterDataConfig(): FlowDataConfig {\n const columns: FlowDataColumn[] = [\n { key: 'category', label: '类别', type: 'string' },\n { key: 'value', label: '数值', type: 'number' },\n ];\n const rows = [\n { category: 'A', value: 30 },\n { category: 'B', value: 45 },\n { category: 'C', value: 28 },\n ];\n return makeDefaultDataConfig({ columns, rows });\n}\n"],"mappings":"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"}
@@ -261,7 +261,7 @@ function Z(i, t) {
261
261
  }
262
262
  function j(i, t) {
263
263
  const e = t.width / 2, r = t.height / 2, n = Math.min(e, r), a = n * 0.4, s = 5, h = [];
264
- for (let c = 0; c < s * 2; c++) {
264
+ for (let c = 0; c < 10; c++) {
265
265
  const l = Math.PI * c / s - Math.PI / 2, u = c % 2 === 0 ? n : a;
266
266
  h.push({
267
267
  x: e + u * Math.cos(l),
@@ -430,7 +430,6 @@ function et(i, t, e, r) {
430
430
  x: h,
431
431
  y: e
432
432
  }), s(h - o, e, 0, e - h + o, 0, e - h), a(0, h);
433
- break;
434
433
  }
435
434
  return n;
436
435
  }
@@ -566,7 +565,6 @@ function st(i, t, e, r, n, a, s, h, c) {
566
565
  break;
567
566
  case "Q":
568
567
  i.quadraticCurveTo(d.cp1x, d.cp1y, d.x, d.y);
569
- break;
570
568
  }
571
569
  i.stroke({
572
570
  color: p,
@@ -1 +1 @@
1
- {"version":3,"file":"shapes.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/shapes.ts"],"sourcesContent":["import { Graphics } from 'pixi.js';\nimport type { FlowShapeType, FlowNodeData, FlowBorderSides, FlowBorderSideOverride } from '../types';\nimport { drawDashedPath, type PathSeg } from '../utils/dashedLine';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nexport interface ShapeDrawOptions {\n width: number;\n height: number;\n fill: string;\n stroke: string;\n strokeWidth: number;\n borderStyle?: 'solid' | 'dashed' | 'dotted' | 'dynamic' | 'none';\n dashOffset?: number;\n}\n\nfunction parseDash(style: string | undefined, strokeWidth: number): number[] | undefined {\n if (!style || style === 'solid') return undefined;\n if (style === 'dynamic') return [strokeWidth * 4, strokeWidth * 3];\n if (style === 'dashed') return [strokeWidth * 4, strokeWidth * 2];\n if (style === 'dotted') return [strokeWidth, strokeWidth * 2];\n return undefined;\n}\n\n/**\n * Sample a rectangle's outline as points for dashed border.\n */\nfunction sampleRect(w: number, h: number, step = 3): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n for (let x = 0; x <= w; x += step) pts.push({ x, y: 0 });\n for (let y = step; y <= h; y += step) pts.push({ x: w, y });\n for (let x = w - step; x >= 0; x -= step) pts.push({ x, y: h });\n for (let y = h - step; y > 0; y -= step) pts.push({ x: 0, y });\n pts.push({ x: 0, y: 0 });\n return pts;\n}\n\n/**\n * Sample a rounded rectangle outline as points.\n */\nfunction sampleRoundRect(w: number, h: number, r: number, step = 3): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n const cornerSamples = Math.max(4, Math.ceil((Math.PI / 2) * r / step));\n const addCorner = (cx: number, cy: number, startAngle: number) => {\n for (let i = 0; i <= cornerSamples; i++) {\n const a = startAngle + (Math.PI / 2) * (i / cornerSamples);\n pts.push({ x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) });\n }\n };\n addCorner(w - r, r, -Math.PI / 2);\n addCorner(w - r, h - r, 0);\n addCorner(r, h - r, Math.PI / 2);\n addCorner(r, r, Math.PI);\n if (pts.length > 0) pts.push(pts[0]);\n return pts;\n}\n\n/**\n * Sample an ellipse outline.\n */\nfunction sampleEllipse(cx: number, cy: number, rx: number, ry: number, samples = 60): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i <= samples; i++) {\n const a = (Math.PI * 2 * i) / samples;\n pts.push({ x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) });\n }\n return pts;\n}\n\n/**\n * Draw dashed polyline onto graphics.\n */\nfunction drawDashedPoly(g: Graphics, pts: Array<{ x: number; y: number }>, dash: number[], offset: number, color: string, width: number): void {\n if (pts.length < 2) return;\n const dists = [0];\n for (let i = 1; i < pts.length; i++) {\n dists.push(dists[i - 1] + Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y));\n }\n const total = dists[dists.length - 1];\n if (total < 1) return;\n const patternLen = dash[0] + dash[1];\n let pos = -(((offset % patternLen) + patternLen) % patternLen);\n let drawing = true;\n\n const lerp = (d: number) => {\n if (d <= 0) return pts[0];\n if (d >= total) return pts[pts.length - 1];\n let lo = 0, hi = dists.length - 1;\n while (lo < hi - 1) { const m = (lo + hi) >> 1; if (dists[m] <= d) lo = m; else hi = m; }\n const t = dists[hi] - dists[lo] > 0 ? (d - dists[lo]) / (dists[hi] - dists[lo]) : 0;\n return { x: pts[lo].x + (pts[hi].x - pts[lo].x) * t, y: pts[lo].y + (pts[hi].y - pts[lo].y) * t };\n };\n\n while (pos < total) {\n const segLen = drawing ? dash[0] : dash[1];\n const start = Math.max(pos, 0);\n const end = Math.min(pos + segLen, total);\n if (drawing && end > start) {\n const p0 = lerp(start);\n g.moveTo(p0.x, p0.y);\n for (let d = start + 2; d < end; d += 2) {\n const p = lerp(d);\n g.lineTo(p.x, p.y);\n }\n const pe = lerp(end);\n g.lineTo(pe.x, pe.y);\n }\n pos += segLen;\n drawing = !drawing;\n }\n g.stroke({ color, width, cap: 'round' as const });\n}\n\nfunction fillShape(g: Graphics, o: ShapeDrawOptions) {\n if (o.fill && o.fill !== 'transparent') {\n g.fill({ color: o.fill });\n }\n if (o.borderStyle === 'none') return;\n if (o.stroke && o.stroke !== 'transparent' && o.strokeWidth > 0) {\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (dash) {\n // Dashed/dotted/dynamic: don't stroke the shape path, we'll draw dashed separately\n } else {\n g.stroke({ color: o.stroke, width: o.strokeWidth });\n }\n }\n}\n\n/**\n * After fillShape, draw dashed border if needed.\n * Pass shape-specific outline points.\n */\nfunction drawDashedBorder(g: Graphics, o: ShapeDrawOptions, outlinePts: Array<{ x: number; y: number }>) {\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (!dash || !o.stroke || o.stroke === 'transparent' || o.strokeWidth <= 0) return;\n const offset = o.borderStyle === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, outlinePts, dash, offset, o.stroke, o.strokeWidth);\n}\n\n/** Draw only a rounded-rectangle border, without leaving a base path that can\n * be picked up by the dashed stroke. Useful when fill and border are rendered\n * independently, as they are for SVG icon nodes. */\nexport function drawRoundRectBorder(g: Graphics, o: ShapeDrawOptions, radius?: number): void {\n if (o.borderStyle === 'none' || !o.stroke || o.stroke === 'transparent' || o.strokeWidth <= 0) return;\n const r = radius ?? Math.min(12, o.width * 0.1, o.height * 0.1);\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (dash) {\n const offset = o.borderStyle === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, sampleRoundRect(o.width, o.height, r), dash, offset, o.stroke, o.strokeWidth);\n } else {\n g.roundRect(0, 0, o.width, o.height, r).stroke({ color: o.stroke, width: o.strokeWidth });\n }\n}\n\nfunction polyPoints(verts: Array<{ x: number; y: number }>): Array<{ x: number; y: number }> {\n return [...verts, verts[0]];\n}\n\nexport function drawRect(g: Graphics, o: ShapeDrawOptions): void {\n g.rect(0, 0, o.width, o.height);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleRect(o.width, o.height));\n}\n\nexport function drawRoundRect(g: Graphics, o: ShapeDrawOptions): void {\n const r = Math.min(12, o.width * 0.1, o.height * 0.1);\n g.roundRect(0, 0, o.width, o.height, r);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleRoundRect(o.width, o.height, r));\n}\n\nexport function drawEllipse(g: Graphics, o: ShapeDrawOptions): void {\n g.ellipse(o.width / 2, o.height / 2, o.width / 2, o.height / 2);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleEllipse(o.width / 2, o.height / 2, o.width / 2, o.height / 2));\n}\n\nexport function drawDiamond(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const verts = [{ x: cx, y: 0 }, { x: o.width, y: cy }, { x: cx, y: o.height }, { x: 0, y: cy }];\n g.moveTo(cx, 0).lineTo(o.width, cy).lineTo(cx, o.height).lineTo(0, cy).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawDocument(g: Graphics, o: ShapeDrawOptions): void {\n const w = o.width, h = o.height, curve = h * 0.15;\n g.moveTo(0, 0)\n .lineTo(w, 0)\n .lineTo(w, h - curve)\n .bezierCurveTo(w * 0.75, h - curve * 2, w * 0.25, h, 0, h - curve)\n .closePath();\n fillShape(g, o);\n const pts: Array<{ x: number; y: number }> = [{ x: 0, y: 0 }, { x: w, y: 0 }, { x: w, y: h - curve }];\n const samples = 20;\n for (let i = 1; i <= samples; i++) {\n const t = i / samples;\n const u = 1 - t;\n pts.push({\n x: u * u * u * w + 3 * u * u * t * (w * 0.75) + 3 * u * t * t * (w * 0.25),\n y: u * u * u * (h - curve) + 3 * u * u * t * (h - curve * 2) + 3 * u * t * t * h + t * t * t * (h - curve),\n });\n }\n pts.push({ x: 0, y: 0 });\n drawDashedBorder(g, o, pts);\n}\n\nexport function drawParallelogram(g: Graphics, o: ShapeDrawOptions): void {\n const skew = o.width * 0.2;\n const verts = [{ x: skew, y: 0 }, { x: o.width, y: 0 }, { x: o.width - skew, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(skew, 0).lineTo(o.width, 0).lineTo(o.width - skew, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawTriangle(g: Graphics, o: ShapeDrawOptions): void {\n const verts = [{ x: o.width / 2, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(o.width / 2, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawTrapezoid(g: Graphics, o: ShapeDrawOptions): void {\n const inset = o.width * 0.15;\n const verts = [{ x: inset, y: 0 }, { x: o.width - inset, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(inset, 0).lineTo(o.width - inset, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nfunction regularPoly(cx: number, cy: number, sides: number, rx: number, ry: number, startAngle: number): Array<{ x: number; y: number }> {\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < sides; i++) {\n const a = (Math.PI * 2 * i) / sides + startAngle;\n verts.push({ x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) });\n }\n return verts;\n}\n\nexport function drawPentagon(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2, r = Math.min(cx, cy);\n const verts = regularPoly(cx, cy, 5, r, r, -Math.PI / 2);\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawHexagon(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const verts = regularPoly(cx, cy, 6, cx, cy, -Math.PI / 6);\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawStar(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const outer = Math.min(cx, cy), inner = outer * 0.4, points = 5;\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < points * 2; i++) {\n const angle = (Math.PI * i) / points - Math.PI / 2;\n const r = i % 2 === 0 ? outer : inner;\n verts.push({ x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) });\n }\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawHexagram(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const outer = Math.min(cx, cy), inner = outer * 0.55;\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < 12; i++) {\n const angle = (Math.PI * i) / 6 - Math.PI / 2;\n const r = i % 2 === 0 ? outer : inner;\n verts.push({ x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) });\n }\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawRightTriangle(g: Graphics, o: ShapeDrawOptions): void {\n const verts = [{ x: 0, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(0, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawCorner(g: Graphics, o: ShapeDrawOptions): void {\n const half = Math.min(o.width, o.height) * 0.4;\n const verts = [\n { x: 0, y: 0 }, { x: o.width, y: 0 }, { x: o.width, y: half },\n { x: half, y: half }, { x: half, y: o.height }, { x: 0, y: o.height },\n ];\n g.moveTo(0, 0).lineTo(o.width, 0).lineTo(o.width, half)\n .lineTo(half, half).lineTo(half, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawFlowGroup(g: Graphics, o: ShapeDrawOptions): void {\n const r = Math.min(6, o.width * 0.04, o.height * 0.04);\n g.roundRect(0, 0, o.width, o.height, r);\n if (o.fill && o.fill !== 'transparent') {\n g.fill({ color: o.fill, alpha: 0.08 });\n }\n const border = o.borderStyle ?? 'dashed';\n if (border !== 'none' && o.stroke && o.stroke !== 'transparent' && o.strokeWidth > 0) {\n const dash = parseDash(border, o.strokeWidth);\n if (dash) {\n const offset = border === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, sampleRoundRect(o.width, o.height, r), dash, offset, o.stroke, o.strokeWidth);\n } else {\n g.stroke({ color: o.stroke, width: o.strokeWidth });\n }\n }\n}\n\nexport const drawGeometryGroup = drawFlowGroup;\n\n/* ─── Per-side borders (top / right / bottom / left) ─────────────────── */\n\nexport type BorderSideName = 'top' | 'right' | 'bottom' | 'left';\nexport const BORDER_SIDE_NAMES: BorderSideName[] = ['top', 'right', 'bottom', 'left'];\n\n/** Shape types whose geometry has four well-defined sides. Other shapes ignore\n * `borderSides` and keep a full outline. */\nexport const BORDER_SIDE_TYPES = new Set<string>([\n 'shapeRect', 'shapeRoundRect', 'shapeEllipse', 'shapeDiamond', 'shapeDocument',\n 'shapeParallelogram', 'shapeTrapezoid', 'mediaNode', 'flowGroup', 'geometryGroup',\n]);\n\n/** True when `borderSides` carries at least one effective override AND the\n * shape type supports per-side borders. */\nexport function hasBorderSideOverrides(data: FlowNodeData, type?: string): boolean {\n if (type !== undefined && !BORDER_SIDE_TYPES.has(type)) return false;\n const sides = data.borderSides;\n if (!sides) return false;\n return BORDER_SIDE_NAMES.some((name) => {\n const side = sides[name];\n return !!side\n && (side.visible === false || side.color !== undefined || side.width !== undefined);\n });\n}\n\n/** Corner radius used by each shape's own drawer, so side segments line up\n * exactly with the (possibly hidden) full outline. */\nfunction borderSideRadius(type: string, w: number, h: number): number {\n switch (type) {\n case 'shapeRoundRect': return Math.min(12, w * 0.1, h * 0.1);\n case 'mediaNode': return 6;\n case 'flowGroup':\n case 'geometryGroup': return Math.min(6, w * 0.04, h * 0.04);\n default: return 0;\n }\n}\n\nconst BEZIER_K = 0.5522847498; // kappa for a 90° arc approximation\n\n/** Build the drawable path of one side of the shape. Corners are owned by the\n * side that starts there (clockwise): top owns the top-left arc, right the\n * top-right arc, and so on — with uniform styling the four sides reconstruct\n * the full outline seamlessly. */\nexport function buildBorderSideSegments(\n type: string,\n w: number,\n h: number,\n side: BorderSideName,\n): PathSeg[] {\n const segs: PathSeg[] = [];\n const line = (x: number, y: number) => segs.push({ type: 'L', x, y });\n const cubic = (\n c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number,\n ) => segs.push({ type: 'C', cp1x: c1x, cp1y: c1y, cp2x: c2x, cp2y: c2y, x, y });\n\n const r = borderSideRadius(type, w, h);\n if (r >= 0.5) {\n // Rounded rect family (shapeRoundRect / mediaNode / group frames): each\n // side owns its starting corner arc (clockwise), so uniform styling\n // reconstructs the full rounded outline seamlessly.\n const k = BEZIER_K * r;\n switch (side) {\n case 'top':\n segs.push({ type: 'M', x: 0, y: r });\n cubic(0, r - k, r - k, 0, r, 0);\n line(w - r, 0);\n break;\n case 'right':\n segs.push({ type: 'M', x: w - r, y: 0 });\n cubic(w - r + k, 0, w, r - k, w, r);\n line(w, h - r);\n break;\n case 'bottom':\n segs.push({ type: 'M', x: w, y: h - r });\n cubic(w, h - r + k, w - r + k, h, w - r, h);\n line(r, h);\n break;\n case 'left':\n segs.push({ type: 'M', x: r, y: h });\n cubic(r - k, h, 0, h - r + k, 0, h - r);\n line(0, r);\n break;\n }\n return segs;\n }\n\n if (type === 'shapeEllipse') {\n // Split the outline at the 45° diagonals so each side is the arc centered\n // on its direction (top arc spans the top, etc.).\n const cx = w / 2, cy = h / 2, rx = w / 2, ry = h / 2;\n const angles: Record<BorderSideName, [number, number]> = {\n top: [Math.PI * 1.25, Math.PI * 1.75],\n right: [Math.PI * 1.75, Math.PI * 2.25],\n bottom: [Math.PI * 0.25, Math.PI * 0.75],\n left: [Math.PI * 0.75, Math.PI * 1.25],\n };\n const [a0, a1] = angles[side];\n const p0x = cx + rx * Math.cos(a0), p0y = cy + ry * Math.sin(a0);\n const p3x = cx + rx * Math.cos(a1), p3y = cy + ry * Math.sin(a1);\n segs.push({ type: 'M', x: p0x, y: p0y });\n cubic(\n p0x - BEZIER_K * rx * Math.sin(a0), p0y + BEZIER_K * ry * Math.cos(a0),\n p3x + BEZIER_K * rx * Math.sin(a1), p3y - BEZIER_K * ry * Math.cos(a1),\n p3x, p3y,\n );\n return segs;\n }\n\n if (type === 'shapeDocument') {\n const curve = h * 0.15;\n if (side === 'top') {\n segs.push({ type: 'M', x: 0, y: 0 });\n line(w, 0);\n } else if (side === 'right') {\n segs.push({ type: 'M', x: w, y: 0 });\n line(w, h - curve);\n } else if (side === 'bottom') {\n segs.push({ type: 'M', x: w, y: h - curve });\n cubic(w * 0.75, h - curve * 2, w * 0.25, h, 0, h - curve);\n } else {\n segs.push({ type: 'M', x: 0, y: h - curve });\n line(0, 0);\n }\n return segs;\n }\n\n // Quadrilaterals (rect / diamond / parallelogram / trapezoid).\n let v0: { x: number; y: number }, v1: { x: number; y: number }, v2: { x: number; y: number }, v3: { x: number; y: number };\n if (type === 'shapeDiamond') {\n const cx = w / 2, cy = h / 2;\n v0 = { x: cx, y: 0 }; v1 = { x: w, y: cy }; v2 = { x: cx, y: h }; v3 = { x: 0, y: cy };\n } else if (type === 'shapeParallelogram') {\n const skew = w * 0.2;\n v0 = { x: skew, y: 0 }; v1 = { x: w, y: 0 }; v2 = { x: w - skew, y: h }; v3 = { x: 0, y: h };\n } else if (type === 'shapeTrapezoid') {\n const inset = w * 0.15;\n v0 = { x: inset, y: 0 }; v1 = { x: w - inset, y: 0 }; v2 = { x: w, y: h }; v3 = { x: 0, y: h };\n } else {\n v0 = { x: 0, y: 0 }; v1 = { x: w, y: 0 }; v2 = { x: w, y: h }; v3 = { x: 0, y: h };\n }\n\n const edges: Record<BorderSideName, [{ x: number; y: number }, { x: number; y: number }]> = {\n top: [v0, v1],\n right: [v1, v2],\n bottom: [v2, v3],\n left: [v3, v0],\n };\n const [a, b] = edges[side];\n segs.push({ type: 'M', x: a.x, y: a.y });\n line(b.x, b.y);\n return segs;\n}\n\n/** Draw the four sides of a node independently, honoring per-side color /\n * width / visibility overrides (falling back to the node's defaults). The\n * node's `borderStyle` (solid / dashed / dotted / dynamic) applies to every\n * side. `defaultColor` is the node's (already theme-resolved) stroke. */\nexport function drawBorderSides(\n g: Graphics,\n type: string,\n width: number,\n height: number,\n sides: FlowBorderSides | undefined,\n defaultColor: string,\n defaultWidth: number,\n borderStyle: string | undefined,\n dashOffset: number,\n): void {\n if (borderStyle === 'none') return;\n for (const name of BORDER_SIDE_NAMES) {\n const side: FlowBorderSideOverride | undefined = sides?.[name];\n if (side?.visible === false) continue;\n const color = resolveThemeColor(side?.color, defaultColor) || defaultColor;\n const strokeWidth = side?.width ?? defaultWidth;\n if (!color || color === 'transparent' || !(strokeWidth > 0)) continue;\n const segs = buildBorderSideSegments(type, width, height, name);\n const dash = parseDash(borderStyle, strokeWidth);\n if (dash) {\n const offset = borderStyle === 'dynamic' ? dashOffset : 0;\n drawDashedPath(g, segs, dash, offset);\n g.stroke({ color, width: strokeWidth, cap: 'round' as const });\n } else {\n for (const seg of segs) {\n switch (seg.type) {\n case 'M': g.moveTo(seg.x, seg.y); break;\n case 'L': g.lineTo(seg.x, seg.y); break;\n case 'C': g.bezierCurveTo(seg.cp1x!, seg.cp1y!, seg.cp2x!, seg.cp2y!, seg.x, seg.y); break;\n case 'Q': g.quadraticCurveTo(seg.cp1x!, seg.cp1y!, seg.x, seg.y); break;\n }\n }\n g.stroke({ color, width: strokeWidth });\n }\n }\n}\n\n/** Lookup table mapping shape type to draw function */\nexport const shapeDrawers: Record<string, (g: Graphics, o: ShapeDrawOptions) => void> = {\n shapeRect: drawRect,\n shapeRoundRect: drawRoundRect,\n shapeEllipse: drawEllipse,\n shapeDiamond: drawDiamond,\n shapeDocument: drawDocument,\n shapeParallelogram: drawParallelogram,\n shapeTriangle: drawTriangle,\n shapeTrapezoid: drawTrapezoid,\n shapePentagon: drawPentagon,\n shapeHexagon: drawHexagon,\n shapeStar: drawStar,\n shapeHexagram: drawHexagram,\n shapeRightTriangle: drawRightTriangle,\n shapeCorner: drawCorner,\n textLabel: drawRect,\n flowGroup: drawFlowGroup,\n geometryGroup: drawGeometryGroup,\n shapeSvg: drawRoundRect,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"shapes.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/shapes.ts"],"sourcesContent":["import { Graphics } from 'pixi.js';\nimport type { FlowShapeType, FlowNodeData, FlowBorderSides, FlowBorderSideOverride } from '../types';\nimport { drawDashedPath, type PathSeg } from '../utils/dashedLine';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nexport interface ShapeDrawOptions {\n width: number;\n height: number;\n fill: string;\n stroke: string;\n strokeWidth: number;\n borderStyle?: 'solid' | 'dashed' | 'dotted' | 'dynamic' | 'none';\n dashOffset?: number;\n}\n\nfunction parseDash(style: string | undefined, strokeWidth: number): number[] | undefined {\n if (!style || style === 'solid') return undefined;\n if (style === 'dynamic') return [strokeWidth * 4, strokeWidth * 3];\n if (style === 'dashed') return [strokeWidth * 4, strokeWidth * 2];\n if (style === 'dotted') return [strokeWidth, strokeWidth * 2];\n return undefined;\n}\n\n/**\n * Sample a rectangle's outline as points for dashed border.\n */\nfunction sampleRect(w: number, h: number, step = 3): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n for (let x = 0; x <= w; x += step) pts.push({ x, y: 0 });\n for (let y = step; y <= h; y += step) pts.push({ x: w, y });\n for (let x = w - step; x >= 0; x -= step) pts.push({ x, y: h });\n for (let y = h - step; y > 0; y -= step) pts.push({ x: 0, y });\n pts.push({ x: 0, y: 0 });\n return pts;\n}\n\n/**\n * Sample a rounded rectangle outline as points.\n */\nfunction sampleRoundRect(w: number, h: number, r: number, step = 3): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n const cornerSamples = Math.max(4, Math.ceil((Math.PI / 2) * r / step));\n const addCorner = (cx: number, cy: number, startAngle: number) => {\n for (let i = 0; i <= cornerSamples; i++) {\n const a = startAngle + (Math.PI / 2) * (i / cornerSamples);\n pts.push({ x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) });\n }\n };\n addCorner(w - r, r, -Math.PI / 2);\n addCorner(w - r, h - r, 0);\n addCorner(r, h - r, Math.PI / 2);\n addCorner(r, r, Math.PI);\n if (pts.length > 0) pts.push(pts[0]);\n return pts;\n}\n\n/**\n * Sample an ellipse outline.\n */\nfunction sampleEllipse(cx: number, cy: number, rx: number, ry: number, samples = 60): Array<{ x: number; y: number }> {\n const pts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i <= samples; i++) {\n const a = (Math.PI * 2 * i) / samples;\n pts.push({ x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) });\n }\n return pts;\n}\n\n/**\n * Draw dashed polyline onto graphics.\n */\nfunction drawDashedPoly(g: Graphics, pts: Array<{ x: number; y: number }>, dash: number[], offset: number, color: string, width: number): void {\n if (pts.length < 2) return;\n const dists = [0];\n for (let i = 1; i < pts.length; i++) {\n dists.push(dists[i - 1] + Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y));\n }\n const total = dists[dists.length - 1];\n if (total < 1) return;\n const patternLen = dash[0] + dash[1];\n let pos = -(((offset % patternLen) + patternLen) % patternLen);\n let drawing = true;\n\n const lerp = (d: number) => {\n if (d <= 0) return pts[0];\n if (d >= total) return pts[pts.length - 1];\n let lo = 0, hi = dists.length - 1;\n while (lo < hi - 1) { const m = (lo + hi) >> 1; if (dists[m] <= d) lo = m; else hi = m; }\n const t = dists[hi] - dists[lo] > 0 ? (d - dists[lo]) / (dists[hi] - dists[lo]) : 0;\n return { x: pts[lo].x + (pts[hi].x - pts[lo].x) * t, y: pts[lo].y + (pts[hi].y - pts[lo].y) * t };\n };\n\n while (pos < total) {\n const segLen = drawing ? dash[0] : dash[1];\n const start = Math.max(pos, 0);\n const end = Math.min(pos + segLen, total);\n if (drawing && end > start) {\n const p0 = lerp(start);\n g.moveTo(p0.x, p0.y);\n for (let d = start + 2; d < end; d += 2) {\n const p = lerp(d);\n g.lineTo(p.x, p.y);\n }\n const pe = lerp(end);\n g.lineTo(pe.x, pe.y);\n }\n pos += segLen;\n drawing = !drawing;\n }\n g.stroke({ color, width, cap: 'round' as const });\n}\n\nfunction fillShape(g: Graphics, o: ShapeDrawOptions) {\n if (o.fill && o.fill !== 'transparent') {\n g.fill({ color: o.fill });\n }\n if (o.borderStyle === 'none') return;\n if (o.stroke && o.stroke !== 'transparent' && o.strokeWidth > 0) {\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (dash) {\n // Dashed/dotted/dynamic: don't stroke the shape path, we'll draw dashed separately\n } else {\n g.stroke({ color: o.stroke, width: o.strokeWidth });\n }\n }\n}\n\n/**\n * After fillShape, draw dashed border if needed.\n * Pass shape-specific outline points.\n */\nfunction drawDashedBorder(g: Graphics, o: ShapeDrawOptions, outlinePts: Array<{ x: number; y: number }>) {\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (!dash || !o.stroke || o.stroke === 'transparent' || o.strokeWidth <= 0) return;\n const offset = o.borderStyle === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, outlinePts, dash, offset, o.stroke, o.strokeWidth);\n}\n\n/** Draw only a rounded-rectangle border, without leaving a base path that can\n * be picked up by the dashed stroke. Useful when fill and border are rendered\n * independently, as they are for SVG icon nodes. */\nexport function drawRoundRectBorder(g: Graphics, o: ShapeDrawOptions, radius?: number): void {\n if (o.borderStyle === 'none' || !o.stroke || o.stroke === 'transparent' || o.strokeWidth <= 0) return;\n const r = radius ?? Math.min(12, o.width * 0.1, o.height * 0.1);\n const dash = parseDash(o.borderStyle, o.strokeWidth);\n if (dash) {\n const offset = o.borderStyle === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, sampleRoundRect(o.width, o.height, r), dash, offset, o.stroke, o.strokeWidth);\n } else {\n g.roundRect(0, 0, o.width, o.height, r).stroke({ color: o.stroke, width: o.strokeWidth });\n }\n}\n\nfunction polyPoints(verts: Array<{ x: number; y: number }>): Array<{ x: number; y: number }> {\n return [...verts, verts[0]];\n}\n\nexport function drawRect(g: Graphics, o: ShapeDrawOptions): void {\n g.rect(0, 0, o.width, o.height);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleRect(o.width, o.height));\n}\n\nexport function drawRoundRect(g: Graphics, o: ShapeDrawOptions): void {\n const r = Math.min(12, o.width * 0.1, o.height * 0.1);\n g.roundRect(0, 0, o.width, o.height, r);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleRoundRect(o.width, o.height, r));\n}\n\nexport function drawEllipse(g: Graphics, o: ShapeDrawOptions): void {\n g.ellipse(o.width / 2, o.height / 2, o.width / 2, o.height / 2);\n fillShape(g, o);\n drawDashedBorder(g, o, sampleEllipse(o.width / 2, o.height / 2, o.width / 2, o.height / 2));\n}\n\nexport function drawDiamond(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const verts = [{ x: cx, y: 0 }, { x: o.width, y: cy }, { x: cx, y: o.height }, { x: 0, y: cy }];\n g.moveTo(cx, 0).lineTo(o.width, cy).lineTo(cx, o.height).lineTo(0, cy).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawDocument(g: Graphics, o: ShapeDrawOptions): void {\n const w = o.width, h = o.height, curve = h * 0.15;\n g.moveTo(0, 0)\n .lineTo(w, 0)\n .lineTo(w, h - curve)\n .bezierCurveTo(w * 0.75, h - curve * 2, w * 0.25, h, 0, h - curve)\n .closePath();\n fillShape(g, o);\n const pts: Array<{ x: number; y: number }> = [{ x: 0, y: 0 }, { x: w, y: 0 }, { x: w, y: h - curve }];\n const samples = 20;\n for (let i = 1; i <= samples; i++) {\n const t = i / samples;\n const u = 1 - t;\n pts.push({\n x: u * u * u * w + 3 * u * u * t * (w * 0.75) + 3 * u * t * t * (w * 0.25),\n y: u * u * u * (h - curve) + 3 * u * u * t * (h - curve * 2) + 3 * u * t * t * h + t * t * t * (h - curve),\n });\n }\n pts.push({ x: 0, y: 0 });\n drawDashedBorder(g, o, pts);\n}\n\nexport function drawParallelogram(g: Graphics, o: ShapeDrawOptions): void {\n const skew = o.width * 0.2;\n const verts = [{ x: skew, y: 0 }, { x: o.width, y: 0 }, { x: o.width - skew, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(skew, 0).lineTo(o.width, 0).lineTo(o.width - skew, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawTriangle(g: Graphics, o: ShapeDrawOptions): void {\n const verts = [{ x: o.width / 2, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(o.width / 2, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawTrapezoid(g: Graphics, o: ShapeDrawOptions): void {\n const inset = o.width * 0.15;\n const verts = [{ x: inset, y: 0 }, { x: o.width - inset, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(inset, 0).lineTo(o.width - inset, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nfunction regularPoly(cx: number, cy: number, sides: number, rx: number, ry: number, startAngle: number): Array<{ x: number; y: number }> {\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < sides; i++) {\n const a = (Math.PI * 2 * i) / sides + startAngle;\n verts.push({ x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) });\n }\n return verts;\n}\n\nexport function drawPentagon(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2, r = Math.min(cx, cy);\n const verts = regularPoly(cx, cy, 5, r, r, -Math.PI / 2);\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawHexagon(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const verts = regularPoly(cx, cy, 6, cx, cy, -Math.PI / 6);\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawStar(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const outer = Math.min(cx, cy), inner = outer * 0.4, points = 5;\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < points * 2; i++) {\n const angle = (Math.PI * i) / points - Math.PI / 2;\n const r = i % 2 === 0 ? outer : inner;\n verts.push({ x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) });\n }\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawHexagram(g: Graphics, o: ShapeDrawOptions): void {\n const cx = o.width / 2, cy = o.height / 2;\n const outer = Math.min(cx, cy), inner = outer * 0.55;\n const verts: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < 12; i++) {\n const angle = (Math.PI * i) / 6 - Math.PI / 2;\n const r = i % 2 === 0 ? outer : inner;\n verts.push({ x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) });\n }\n for (let i = 0; i < verts.length; i++) {\n if (i === 0) g.moveTo(verts[i].x, verts[i].y); else g.lineTo(verts[i].x, verts[i].y);\n }\n g.closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawRightTriangle(g: Graphics, o: ShapeDrawOptions): void {\n const verts = [{ x: 0, y: 0 }, { x: o.width, y: o.height }, { x: 0, y: o.height }];\n g.moveTo(0, 0).lineTo(o.width, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawCorner(g: Graphics, o: ShapeDrawOptions): void {\n const half = Math.min(o.width, o.height) * 0.4;\n const verts = [\n { x: 0, y: 0 }, { x: o.width, y: 0 }, { x: o.width, y: half },\n { x: half, y: half }, { x: half, y: o.height }, { x: 0, y: o.height },\n ];\n g.moveTo(0, 0).lineTo(o.width, 0).lineTo(o.width, half)\n .lineTo(half, half).lineTo(half, o.height).lineTo(0, o.height).closePath();\n fillShape(g, o);\n drawDashedBorder(g, o, polyPoints(verts));\n}\n\nexport function drawFlowGroup(g: Graphics, o: ShapeDrawOptions): void {\n const r = Math.min(6, o.width * 0.04, o.height * 0.04);\n g.roundRect(0, 0, o.width, o.height, r);\n if (o.fill && o.fill !== 'transparent') {\n g.fill({ color: o.fill, alpha: 0.08 });\n }\n const border = o.borderStyle ?? 'dashed';\n if (border !== 'none' && o.stroke && o.stroke !== 'transparent' && o.strokeWidth > 0) {\n const dash = parseDash(border, o.strokeWidth);\n if (dash) {\n const offset = border === 'dynamic' ? (o.dashOffset ?? 0) : 0;\n drawDashedPoly(g, sampleRoundRect(o.width, o.height, r), dash, offset, o.stroke, o.strokeWidth);\n } else {\n g.stroke({ color: o.stroke, width: o.strokeWidth });\n }\n }\n}\n\nexport const drawGeometryGroup = drawFlowGroup;\n\n/* ─── Per-side borders (top / right / bottom / left) ─────────────────── */\n\nexport type BorderSideName = 'top' | 'right' | 'bottom' | 'left';\nexport const BORDER_SIDE_NAMES: BorderSideName[] = ['top', 'right', 'bottom', 'left'];\n\n/** Shape types whose geometry has four well-defined sides. Other shapes ignore\n * `borderSides` and keep a full outline. */\nexport const BORDER_SIDE_TYPES = new Set<string>([\n 'shapeRect', 'shapeRoundRect', 'shapeEllipse', 'shapeDiamond', 'shapeDocument',\n 'shapeParallelogram', 'shapeTrapezoid', 'mediaNode', 'flowGroup', 'geometryGroup',\n]);\n\n/** True when `borderSides` carries at least one effective override AND the\n * shape type supports per-side borders. */\nexport function hasBorderSideOverrides(data: FlowNodeData, type?: string): boolean {\n if (type !== undefined && !BORDER_SIDE_TYPES.has(type)) return false;\n const sides = data.borderSides;\n if (!sides) return false;\n return BORDER_SIDE_NAMES.some((name) => {\n const side = sides[name];\n return !!side\n && (side.visible === false || side.color !== undefined || side.width !== undefined);\n });\n}\n\n/** Corner radius used by each shape's own drawer, so side segments line up\n * exactly with the (possibly hidden) full outline. */\nfunction borderSideRadius(type: string, w: number, h: number): number {\n switch (type) {\n case 'shapeRoundRect': return Math.min(12, w * 0.1, h * 0.1);\n case 'mediaNode': return 6;\n case 'flowGroup':\n case 'geometryGroup': return Math.min(6, w * 0.04, h * 0.04);\n default: return 0;\n }\n}\n\nconst BEZIER_K = 0.5522847498; // kappa for a 90° arc approximation\n\n/** Build the drawable path of one side of the shape. Corners are owned by the\n * side that starts there (clockwise): top owns the top-left arc, right the\n * top-right arc, and so on — with uniform styling the four sides reconstruct\n * the full outline seamlessly. */\nexport function buildBorderSideSegments(\n type: string,\n w: number,\n h: number,\n side: BorderSideName,\n): PathSeg[] {\n const segs: PathSeg[] = [];\n const line = (x: number, y: number) => segs.push({ type: 'L', x, y });\n const cubic = (\n c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number,\n ) => segs.push({ type: 'C', cp1x: c1x, cp1y: c1y, cp2x: c2x, cp2y: c2y, x, y });\n\n const r = borderSideRadius(type, w, h);\n if (r >= 0.5) {\n // Rounded rect family (shapeRoundRect / mediaNode / group frames): each\n // side owns its starting corner arc (clockwise), so uniform styling\n // reconstructs the full rounded outline seamlessly.\n const k = BEZIER_K * r;\n switch (side) {\n case 'top':\n segs.push({ type: 'M', x: 0, y: r });\n cubic(0, r - k, r - k, 0, r, 0);\n line(w - r, 0);\n break;\n case 'right':\n segs.push({ type: 'M', x: w - r, y: 0 });\n cubic(w - r + k, 0, w, r - k, w, r);\n line(w, h - r);\n break;\n case 'bottom':\n segs.push({ type: 'M', x: w, y: h - r });\n cubic(w, h - r + k, w - r + k, h, w - r, h);\n line(r, h);\n break;\n case 'left':\n segs.push({ type: 'M', x: r, y: h });\n cubic(r - k, h, 0, h - r + k, 0, h - r);\n line(0, r);\n break;\n }\n return segs;\n }\n\n if (type === 'shapeEllipse') {\n // Split the outline at the 45° diagonals so each side is the arc centered\n // on its direction (top arc spans the top, etc.).\n const cx = w / 2, cy = h / 2, rx = w / 2, ry = h / 2;\n const angles: Record<BorderSideName, [number, number]> = {\n top: [Math.PI * 1.25, Math.PI * 1.75],\n right: [Math.PI * 1.75, Math.PI * 2.25],\n bottom: [Math.PI * 0.25, Math.PI * 0.75],\n left: [Math.PI * 0.75, Math.PI * 1.25],\n };\n const [a0, a1] = angles[side];\n const p0x = cx + rx * Math.cos(a0), p0y = cy + ry * Math.sin(a0);\n const p3x = cx + rx * Math.cos(a1), p3y = cy + ry * Math.sin(a1);\n segs.push({ type: 'M', x: p0x, y: p0y });\n cubic(\n p0x - BEZIER_K * rx * Math.sin(a0), p0y + BEZIER_K * ry * Math.cos(a0),\n p3x + BEZIER_K * rx * Math.sin(a1), p3y - BEZIER_K * ry * Math.cos(a1),\n p3x, p3y,\n );\n return segs;\n }\n\n if (type === 'shapeDocument') {\n const curve = h * 0.15;\n if (side === 'top') {\n segs.push({ type: 'M', x: 0, y: 0 });\n line(w, 0);\n } else if (side === 'right') {\n segs.push({ type: 'M', x: w, y: 0 });\n line(w, h - curve);\n } else if (side === 'bottom') {\n segs.push({ type: 'M', x: w, y: h - curve });\n cubic(w * 0.75, h - curve * 2, w * 0.25, h, 0, h - curve);\n } else {\n segs.push({ type: 'M', x: 0, y: h - curve });\n line(0, 0);\n }\n return segs;\n }\n\n // Quadrilaterals (rect / diamond / parallelogram / trapezoid).\n let v0: { x: number; y: number }, v1: { x: number; y: number }, v2: { x: number; y: number }, v3: { x: number; y: number };\n if (type === 'shapeDiamond') {\n const cx = w / 2, cy = h / 2;\n v0 = { x: cx, y: 0 }; v1 = { x: w, y: cy }; v2 = { x: cx, y: h }; v3 = { x: 0, y: cy };\n } else if (type === 'shapeParallelogram') {\n const skew = w * 0.2;\n v0 = { x: skew, y: 0 }; v1 = { x: w, y: 0 }; v2 = { x: w - skew, y: h }; v3 = { x: 0, y: h };\n } else if (type === 'shapeTrapezoid') {\n const inset = w * 0.15;\n v0 = { x: inset, y: 0 }; v1 = { x: w - inset, y: 0 }; v2 = { x: w, y: h }; v3 = { x: 0, y: h };\n } else {\n v0 = { x: 0, y: 0 }; v1 = { x: w, y: 0 }; v2 = { x: w, y: h }; v3 = { x: 0, y: h };\n }\n\n const edges: Record<BorderSideName, [{ x: number; y: number }, { x: number; y: number }]> = {\n top: [v0, v1],\n right: [v1, v2],\n bottom: [v2, v3],\n left: [v3, v0],\n };\n const [a, b] = edges[side];\n segs.push({ type: 'M', x: a.x, y: a.y });\n line(b.x, b.y);\n return segs;\n}\n\n/** Draw the four sides of a node independently, honoring per-side color /\n * width / visibility overrides (falling back to the node's defaults). The\n * node's `borderStyle` (solid / dashed / dotted / dynamic) applies to every\n * side. `defaultColor` is the node's (already theme-resolved) stroke. */\nexport function drawBorderSides(\n g: Graphics,\n type: string,\n width: number,\n height: number,\n sides: FlowBorderSides | undefined,\n defaultColor: string,\n defaultWidth: number,\n borderStyle: string | undefined,\n dashOffset: number,\n): void {\n if (borderStyle === 'none') return;\n for (const name of BORDER_SIDE_NAMES) {\n const side: FlowBorderSideOverride | undefined = sides?.[name];\n if (side?.visible === false) continue;\n const color = resolveThemeColor(side?.color, defaultColor) || defaultColor;\n const strokeWidth = side?.width ?? defaultWidth;\n if (!color || color === 'transparent' || !(strokeWidth > 0)) continue;\n const segs = buildBorderSideSegments(type, width, height, name);\n const dash = parseDash(borderStyle, strokeWidth);\n if (dash) {\n const offset = borderStyle === 'dynamic' ? dashOffset : 0;\n drawDashedPath(g, segs, dash, offset);\n g.stroke({ color, width: strokeWidth, cap: 'round' as const });\n } else {\n for (const seg of segs) {\n switch (seg.type) {\n case 'M': g.moveTo(seg.x, seg.y); break;\n case 'L': g.lineTo(seg.x, seg.y); break;\n case 'C': g.bezierCurveTo(seg.cp1x!, seg.cp1y!, seg.cp2x!, seg.cp2y!, seg.x, seg.y); break;\n case 'Q': g.quadraticCurveTo(seg.cp1x!, seg.cp1y!, seg.x, seg.y); break;\n }\n }\n g.stroke({ color, width: strokeWidth });\n }\n }\n}\n\n/** Lookup table mapping shape type to draw function */\nexport const shapeDrawers: Record<string, (g: Graphics, o: ShapeDrawOptions) => void> = {\n shapeRect: drawRect,\n shapeRoundRect: drawRoundRect,\n shapeEllipse: drawEllipse,\n shapeDiamond: drawDiamond,\n shapeDocument: drawDocument,\n shapeParallelogram: drawParallelogram,\n shapeTriangle: drawTriangle,\n shapeTrapezoid: drawTrapezoid,\n shapePentagon: drawPentagon,\n shapeHexagon: drawHexagon,\n shapeStar: drawStar,\n shapeHexagram: drawHexagram,\n shapeRightTriangle: drawRightTriangle,\n shapeCorner: drawCorner,\n textLabel: drawRect,\n flowGroup: drawFlowGroup,\n geometryGroup: drawGeometryGroup,\n shapeSvg: drawRoundRect,\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AIPanel.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/AIPanel.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport Button from '../../../Button';\nimport Input from '../../../Input';\nimport Select from '../../../Select';\nimport Label from '../../../Label';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowAI } from '../context/FlowAIContext';\nimport { completeAIChatStream } from '../nodes/aiClient';\nimport { ROOT_CANVAS_ID, DEFAULT_NODE_DATA, DEFAULT_EDGE_DATA } from '../constants';\nimport type { FlowAIConfig, FlowDocument } from '../types';\n\n/**\n * System prompt that constrains the model to emit a FlowDocument JSON so the\n * result can be parsed and loaded directly onto the canvas.\n */\nconst SYSTEM_PROMPT = `You are a diagramming assistant for a flowchart editor. Convert the user's request (a description, or an uploaded diagram image to reproduce) into a flow document.\n\nReply with ONE fenced \\`\\`\\`json code block and nothing else. The JSON must match:\n{\n \"canvases\": {\n \"root\": {\n \"nodes\": [\n { \"id\": \"n1\", \"type\": \"shapeRoundRect\", \"position\": {\"x\": 80, \"y\": 80}, \"width\": 160, \"height\": 64,\n \"data\": { \"label\": \"Start\" } }\n ],\n \"edges\": [\n { \"id\": \"e1\", \"source\": \"n1\", \"target\": \"n2\", \"type\": \"smoothstep\",\n \"data\": { \"labelText\": \"yes\" } }\n ],\n \"lines\": []\n }\n },\n \"stack\": [\"root\"]\n}\n\nRules:\n- Node \"type\" is one of: shapeRect, shapeRoundRect, shapeEllipse, shapeDiamond, shapeParallelogram, shapeDocument, shapeHexagon. Use shapeDiamond for decisions, shapeRoundRect for processes, shapeEllipse for start/end.\n- Give every node a unique \"id\". Every edge \"source\"/\"target\" must reference an existing node id.\n- Lay nodes out on a readable grid (top-to-bottom or left-to-right), spacing ~180px, no overlaps. Widths ~140-180, heights ~56-72 (diamonds ~120x100).\n- Put a short \"label\" on each node. Optional edge label goes in data.labelText.\n- Do NOT include colors; the editor themes them automatically.\n- Output ONLY the JSON code block.`;\n\n/** Extract and parse the first JSON object from an AI reply. */\nfunction parseFlowJson(text: string): FlowDocument | null {\n let raw = text.trim();\n const fence = /```(?:json)?\\s*([\\s\\S]*?)```/i.exec(raw);\n if (fence) raw = fence[1].trim();\n else {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start >= 0 && end > start) raw = raw.slice(start, end + 1);\n }\n try {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== 'object' || !parsed.canvases) return null;\n return parsed as FlowDocument;\n } catch {\n return null;\n }\n}\n\n/** Normalize an AI-produced document: fill defaults, ensure a root canvas. */\nfunction normalizeAIDocument(doc: FlowDocument): FlowDocument {\n const canvases = doc.canvases ?? {};\n const rootKey = doc.stack?.[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = canvases[rootKey] ?? canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n const nodes = (canvas.nodes ?? []).map((n: any, i: number) => ({\n id: n.id ?? `n${i + 1}`,\n type: n.type ?? 'shapeRoundRect',\n position: { x: Number(n.position?.x ?? 80), y: Number(n.position?.y ?? 80 + i * 120) },\n width: Number(n.width ?? 160),\n height: Number(n.height ?? 64),\n zIndex: n.zIndex ?? i,\n data: { ...DEFAULT_NODE_DATA, ...(n.data ?? {}), label: n.data?.label ?? n.label ?? 'Node' },\n }));\n const nodeById = new Map<string, any>(nodes.map((n) => [n.id, n]));\n const edges = (canvas.edges ?? []).map((e: any, i: number) => ({\n id: e.id ?? `e${i + 1}`,\n source: e.source,\n target: e.target,\n type: e.type ?? 'smoothstep',\n data: { ...DEFAULT_EDGE_DATA, ...(e.data ?? {}) },\n })).filter((e: any) => e.source && e.target)\n .map((e: any) => pinEdgeToSideMidpoints(e, nodeById));\n return {\n canvases: { [ROOT_CANVAS_ID]: { nodes, edges, lines: [] } },\n stack: [ROOT_CANVAS_ID],\n };\n}\n\n/**\n * Pin an AI-generated edge to the midpoint handles of the facing node sides\n * (`r_0.5` / `l_0.5` / `t_0.5` / `b_0.5`) so connections attach at the center\n * of each side instead of sliding along the side toward the other node.\n */\nfunction pinEdgeToSideMidpoints(edge: any, nodeById: Map<string, any>): any {\n const s = nodeById.get(edge.source);\n const t = nodeById.get(edge.target);\n if (!s || !t || s === t) return edge;\n const dx = (t.position.x + t.width / 2) - (s.position.x + s.width / 2);\n const dy = (t.position.y + t.height / 2) - (s.position.y + s.height / 2);\n if (Math.abs(dx) >= Math.abs(dy)) {\n const forward = dx >= 0;\n return {\n ...edge,\n sourceHandle: forward ? 'r_0.5' : 'l_0.5',\n targetHandle: forward ? 'l_0.5' : 'r_0.5',\n };\n }\n const forward = dy >= 0;\n return {\n ...edge,\n sourceHandle: forward ? 'b_0.5' : 't_0.5',\n targetHandle: forward ? 't_0.5' : 'b_0.5',\n };\n}\n\nconst PROTOCOL_OPTIONS = [\n { value: 'openai', label: 'OpenAI 兼容' },\n { value: 'anthropic', label: 'Anthropic' },\n];\n\n/** Char count at which the simulated progress bar saturates (99%). */\nconst PROGRESS_FULL_CHARS = 20000;\n\nexport function AIPanelContent() {\n const { setDoc } = useFlowContext();\n const { aiConfig, setAIConfig, showAIConfig } = useFlowAI();\n\n const [prompt, setPrompt] = useState('');\n const [imageDataUrl, setImageDataUrl] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [status, setStatus] = useState<string | null>(null);\n const [streamOpen, setStreamOpen] = useState(false);\n const [finished, setFinished] = useState(false);\n const [pendingDoc, setPendingDoc] = useState<FlowDocument | null>(null);\n const [displayLen, setDisplayLen] = useState(0);\n const abortRef = useRef<AbortController | null>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const streamBodyRef = useRef<HTMLPreElement>(null);\n const streamTailRef = useRef<HTMLPreElement>(null);\n /** Full text received from the model so far (grows on every SSE delta). */\n const targetRef = useRef('');\n\n const updateConfig = useCallback((patch: Partial<FlowAIConfig>) => {\n setAIConfig({ ...aiConfig, ...patch });\n }, [aiConfig, setAIConfig]);\n\n const onPickImage = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => setImageDataUrl(reader.result as string);\n reader.readAsDataURL(file);\n }, []);\n\n // Accept an image pasted from the clipboard (Ctrl/Cmd+V) anywhere in the panel\n // or into the textarea. Falls through to normal text paste otherwise.\n const onPaste = useCallback((e: React.ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items) return;\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n const file = item.getAsFile();\n if (file) {\n e.preventDefault();\n const reader = new FileReader();\n reader.onload = () => setImageDataUrl(reader.result as string);\n reader.readAsDataURL(file);\n return;\n }\n }\n }\n }, []);\n\n // Progressive reveal: SSE deltas land in `targetRef` (often several chunks\n // per network read, which React would batch into a single paint), and this\n // timer types the text out with an exponential catch-up so the panel always\n // shows the reply growing character-by-character.\n useEffect(() => {\n const timer = window.setInterval(() => {\n setDisplayLen((len) => {\n const target = targetRef.current.length;\n if (len >= target) return len;\n return len + Math.max(8, Math.ceil((target - len) / 8));\n });\n }, 40);\n return () => window.clearInterval(timer);\n }, []);\n\n const streamText = targetRef.current.slice(0, displayLen);\n\n // Keep the streaming output pinned to the latest chunk while visible.\n useEffect(() => {\n const el = streamBodyRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n const tail = streamTailRef.current;\n if (tail) tail.scrollTop = tail.scrollHeight;\n }, [streamText, streamOpen]);\n\n const generate = useCallback(async () => {\n if (busy) return;\n if (!aiConfig.gateway || !aiConfig.model) {\n setError('请先配置 AI 接口地址与模型');\n return;\n }\n if (!prompt.trim() && !imageDataUrl) {\n setError('请输入需求描述,或上传一张流程图');\n return;\n }\n setError(null);\n setStatus('正在生成…');\n targetRef.current = '';\n setDisplayLen(0);\n setFinished(false);\n setPendingDoc(null);\n setBusy(true);\n const ac = new AbortController();\n abortRef.current = ac;\n try {\n const text = await completeAIChatStream(\n aiConfig,\n prompt.trim() || '请根据这张图片复刻出对应的流程图。',\n {\n imageDataUrl: imageDataUrl ?? undefined,\n systemPrompt: SYSTEM_PROMPT,\n signal: ac.signal,\n onDelta: (accumulated) => { targetRef.current = accumulated; },\n },\n );\n setFinished(true);\n const parsed = parseFlowJson(text);\n if (!parsed) {\n setError('AI 返回内容无法解析为流程图,请重试或调整描述');\n setStatus(null);\n return;\n }\n setPendingDoc(normalizeAIDocument(parsed));\n setStatus(null);\n } catch (err: any) {\n if (err?.name !== 'AbortError') setError(err?.message ?? '生成失败');\n setStatus(null);\n } finally {\n setBusy(false);\n abortRef.current = null;\n }\n }, [busy, aiConfig, prompt, imageDataUrl]);\n\n const cancel = useCallback(() => abortRef.current?.abort(), []);\n\n /** Merge the generated canvas into the current canvas, remapping ids. */\n const applyInsert = useCallback(() => {\n if (!pendingDoc) return;\n const gen = pendingDoc.canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n setDoc((prev) => {\n const canvasId = prev.stack[prev.stack.length - 1] ?? ROOT_CANVAS_ID;\n const cur = prev.canvases[canvasId] ?? { nodes: [], edges: [], lines: [] };\n const used = new Set([\n ...cur.nodes.map((n) => n.id),\n ...cur.edges.map((e) => e.id),\n ...cur.lines.map((l) => l.id),\n ]);\n const fresh = (id: string) => {\n let next = id;\n let i = 1;\n while (used.has(next)) next = `${id}_${i++}`;\n used.add(next);\n return next;\n };\n const idMap = new Map<string, string>();\n const nodes = gen.nodes.map((n) => {\n const id = fresh(n.id);\n idMap.set(n.id, id);\n return { ...n, id };\n });\n const edges = gen.edges.map((e) => ({\n ...e,\n id: fresh(e.id),\n source: idMap.get(e.source) ?? e.source,\n target: idMap.get(e.target) ?? e.target,\n }));\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [canvasId]: { nodes: [...cur.nodes, ...nodes], edges: [...cur.edges, ...edges], lines: cur.lines },\n },\n };\n });\n setPendingDoc(null);\n setStatus('已插入流程图');\n }, [pendingDoc, setDoc]);\n\n /** Clear the current canvas, then place the generated content onto it. */\n const applyReplace = useCallback(() => {\n if (!pendingDoc) return;\n const gen = pendingDoc.canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n setDoc((prev) => {\n const canvasId = prev.stack[prev.stack.length - 1] ?? ROOT_CANVAS_ID;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [canvasId]: { nodes: gen.nodes, edges: gen.edges, lines: [] },\n },\n };\n });\n setPendingDoc(null);\n setStatus('已替换画布');\n }, [pendingDoc, setDoc]);\n\n const charCount = streamText.length;\n const fullyRevealed = charCount >= targetRef.current.length;\n const progress = finished && fullyRevealed\n ? 100\n : Math.min(99, Math.floor((charCount / PROGRESS_FULL_CHARS) * 99));\n\n return (\n <div className=\"flow-ai-panel\" onPaste={onPaste}>\n {showAIConfig && (\n <div className=\"flow-ai-section\">\n <div className=\"flow-ai-section-title\">模型配置</div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">协议</Label>\n <Select\n options={PROTOCOL_OPTIONS}\n value={aiConfig.protocol}\n onChange={(v) => updateConfig({ protocol: v as FlowAIConfig['protocol'] })}\n style={{ fontSize: 12 }}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">接口地址</Label>\n <Input\n size=\"xs\"\n value={aiConfig.gateway}\n placeholder=\"https://api.moonshot.cn/v1\"\n onChange={(e) => updateConfig({ gateway: e.target.value })}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">模型</Label>\n <Input\n size=\"xs\"\n value={aiConfig.model}\n placeholder=\"gpt-4o-mini\"\n onChange={(e) => updateConfig({ model: e.target.value })}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">API Key</Label>\n <Input\n size=\"xs\"\n type=\"password\"\n value={aiConfig.apiKey ?? ''}\n placeholder=\"sk-…\"\n onChange={(e) => updateConfig({ apiKey: e.target.value })}\n />\n </div>\n </div>\n )}\n\n <div className=\"flow-ai-section\">\n <div className=\"flow-ai-section-title\">生成流程图</div>\n <textarea\n className=\"flow-ai-textarea\"\n value={prompt}\n placeholder=\"描述你想要的流程,例如:用户注册流程,包含邮箱校验、发送验证码、创建账号等步骤(可直接粘贴图片)\"\n onChange={(e) => setPrompt(e.target.value)}\n onPaste={onPaste}\n onPointerDown={(e) => e.stopPropagation()}\n />\n\n <div className=\"flow-ai-image-row\">\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: 'none' }}\n onChange={onPickImage}\n />\n {imageDataUrl ? (\n <div className=\"flow-ai-image-preview\">\n <img src={imageDataUrl} alt=\"参考图\" />\n <button\n type=\"button\"\n className=\"flow-ai-image-remove\"\n title=\"移除图片\"\n onClick={() => setImageDataUrl(null)}\n >×</button>\n </div>\n ) : (\n <Button size=\"xs\" variant=\"ghost\" onClick={() => fileRef.current?.click()}>\n 上传流程图图片\n </Button>\n )}\n <span className=\"flow-ai-hint\">或粘贴图片 (Ctrl/⌘+V)</span>\n </div>\n\n <div className=\"flow-ai-actions\">\n {busy ? (\n <Button size=\"xs\" variant=\"ghost\" onClick={cancel}>停止</Button>\n ) : (\n <Button size=\"xs\" variant=\"primary\" onClick={generate}>生成流程图</Button>\n )}\n </div>\n\n {(busy || streamText) && (\n <div className=\"flow-ai-stream\">\n <div className=\"flow-ai-progress\">\n <div className=\"flow-ai-progress-track\">\n <div className=\"flow-ai-progress-bar\" style={{ width: `${progress}%` }} />\n </div>\n <span className=\"flow-ai-progress-label\">{progress}%</span>\n </div>\n <button\n type=\"button\"\n className=\"flow-ai-stream-header\"\n onClick={() => setStreamOpen((open) => !open)}\n >\n <span className={`flow-ai-stream-chevron${streamOpen ? ' flow-ai-stream-chevron--open' : ''}`}>▸</span>\n <span>返回内容</span>\n <span className=\"flow-ai-stream-count\">{charCount.toLocaleString()} 字符</span>\n </button>\n {streamOpen ? (\n <pre ref={streamBodyRef} className=\"flow-ai-stream-body\">{streamText || '等待返回…'}</pre>\n ) : (\n streamText && <pre ref={streamTailRef} className=\"flow-ai-stream-tail\">{streamText}</pre>\n )}\n </div>\n )}\n\n {status && !error && <div className=\"flow-ai-status\">{status}</div>}\n {error && <div className=\"flow-media-error\">{error}</div>}\n </div>\n\n {pendingDoc && (\n <div className=\"flow-ai-dialog-overlay\" onClick={() => setPendingDoc(null)}>\n <div\n className=\"flow-ai-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"流程图已生成\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flow-ai-dialog-title\">流程图已生成</div>\n <div className=\"flow-ai-dialog-desc\">\n 插入:将生成内容追加到当前画布;替换:清空当前画布后再插入。\n </div>\n <div className=\"flow-ai-dialog-actions\">\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setPendingDoc(null)}>取消</Button>\n <Button size=\"xs\" variant=\"neutral\" outline onClick={applyInsert}>插入</Button>\n <Button size=\"xs\" variant=\"primary\" onClick={applyReplace}>替换</Button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AIPanel.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/AIPanel.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport Button from '../../../Button';\nimport Input from '../../../Input';\nimport Select from '../../../Select';\nimport Label from '../../../Label';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowAI } from '../context/FlowAIContext';\nimport { completeAIChatStream } from '../nodes/aiClient';\nimport { ROOT_CANVAS_ID, DEFAULT_NODE_DATA, DEFAULT_EDGE_DATA } from '../constants';\nimport type { FlowAIConfig, FlowDocument } from '../types';\n\n/**\n * System prompt that constrains the model to emit a FlowDocument JSON so the\n * result can be parsed and loaded directly onto the canvas.\n */\nconst SYSTEM_PROMPT = `You are a diagramming assistant for a flowchart editor. Convert the user's request (a description, or an uploaded diagram image to reproduce) into a flow document.\n\nReply with ONE fenced \\`\\`\\`json code block and nothing else. The JSON must match:\n{\n \"canvases\": {\n \"root\": {\n \"nodes\": [\n { \"id\": \"n1\", \"type\": \"shapeRoundRect\", \"position\": {\"x\": 80, \"y\": 80}, \"width\": 160, \"height\": 64,\n \"data\": { \"label\": \"Start\" } }\n ],\n \"edges\": [\n { \"id\": \"e1\", \"source\": \"n1\", \"target\": \"n2\", \"type\": \"smoothstep\",\n \"data\": { \"labelText\": \"yes\" } }\n ],\n \"lines\": []\n }\n },\n \"stack\": [\"root\"]\n}\n\nRules:\n- Node \"type\" is one of: shapeRect, shapeRoundRect, shapeEllipse, shapeDiamond, shapeParallelogram, shapeDocument, shapeHexagon. Use shapeDiamond for decisions, shapeRoundRect for processes, shapeEllipse for start/end.\n- Give every node a unique \"id\". Every edge \"source\"/\"target\" must reference an existing node id.\n- Lay nodes out on a readable grid (top-to-bottom or left-to-right), spacing ~180px, no overlaps. Widths ~140-180, heights ~56-72 (diamonds ~120x100).\n- Put a short \"label\" on each node. Optional edge label goes in data.labelText.\n- Do NOT include colors; the editor themes them automatically.\n- Output ONLY the JSON code block.`;\n\n/** Extract and parse the first JSON object from an AI reply. */\nfunction parseFlowJson(text: string): FlowDocument | null {\n let raw = text.trim();\n const fence = /```(?:json)?\\s*([\\s\\S]*?)```/i.exec(raw);\n if (fence) raw = fence[1].trim();\n else {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start >= 0 && end > start) raw = raw.slice(start, end + 1);\n }\n try {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== 'object' || !parsed.canvases) return null;\n return parsed as FlowDocument;\n } catch {\n return null;\n }\n}\n\n/** Normalize an AI-produced document: fill defaults, ensure a root canvas. */\nfunction normalizeAIDocument(doc: FlowDocument): FlowDocument {\n const canvases = doc.canvases ?? {};\n const rootKey = doc.stack?.[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = canvases[rootKey] ?? canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n const nodes = (canvas.nodes ?? []).map((n: any, i: number) => ({\n id: n.id ?? `n${i + 1}`,\n type: n.type ?? 'shapeRoundRect',\n position: { x: Number(n.position?.x ?? 80), y: Number(n.position?.y ?? 80 + i * 120) },\n width: Number(n.width ?? 160),\n height: Number(n.height ?? 64),\n zIndex: n.zIndex ?? i,\n data: { ...DEFAULT_NODE_DATA, ...(n.data ?? {}), label: n.data?.label ?? n.label ?? 'Node' },\n }));\n const nodeById = new Map<string, any>(nodes.map((n) => [n.id, n]));\n const edges = (canvas.edges ?? []).map((e: any, i: number) => ({\n id: e.id ?? `e${i + 1}`,\n source: e.source,\n target: e.target,\n type: e.type ?? 'smoothstep',\n data: { ...DEFAULT_EDGE_DATA, ...(e.data ?? {}) },\n })).filter((e: any) => e.source && e.target)\n .map((e: any) => pinEdgeToSideMidpoints(e, nodeById));\n return {\n canvases: { [ROOT_CANVAS_ID]: { nodes, edges, lines: [] } },\n stack: [ROOT_CANVAS_ID],\n };\n}\n\n/**\n * Pin an AI-generated edge to the midpoint handles of the facing node sides\n * (`r_0.5` / `l_0.5` / `t_0.5` / `b_0.5`) so connections attach at the center\n * of each side instead of sliding along the side toward the other node.\n */\nfunction pinEdgeToSideMidpoints(edge: any, nodeById: Map<string, any>): any {\n const s = nodeById.get(edge.source);\n const t = nodeById.get(edge.target);\n if (!s || !t || s === t) return edge;\n const dx = (t.position.x + t.width / 2) - (s.position.x + s.width / 2);\n const dy = (t.position.y + t.height / 2) - (s.position.y + s.height / 2);\n if (Math.abs(dx) >= Math.abs(dy)) {\n const forward = dx >= 0;\n return {\n ...edge,\n sourceHandle: forward ? 'r_0.5' : 'l_0.5',\n targetHandle: forward ? 'l_0.5' : 'r_0.5',\n };\n }\n const forward = dy >= 0;\n return {\n ...edge,\n sourceHandle: forward ? 'b_0.5' : 't_0.5',\n targetHandle: forward ? 't_0.5' : 'b_0.5',\n };\n}\n\nconst PROTOCOL_OPTIONS = [\n { value: 'openai', label: 'OpenAI 兼容' },\n { value: 'anthropic', label: 'Anthropic' },\n];\n\n/** Char count at which the simulated progress bar saturates (99%). */\nconst PROGRESS_FULL_CHARS = 20000;\n\nexport function AIPanelContent() {\n const { setDoc } = useFlowContext();\n const { aiConfig, setAIConfig, showAIConfig } = useFlowAI();\n\n const [prompt, setPrompt] = useState('');\n const [imageDataUrl, setImageDataUrl] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [status, setStatus] = useState<string | null>(null);\n const [streamOpen, setStreamOpen] = useState(false);\n const [finished, setFinished] = useState(false);\n const [pendingDoc, setPendingDoc] = useState<FlowDocument | null>(null);\n const [displayLen, setDisplayLen] = useState(0);\n const abortRef = useRef<AbortController | null>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const streamBodyRef = useRef<HTMLPreElement>(null);\n const streamTailRef = useRef<HTMLPreElement>(null);\n /** Full text received from the model so far (grows on every SSE delta). */\n const targetRef = useRef('');\n\n const updateConfig = useCallback((patch: Partial<FlowAIConfig>) => {\n setAIConfig({ ...aiConfig, ...patch });\n }, [aiConfig, setAIConfig]);\n\n const onPickImage = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => setImageDataUrl(reader.result as string);\n reader.readAsDataURL(file);\n }, []);\n\n // Accept an image pasted from the clipboard (Ctrl/Cmd+V) anywhere in the panel\n // or into the textarea. Falls through to normal text paste otherwise.\n const onPaste = useCallback((e: React.ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items) return;\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n const file = item.getAsFile();\n if (file) {\n e.preventDefault();\n const reader = new FileReader();\n reader.onload = () => setImageDataUrl(reader.result as string);\n reader.readAsDataURL(file);\n return;\n }\n }\n }\n }, []);\n\n // Progressive reveal: SSE deltas land in `targetRef` (often several chunks\n // per network read, which React would batch into a single paint), and this\n // timer types the text out with an exponential catch-up so the panel always\n // shows the reply growing character-by-character.\n useEffect(() => {\n const timer = window.setInterval(() => {\n setDisplayLen((len) => {\n const target = targetRef.current.length;\n if (len >= target) return len;\n return len + Math.max(8, Math.ceil((target - len) / 8));\n });\n }, 40);\n return () => window.clearInterval(timer);\n }, []);\n\n const streamText = targetRef.current.slice(0, displayLen);\n\n // Keep the streaming output pinned to the latest chunk while visible.\n useEffect(() => {\n const el = streamBodyRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n const tail = streamTailRef.current;\n if (tail) tail.scrollTop = tail.scrollHeight;\n }, [streamText, streamOpen]);\n\n const generate = useCallback(async () => {\n if (busy) return;\n if (!aiConfig.gateway || !aiConfig.model) {\n setError('请先配置 AI 接口地址与模型');\n return;\n }\n if (!prompt.trim() && !imageDataUrl) {\n setError('请输入需求描述,或上传一张流程图');\n return;\n }\n setError(null);\n setStatus('正在生成…');\n targetRef.current = '';\n setDisplayLen(0);\n setFinished(false);\n setPendingDoc(null);\n setBusy(true);\n const ac = new AbortController();\n abortRef.current = ac;\n try {\n const text = await completeAIChatStream(\n aiConfig,\n prompt.trim() || '请根据这张图片复刻出对应的流程图。',\n {\n imageDataUrl: imageDataUrl ?? undefined,\n systemPrompt: SYSTEM_PROMPT,\n signal: ac.signal,\n onDelta: (accumulated) => { targetRef.current = accumulated; },\n },\n );\n setFinished(true);\n const parsed = parseFlowJson(text);\n if (!parsed) {\n setError('AI 返回内容无法解析为流程图,请重试或调整描述');\n setStatus(null);\n return;\n }\n setPendingDoc(normalizeAIDocument(parsed));\n setStatus(null);\n } catch (err: any) {\n if (err?.name !== 'AbortError') setError(err?.message ?? '生成失败');\n setStatus(null);\n } finally {\n setBusy(false);\n abortRef.current = null;\n }\n }, [busy, aiConfig, prompt, imageDataUrl]);\n\n const cancel = useCallback(() => abortRef.current?.abort(), []);\n\n /** Merge the generated canvas into the current canvas, remapping ids. */\n const applyInsert = useCallback(() => {\n if (!pendingDoc) return;\n const gen = pendingDoc.canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n setDoc((prev) => {\n const canvasId = prev.stack[prev.stack.length - 1] ?? ROOT_CANVAS_ID;\n const cur = prev.canvases[canvasId] ?? { nodes: [], edges: [], lines: [] };\n const used = new Set([\n ...cur.nodes.map((n) => n.id),\n ...cur.edges.map((e) => e.id),\n ...cur.lines.map((l) => l.id),\n ]);\n const fresh = (id: string) => {\n let next = id;\n let i = 1;\n while (used.has(next)) next = `${id}_${i++}`;\n used.add(next);\n return next;\n };\n const idMap = new Map<string, string>();\n const nodes = gen.nodes.map((n) => {\n const id = fresh(n.id);\n idMap.set(n.id, id);\n return { ...n, id };\n });\n const edges = gen.edges.map((e) => ({\n ...e,\n id: fresh(e.id),\n source: idMap.get(e.source) ?? e.source,\n target: idMap.get(e.target) ?? e.target,\n }));\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [canvasId]: { nodes: [...cur.nodes, ...nodes], edges: [...cur.edges, ...edges], lines: cur.lines },\n },\n };\n });\n setPendingDoc(null);\n setStatus('已插入流程图');\n }, [pendingDoc, setDoc]);\n\n /** Clear the current canvas, then place the generated content onto it. */\n const applyReplace = useCallback(() => {\n if (!pendingDoc) return;\n const gen = pendingDoc.canvases[ROOT_CANVAS_ID] ?? { nodes: [], edges: [], lines: [] };\n setDoc((prev) => {\n const canvasId = prev.stack[prev.stack.length - 1] ?? ROOT_CANVAS_ID;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [canvasId]: { nodes: gen.nodes, edges: gen.edges, lines: [] },\n },\n };\n });\n setPendingDoc(null);\n setStatus('已替换画布');\n }, [pendingDoc, setDoc]);\n\n const charCount = streamText.length;\n const fullyRevealed = charCount >= targetRef.current.length;\n const progress = finished && fullyRevealed\n ? 100\n : Math.min(99, Math.floor((charCount / PROGRESS_FULL_CHARS) * 99));\n\n return (\n <div className=\"flow-ai-panel\" onPaste={onPaste}>\n {showAIConfig && (\n <div className=\"flow-ai-section\">\n <div className=\"flow-ai-section-title\">模型配置</div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">协议</Label>\n <Select\n options={PROTOCOL_OPTIONS}\n value={aiConfig.protocol}\n onChange={(v) => updateConfig({ protocol: v as FlowAIConfig['protocol'] })}\n style={{ fontSize: 12 }}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">接口地址</Label>\n <Input\n size=\"xs\"\n value={aiConfig.gateway}\n placeholder=\"https://api.moonshot.cn/v1\"\n onChange={(e) => updateConfig({ gateway: e.target.value })}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">模型</Label>\n <Input\n size=\"xs\"\n value={aiConfig.model}\n placeholder=\"gpt-4o-mini\"\n onChange={(e) => updateConfig({ model: e.target.value })}\n />\n </div>\n <div className=\"flow-inspector-row\">\n <Label size=\"xs\" className=\"flow-inspector-label\">API Key</Label>\n <Input\n size=\"xs\"\n type=\"password\"\n value={aiConfig.apiKey ?? ''}\n placeholder=\"sk-…\"\n onChange={(e) => updateConfig({ apiKey: e.target.value })}\n />\n </div>\n </div>\n )}\n\n <div className=\"flow-ai-section\">\n <div className=\"flow-ai-section-title\">生成流程图</div>\n <textarea\n className=\"flow-ai-textarea\"\n value={prompt}\n placeholder=\"描述你想要的流程,例如:用户注册流程,包含邮箱校验、发送验证码、创建账号等步骤(可直接粘贴图片)\"\n onChange={(e) => setPrompt(e.target.value)}\n onPaste={onPaste}\n onPointerDown={(e) => e.stopPropagation()}\n />\n\n <div className=\"flow-ai-image-row\">\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: 'none' }}\n onChange={onPickImage}\n />\n {imageDataUrl ? (\n <div className=\"flow-ai-image-preview\">\n <img src={imageDataUrl} alt=\"参考图\" />\n <button\n type=\"button\"\n className=\"flow-ai-image-remove\"\n title=\"移除图片\"\n onClick={() => setImageDataUrl(null)}\n >×</button>\n </div>\n ) : (\n <Button size=\"xs\" variant=\"ghost\" onClick={() => fileRef.current?.click()}>\n 上传流程图图片\n </Button>\n )}\n <span className=\"flow-ai-hint\">或粘贴图片 (Ctrl/⌘+V)</span>\n </div>\n\n <div className=\"flow-ai-actions\">\n {busy ? (\n <Button size=\"xs\" variant=\"ghost\" onClick={cancel}>停止</Button>\n ) : (\n <Button size=\"xs\" variant=\"primary\" onClick={generate}>生成流程图</Button>\n )}\n </div>\n\n {(busy || streamText) && (\n <div className=\"flow-ai-stream\">\n <div className=\"flow-ai-progress\">\n <div className=\"flow-ai-progress-track\">\n <div className=\"flow-ai-progress-bar\" style={{ width: `${progress}%` }} />\n </div>\n <span className=\"flow-ai-progress-label\">{progress}%</span>\n </div>\n <button\n type=\"button\"\n className=\"flow-ai-stream-header\"\n onClick={() => setStreamOpen((open) => !open)}\n >\n <span className={`flow-ai-stream-chevron${streamOpen ? ' flow-ai-stream-chevron--open' : ''}`}>▸</span>\n <span>返回内容</span>\n <span className=\"flow-ai-stream-count\">{charCount.toLocaleString()} 字符</span>\n </button>\n {streamOpen ? (\n <pre ref={streamBodyRef} className=\"flow-ai-stream-body\">{streamText || '等待返回…'}</pre>\n ) : (\n streamText && <pre ref={streamTailRef} className=\"flow-ai-stream-tail\">{streamText}</pre>\n )}\n </div>\n )}\n\n {status && !error && <div className=\"flow-ai-status\">{status}</div>}\n {error && <div className=\"flow-media-error\">{error}</div>}\n </div>\n\n {pendingDoc && (\n <div className=\"flow-ai-dialog-overlay\" onClick={() => setPendingDoc(null)}>\n <div\n className=\"flow-ai-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"流程图已生成\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flow-ai-dialog-title\">流程图已生成</div>\n <div className=\"flow-ai-dialog-desc\">\n 插入:将生成内容追加到当前画布;替换:清空当前画布后再插入。\n </div>\n <div className=\"flow-ai-dialog-actions\">\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setPendingDoc(null)}>取消</Button>\n <Button size=\"xs\" variant=\"neutral\" outline onClick={applyInsert}>插入</Button>\n <Button size=\"xs\" variant=\"primary\" onClick={applyReplace}>替换</Button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/Breadcrumb.tsx"],"sourcesContent":["import React from 'react';\nimport Button from '../../../Button';\nimport { useFlowContext } from '../context/FlowContext';\nimport { ROOT_CANVAS_ID } from '../constants';\n\nfunction findNodeLabel(doc: ReturnType<typeof useFlowContext>['doc'], canvasId: string): string {\n if (canvasId === ROOT_CANVAS_ID) return 'Root';\n for (const [, canvas] of Object.entries(doc.canvases)) {\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId === canvasId) {\n return node.data.label || node.type;\n }\n }\n }\n return canvasId;\n}\n\nexport default function Breadcrumb() {\n const { doc, setDoc, setSelection } = useFlowContext();\n const { stack } = doc;\n\n if (stack.length <= 1) return null;\n\n const handleClick = (index: number) => {\n if (index === stack.length - 1) return;\n setDoc(prev => ({\n ...prev,\n stack: prev.stack.slice(0, index + 1),\n }));\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n };\n\n return (\n <div className=\"flow-breadcrumb\">\n {stack.map((canvasId, i) => {\n const label = findNodeLabel(doc, canvasId);\n const isLast = i === stack.length - 1;\n return (\n <React.Fragment key={canvasId}>\n {i > 0 && <span className=\"flow-breadcrumb-sep\">›</span>}\n <Button\n variant=\"ghost\"\n size=\"xs\"\n className={`flow-breadcrumb-item ${isLast ? 'flow-breadcrumb-item--active' : ''}`}\n onClick={() => handleClick(i)}\n disabled={isLast}\n >\n {label}\n </Button>\n </React.Fragment>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAc,GAA+C,GAA0B;AAC9F,MAAI,MAAA,OAA6B,QAAO;AACxC,aAAW,CAAA,EAAG,CAAA,KAAW,OAAO,QAAQ,EAAI,QAAQ,EAClD,YAAW,KAAQ,EAAO,MACxB,KAAI,EAAK,KAAK,kBAAkB,EAC9B,QAAO,EAAK,KAAK,SAAS,EAAK;AAIrC,SAAO;AACT;AAEA,SAAwB,IAAa;AACnC,QAAM,EAAE,KAAA,GAAK,QAAA,GAAQ,cAAA,EAAA,IAAiB,EAAe,GAC/C,EAAE,OAAA,EAAA,IAAU;AAElB,MAAI,EAAM,UAAU,EAAG,QAAO;AAE9B,QAAM,IAAA,CAAe,MAAkB;AACrC,IAAI,MAAU,EAAM,SAAS,MAC7B,EAAA,CAAO,OAAS;AAAA,MACd,GAAG;AAAA,MACH,OAAO,EAAK,MAAM,MAAM,GAAG,IAAQ,CAAC;AAAA,IACtC,EAAE,GACF,EAAa;AAAA,MAAE,SAAS,oBAAI,IAAI;AAAA,MAAG,SAAS,oBAAI,IAAI;AAAA,MAAG,SAAS,oBAAI,IAAI;AAAA,IAAE,CAAC;AAAA,EAC7E;AAEA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,cACZ,EAAM,IAAA,CAAK,GAAU,MAAM;AAC1B,YAAM,IAAQ,EAAc,GAAK,CAAQ,GACnC,IAAS,MAAM,EAAM,SAAS;AACpC,aACE,gBAAA,EAAC,EAAM,UAAP,EAAA,UAAA,CACG,IAAI,KAAK,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,kBAAsB;AAAA,MAAO,CAAA,GACvD,gBAAA,EAAC,GAAD;AAAA,QACE,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW,wBAAwB,IAAS,iCAAiC,EAAA;AAAA,QAC7E,SAAA,MAAe,EAAY,CAAC;AAAA,QAC5B,UAAU;AAAA,kBAET;AAAA,MACK,CAAA,CACM,EAAA,GAXK,CAWL;AAAA,IAEpB,CAAC;AAAA,EACE,CAAA;AAET"}
1
+ {"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/Breadcrumb.tsx"],"sourcesContent":["import React from 'react';\nimport Button from '../../../Button';\nimport { useFlowContext } from '../context/FlowContext';\nimport { ROOT_CANVAS_ID } from '../constants';\n\nfunction findNodeLabel(doc: ReturnType<typeof useFlowContext>['doc'], canvasId: string): string {\n if (canvasId === ROOT_CANVAS_ID) return 'Root';\n for (const [, canvas] of Object.entries(doc.canvases)) {\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId === canvasId) {\n return node.data.label || node.type;\n }\n }\n }\n return canvasId;\n}\n\nexport default function Breadcrumb() {\n const { doc, setDoc, setSelection } = useFlowContext();\n const { stack } = doc;\n\n if (stack.length <= 1) return null;\n\n const handleClick = (index: number) => {\n if (index === stack.length - 1) return;\n setDoc(prev => ({\n ...prev,\n stack: prev.stack.slice(0, index + 1),\n }));\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n };\n\n return (\n <div className=\"flow-breadcrumb\">\n {stack.map((canvasId, i) => {\n const label = findNodeLabel(doc, canvasId);\n const isLast = i === stack.length - 1;\n return (\n <React.Fragment key={canvasId}>\n {i > 0 && <span className=\"flow-breadcrumb-sep\">›</span>}\n <Button\n variant=\"ghost\"\n size=\"xs\"\n className={`flow-breadcrumb-item ${isLast ? 'flow-breadcrumb-item--active' : ''}`}\n onClick={() => handleClick(i)}\n disabled={isLast}\n >\n {label}\n </Button>\n </React.Fragment>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAc,GAA+C,GAA0B;AAC9F,MAAI,MAAA,OAA6B,QAAO;AACxC,aAAW,CAAA,EAAG,CAAA,KAAW,OAAO,QAAQ,EAAI,QAAQ,EAClD,YAAW,KAAQ,EAAO,MACxB,KAAI,EAAK,KAAK,kBAAkB,EAC9B,QAAO,EAAK,KAAK,SAAS,EAAK;AAIrC,SAAO;AACT;AAEA,SAAwB,IAAa;AACnC,QAAM,EAAE,KAAA,GAAK,QAAA,GAAQ,cAAA,EAAA,IAAiB,EAAe,GAC/C,EAAE,OAAA,EAAA,IAAU;AAElB,MAAI,EAAM,UAAU,EAAG,QAAO;AAE9B,QAAM,IAAA,CAAe,MAAkB;AACrC,IAAI,MAAU,EAAM,SAAS,MAC7B,EAAA,CAAO,OAAS;AAAA,MACd,GAAG;AAAA,MACH,OAAO,EAAK,MAAM,MAAM,GAAG,IAAQ,CAAC;AAAA,IACtC,EAAE,GACF,EAAa;AAAA,MAAE,SAAS,oBAAI,IAAI;AAAA,MAAG,SAAS,oBAAI,IAAI;AAAA,MAAG,SAAS,oBAAI,IAAI;AAAA,IAAE,CAAC;AAAA,EAC7E;AAEA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IACZ,UAAA,EAAM,IAAA,CAAK,GAAU,MAAM;AAC1B,YAAM,IAAQ,EAAc,GAAK,CAAQ,GACnC,IAAS,MAAM,EAAM,SAAS;AACpC,aACE,gBAAA,EAAC,EAAM,UAAP,EAAA,UAAA,CACG,IAAI,KAAK,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAAsB,UAAA;AAAA,MAAO,CAAA,GACvD,gBAAA,EAAC,GAAD;AAAA,QACE,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW,wBAAwB,IAAS,iCAAiC,EAAA;AAAA,QAC7E,SAAA,MAAe,EAAY,CAAC;AAAA,QAC5B,UAAU;AAAA,QAET,UAAA;AAAA,MACK,CAAA,CACM,EAAA,GAXK,CAWL;AAAA,IAEpB,CAAC;AAAA,EACE,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/ContextMenu.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nexport interface ContextMenuItem {\n label: string;\n icon?: string;\n action: () => void;\n danger?: boolean;\n disabled?: boolean;\n}\n\nexport interface ContextMenuProps {\n x: number;\n y: number;\n items: ContextMenuItem[];\n onClose: () => void;\n}\n\nexport default function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [onClose]);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [onClose]);\n\n return (\n <div ref={ref} className=\"flow-context-menu\" style={{ left: x, top: y }}>\n {items.map((item, i) => {\n if (item.label === '---') {\n return <div key={i} className=\"flow-context-menu-separator\" />;\n }\n return (\n <div\n key={i}\n className=\"flow-context-menu-item\"\n style={{\n opacity: item.disabled ? 0.4 : 1,\n pointerEvents: item.disabled ? 'none' : undefined,\n color: item.danger ? 'oklch(var(--er))' : undefined,\n }}\n onClick={() => { item.action(); onClose(); }}\n >\n {item.icon && <span>{item.icon}</span>}\n <span>{item.label}</span>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;AAiBA,SAAwB,EAAY,EAAE,GAAA,GAAG,GAAA,GAAG,OAAA,GAAO,SAAA,EAAA,GAA6B;AAC9E,QAAM,IAAM,EAAuB,IAAI;AAEvC,SAAA,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAQ;AAAA,IAEZ;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,CAAO,CAAC,GAEZ,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAqB;AACpC,MAAI,EAAE,QAAQ,YAAU,EAAQ;AAAA,IAClC;AACA,oBAAS,iBAAiB,WAAW,CAAO,GAC5C,MAAa,SAAS,oBAAoB,WAAW,CAAO;AAAA,EAC9D,GAAG,CAAC,CAAO,CAAC,GAGV,gBAAA,EAAC,OAAD;AAAA,IAAU,KAAA;AAAA,IAAK,WAAU;AAAA,IAAoB,OAAO;AAAA,MAAE,MAAM;AAAA,MAAG,KAAK;AAAA,IAAE;AAAA,cACnE,EAAM,IAAA,CAAK,GAAM,MACZ,EAAK,UAAU,QACV,gBAAA,EAAC,OAAD,EAAa,WAAU,8BAA+B,GAA5C,CAA4C,IAG7D,gBAAA,EAAC,OAAD;AAAA,MAEE,WAAU;AAAA,MACV,OAAO;AAAA,QACL,SAAS,EAAK,WAAW,MAAM;AAAA,QAC/B,eAAe,EAAK,WAAW,SAAS;AAAA,QACxC,OAAO,EAAK,SAAS,qBAAqB;AAAA,MAC5C;AAAA,MACA,SAAA,MAAe;AAAE,QAAA,EAAK,OAAO,GAAG,EAAQ;AAAA,MAAG;AAAA,gBAR7C,CAUG,EAAK,QAAQ,gBAAA,EAAC,QAAD,EAAA,UAAO,EAAK,KAAW,CAAA,GACrC,gBAAA,EAAC,QAAD,EAAA,UAAO,EAAK,MAAY,CAAA,CACrB;AAAA,OAXE,CAWF,CAER;AAAA,EACE,CAAA;AAET"}
1
+ {"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../../../src/components/pro/Flow/panels/ContextMenu.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nexport interface ContextMenuItem {\n label: string;\n icon?: string;\n action: () => void;\n danger?: boolean;\n disabled?: boolean;\n}\n\nexport interface ContextMenuProps {\n x: number;\n y: number;\n items: ContextMenuItem[];\n onClose: () => void;\n}\n\nexport default function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [onClose]);\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [onClose]);\n\n return (\n <div ref={ref} className=\"flow-context-menu\" style={{ left: x, top: y }}>\n {items.map((item, i) => {\n if (item.label === '---') {\n return <div key={i} className=\"flow-context-menu-separator\" />;\n }\n return (\n <div\n key={i}\n className=\"flow-context-menu-item\"\n style={{\n opacity: item.disabled ? 0.4 : 1,\n pointerEvents: item.disabled ? 'none' : undefined,\n color: item.danger ? 'oklch(var(--er))' : undefined,\n }}\n onClick={() => { item.action(); onClose(); }}\n >\n {item.icon && <span>{item.icon}</span>}\n <span>{item.label}</span>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;AAiBA,SAAwB,EAAY,EAAE,GAAA,GAAG,GAAA,GAAG,OAAA,GAAO,SAAA,EAAA,GAA6B;AAC9E,QAAM,IAAM,EAAuB,IAAI;AAEvC,SAAA,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAQ;AAAA,IAEZ;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,CAAO,CAAC,GAEZ,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAqB;AACpC,MAAI,EAAE,QAAQ,YAAU,EAAQ;AAAA,IAClC;AACA,oBAAS,iBAAiB,WAAW,CAAO,GAC5C,MAAa,SAAS,oBAAoB,WAAW,CAAO;AAAA,EAC9D,GAAG,CAAC,CAAO,CAAC,GAGV,gBAAA,EAAC,OAAD;AAAA,IAAU,KAAA;AAAA,IAAK,WAAU;AAAA,IAAoB,OAAO;AAAA,MAAE,MAAM;AAAA,MAAG,KAAK;AAAA,IAAE;AAAA,IACnE,UAAA,EAAM,IAAA,CAAK,GAAM,MACZ,EAAK,UAAU,QACV,gBAAA,EAAC,OAAD,EAAa,WAAU,8BAA+B,GAA5C,CAA4C,IAG7D,gBAAA,EAAC,OAAD;AAAA,MAEE,WAAU;AAAA,MACV,OAAO;AAAA,QACL,SAAS,EAAK,WAAW,MAAM;AAAA,QAC/B,eAAe,EAAK,WAAW,SAAS;AAAA,QACxC,OAAO,EAAK,SAAS,qBAAqB;AAAA,MAC5C;AAAA,MACA,SAAA,MAAe;AAAE,QAAA,EAAK,OAAO,GAAG,EAAQ;AAAA,MAAG;AAAA,MAR7C,UAAA,CAUG,EAAK,QAAQ,gBAAA,EAAC,QAAD,EAAA,UAAO,EAAK,KAAW,CAAA,GACrC,gBAAA,EAAC,QAAD,EAAA,UAAO,EAAK,MAAY,CAAA,CACrB;AAAA,IAXE,GAAA,CAWF,CAER;AAAA,EACE,CAAA;AAET"}