@01.software/sdk 0.3.0 → 0.4.1

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 (58) hide show
  1. package/README.md +5 -2
  2. package/dist/auth.d.cts +1 -1
  3. package/dist/auth.d.ts +1 -1
  4. package/dist/const-BsO3aVX_.d.cts +19 -0
  5. package/dist/const-DZyvV9wU.d.ts +19 -0
  6. package/dist/index.cjs +285 -86
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +114 -196
  9. package/dist/index.d.ts +114 -196
  10. package/dist/index.js +285 -86
  11. package/dist/index.js.map +1 -1
  12. package/dist/{payload-types-ggU6BNuH.d.cts → payload-types-BsjHfeAF.d.cts} +68 -7
  13. package/dist/{payload-types-ggU6BNuH.d.ts → payload-types-BsjHfeAF.d.ts} +68 -7
  14. package/dist/realtime-DupPIYx-.d.cts +33 -0
  15. package/dist/realtime-DupPIYx-.d.ts +33 -0
  16. package/dist/realtime.cjs +263 -0
  17. package/dist/realtime.cjs.map +1 -0
  18. package/dist/realtime.d.cts +38 -0
  19. package/dist/realtime.d.ts +38 -0
  20. package/dist/realtime.js +241 -0
  21. package/dist/realtime.js.map +1 -0
  22. package/dist/ui/code-block.cjs +3 -1
  23. package/dist/ui/code-block.cjs.map +1 -1
  24. package/dist/ui/code-block.js +4 -2
  25. package/dist/ui/code-block.js.map +1 -1
  26. package/dist/ui/flow.cjs +282 -39
  27. package/dist/ui/flow.cjs.map +1 -1
  28. package/dist/ui/flow.d.cts +104 -3
  29. package/dist/ui/flow.d.ts +104 -3
  30. package/dist/ui/flow.js +270 -24
  31. package/dist/ui/flow.js.map +1 -1
  32. package/dist/ui/form.d.cts +1 -1
  33. package/dist/ui/form.d.ts +1 -1
  34. package/dist/ui/rich-text.cjs +8 -1
  35. package/dist/ui/rich-text.cjs.map +1 -1
  36. package/dist/ui/rich-text.d.cts +20 -1
  37. package/dist/ui/rich-text.d.ts +20 -1
  38. package/dist/ui/rich-text.js +8 -1
  39. package/dist/ui/rich-text.js.map +1 -1
  40. package/dist/ui/video.cjs +219 -0
  41. package/dist/ui/video.cjs.map +1 -0
  42. package/dist/ui/video.d.cts +96 -0
  43. package/dist/ui/video.d.ts +96 -0
  44. package/dist/ui/video.js +191 -0
  45. package/dist/ui/video.js.map +1 -0
  46. package/dist/video-DbLL8yuc.d.cts +85 -0
  47. package/dist/video-DbLL8yuc.d.ts +85 -0
  48. package/dist/webhook-BBWl8O2f.d.ts +20 -0
  49. package/dist/webhook-CkL56e65.d.cts +20 -0
  50. package/dist/webhook.cjs +8 -8
  51. package/dist/webhook.cjs.map +1 -1
  52. package/dist/webhook.d.cts +3 -2
  53. package/dist/webhook.d.ts +3 -2
  54. package/dist/webhook.js +8 -8
  55. package/dist/webhook.js.map +1 -1
  56. package/package.json +30 -4
  57. package/dist/webhook-B54a-HGd.d.ts +0 -35
  58. package/dist/webhook-DInps2xX.d.cts +0 -35
@@ -103,7 +103,9 @@ function CodeBlock({
103
103
  }) {
104
104
  const [nodes, setNodes] = (0, import_react2.useState)(initial);
105
105
  const [copied, setCopied] = (0, import_react2.useState)(false);
106
+ const initialCodeRef = (0, import_react2.useRef)(code);
106
107
  (0, import_react2.useEffect)(() => {
108
+ if (initial && code === initialCodeRef.current && nodes === initial) return;
107
109
  let cancelled = false;
108
110
  void highlight(code, language, theme).then((el) => {
109
111
  if (!cancelled) setNodes(el);
@@ -111,7 +113,7 @@ function CodeBlock({
111
113
  return () => {
112
114
  cancelled = true;
113
115
  };
114
- }, [code, language, theme]);
116
+ }, [code, language, theme, initial]);
115
117
  const handleCopy = () => {
116
118
  void navigator.clipboard.writeText(code).then(
117
119
  () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/CodeBlock/index.tsx","../../src/ui/CodeBlock/highlight.ts"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useState, type JSX } from 'react'\nimport { highlight, type BundledTheme } from './highlight'\n\nexport type { BundledTheme }\nexport { highlight }\n\nexport interface CodeBlockProps {\n /** Code string to highlight */\n code: string\n /** Language identifier (e.g. 'typescript', 'js', 'python') */\n language?: string\n /** Shiki theme name. Default: 'github-dark' */\n theme?: BundledTheme\n /** CSS class for the wrapper */\n className?: string\n /** Pre-rendered JSX from server component via `highlight()` */\n initial?: JSX.Element\n /** Show line numbers. Default: false */\n showLineNumbers?: boolean\n /** Show copy button. Default: true */\n showCopyButton?: boolean\n}\n\n/**\n * Syntax-highlighted code block using shiki.\n *\n * @example Basic usage\n * ```tsx\n * <CodeBlock code=\"const x = 1\" language=\"typescript\" />\n * ```\n *\n * @example With server pre-rendering (Next.js)\n * ```tsx\n * // Server Component\n * const initial = await highlight(code, 'typescript')\n * return <CodeBlock code={code} language=\"typescript\" initial={initial} />\n * ```\n *\n * @example As RichTextContent block renderer\n * ```tsx\n * <RichTextContent\n * data={data}\n * blocks={{\n * Code: ({ node }) => (\n * <CodeBlock code={node.fields.code} language={node.fields.language} />\n * ),\n * }}\n * />\n * ```\n */\nexport function CodeBlock({\n code,\n language = 'typescript',\n theme = 'github-dark',\n className,\n initial,\n showLineNumbers = false,\n showCopyButton = true,\n}: CodeBlockProps) {\n const [nodes, setNodes] = useState<JSX.Element | undefined>(initial)\n const [copied, setCopied] = useState(false)\n\n useEffect(() => {\n let cancelled = false\n void highlight(code, language, theme).then((el) => {\n if (!cancelled) setNodes(el)\n })\n return () => {\n cancelled = true\n }\n }, [code, language, theme])\n\n const handleCopy = () => {\n void navigator.clipboard.writeText(code).then(\n () => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n },\n () => {},\n )\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy code\"\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n zIndex: 1,\n padding: '4px 8px',\n fontSize: 12,\n lineHeight: 1,\n border: '1px solid rgba(255,255,255,0.2)',\n borderRadius: 4,\n background: 'rgba(0,0,0,0.3)',\n color: '#ccc',\n cursor: 'pointer',\n opacity: 0.7,\n transition: 'opacity 0.15s',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '0.7'\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )}\n {showLineNumbers && nodes ? (\n <div style={{ display: 'flex' }}>\n <div\n aria-hidden\n style={{\n padding: '1em 0.5em 1em 1em',\n textAlign: 'right',\n userSelect: 'none',\n color: 'rgba(255,255,255,0.3)',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n {code.split('\\n').map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n <div style={{ flex: 1, overflow: 'auto' }}>{nodes}</div>\n </div>\n ) : (\n (nodes ?? (\n <pre\n style={{\n margin: 0,\n padding: '1em',\n overflow: 'auto',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n <code>{code}</code>\n </pre>\n ))\n )}\n </div>\n )\n}\n","import type { JSX } from 'react'\nimport { Fragment } from 'react'\nimport { jsx, jsxs } from 'react/jsx-runtime'\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime'\nimport { codeToHast, type BundledLanguage, type BundledTheme } from 'shiki'\n\nexport type { BundledLanguage, BundledTheme }\n\n/** Normalize language aliases to shiki-compatible language IDs */\nconst LANGUAGE_ALIASES: Record<string, string> = {\n js: 'javascript',\n ts: 'typescript',\n sh: 'bash',\n shell: 'bash',\n yml: 'yaml',\n py: 'python',\n rb: 'ruby',\n plaintext: 'text',\n}\n\nfunction normalizeLanguage(lang: string): string {\n return LANGUAGE_ALIASES[lang] || lang\n}\n\n/**\n * Highlight code to JSX using shiki.\n * Works in both Server and Client components.\n *\n * @example Server Component\n * ```tsx\n * const highlighted = await highlight('const x = 1', 'typescript')\n * return <div>{highlighted}</div>\n * ```\n */\nexport async function highlight(\n code: string,\n lang: string,\n theme: BundledTheme = 'github-dark',\n): Promise<JSX.Element> {\n const normalized = normalizeLanguage(lang)\n try {\n const hast = await codeToHast(code, {\n lang: normalized as BundledLanguage,\n theme,\n })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n } catch {\n // Fallback to plain text if language is not supported\n const hast = await codeToHast(code, { lang: 'text', theme })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n }\n}\n"],"mappings":"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","names":["import_react","React"]}
1
+ {"version":3,"sources":["../../src/ui/CodeBlock/index.tsx","../../src/ui/CodeBlock/highlight.ts"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useRef, useState, type JSX } from 'react'\nimport { highlight, type BundledTheme } from './highlight'\n\nexport type { BundledTheme }\nexport { highlight }\n\nexport interface CodeBlockProps {\n /** Code string to highlight */\n code: string\n /** Language identifier (e.g. 'typescript', 'js', 'python') */\n language?: string\n /** Shiki theme name. Default: 'github-dark' */\n theme?: BundledTheme\n /** CSS class for the wrapper */\n className?: string\n /** Pre-rendered JSX from server component via `highlight()` */\n initial?: JSX.Element\n /** Show line numbers. Default: false */\n showLineNumbers?: boolean\n /** Show copy button. Default: true */\n showCopyButton?: boolean\n}\n\n/**\n * Syntax-highlighted code block using shiki.\n *\n * @example Basic usage\n * ```tsx\n * <CodeBlock code=\"const x = 1\" language=\"typescript\" />\n * ```\n *\n * @example With server pre-rendering (Next.js)\n * ```tsx\n * // Server Component\n * const initial = await highlight(code, 'typescript')\n * return <CodeBlock code={code} language=\"typescript\" initial={initial} />\n * ```\n *\n * @example As RichTextContent block renderer\n * ```tsx\n * <RichTextContent\n * data={data}\n * blocks={{\n * Code: ({ node }) => (\n * <CodeBlock code={node.fields.code} language={node.fields.language} />\n * ),\n * }}\n * />\n * ```\n */\nexport function CodeBlock({\n code,\n language = 'typescript',\n theme = 'github-dark',\n className,\n initial,\n showLineNumbers = false,\n showCopyButton = true,\n}: CodeBlockProps) {\n const [nodes, setNodes] = useState<JSX.Element | undefined>(initial)\n const [copied, setCopied] = useState(false)\n const initialCodeRef = useRef(code)\n\n useEffect(() => {\n // Skip re-highlighting if server pre-rendered and code hasn't changed\n if (initial && code === initialCodeRef.current && nodes === initial) return\n\n let cancelled = false\n void highlight(code, language, theme).then((el) => {\n if (!cancelled) setNodes(el)\n })\n return () => {\n cancelled = true\n }\n }, [code, language, theme, initial])\n\n const handleCopy = () => {\n void navigator.clipboard.writeText(code).then(\n () => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n },\n () => {},\n )\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy code\"\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n zIndex: 1,\n padding: '4px 8px',\n fontSize: 12,\n lineHeight: 1,\n border: '1px solid rgba(255,255,255,0.2)',\n borderRadius: 4,\n background: 'rgba(0,0,0,0.3)',\n color: '#ccc',\n cursor: 'pointer',\n opacity: 0.7,\n transition: 'opacity 0.15s',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '0.7'\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )}\n {showLineNumbers && nodes ? (\n <div style={{ display: 'flex' }}>\n <div\n aria-hidden\n style={{\n padding: '1em 0.5em 1em 1em',\n textAlign: 'right',\n userSelect: 'none',\n color: 'rgba(255,255,255,0.3)',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n {code.split('\\n').map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n <div style={{ flex: 1, overflow: 'auto' }}>{nodes}</div>\n </div>\n ) : (\n (nodes ?? (\n <pre\n style={{\n margin: 0,\n padding: '1em',\n overflow: 'auto',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n <code>{code}</code>\n </pre>\n ))\n )}\n </div>\n )\n}\n","import type { JSX } from 'react'\nimport { Fragment } from 'react'\nimport { jsx, jsxs } from 'react/jsx-runtime'\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime'\nimport { codeToHast, type BundledLanguage, type BundledTheme } from 'shiki'\n\nexport type { BundledLanguage, BundledTheme }\n\n/** Normalize language aliases to shiki-compatible language IDs */\nconst LANGUAGE_ALIASES: Record<string, string> = {\n js: 'javascript',\n ts: 'typescript',\n sh: 'bash',\n shell: 'bash',\n yml: 'yaml',\n py: 'python',\n rb: 'ruby',\n plaintext: 'text',\n}\n\nfunction normalizeLanguage(lang: string): string {\n return LANGUAGE_ALIASES[lang] || lang\n}\n\n/**\n * Highlight code to JSX using shiki.\n * Works in both Server and Client components.\n *\n * @example Server Component\n * ```tsx\n * const highlighted = await highlight('const x = 1', 'typescript')\n * return <div>{highlighted}</div>\n * ```\n */\nexport async function highlight(\n code: string,\n lang: string,\n theme: BundledTheme = 'github-dark',\n): Promise<JSX.Element> {\n const normalized = normalizeLanguage(lang)\n try {\n const hast = await codeToHast(code, {\n lang: normalized as BundledLanguage,\n theme,\n })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n } catch {\n // Fallback to plain text if language is not supported\n const hast = await codeToHast(code, { lang: 'text', theme })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n }\n}\n"],"mappings":"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","names":["import_react","React"]}
@@ -21,7 +21,7 @@ var __async = (__this, __arguments, generator) => {
21
21
  };
22
22
 
23
23
  // src/ui/CodeBlock/index.tsx
24
- import React, { useEffect, useState } from "react";
24
+ import React, { useEffect, useRef, useState } from "react";
25
25
 
26
26
  // src/ui/CodeBlock/highlight.ts
27
27
  import { Fragment } from "react";
@@ -69,7 +69,9 @@ function CodeBlock({
69
69
  }) {
70
70
  const [nodes, setNodes] = useState(initial);
71
71
  const [copied, setCopied] = useState(false);
72
+ const initialCodeRef = useRef(code);
72
73
  useEffect(() => {
74
+ if (initial && code === initialCodeRef.current && nodes === initial) return;
73
75
  let cancelled = false;
74
76
  void highlight(code, language, theme).then((el) => {
75
77
  if (!cancelled) setNodes(el);
@@ -77,7 +79,7 @@ function CodeBlock({
77
79
  return () => {
78
80
  cancelled = true;
79
81
  };
80
- }, [code, language, theme]);
82
+ }, [code, language, theme, initial]);
81
83
  const handleCopy = () => {
82
84
  void navigator.clipboard.writeText(code).then(
83
85
  () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/CodeBlock/index.tsx","../../src/ui/CodeBlock/highlight.ts"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useState, type JSX } from 'react'\nimport { highlight, type BundledTheme } from './highlight'\n\nexport type { BundledTheme }\nexport { highlight }\n\nexport interface CodeBlockProps {\n /** Code string to highlight */\n code: string\n /** Language identifier (e.g. 'typescript', 'js', 'python') */\n language?: string\n /** Shiki theme name. Default: 'github-dark' */\n theme?: BundledTheme\n /** CSS class for the wrapper */\n className?: string\n /** Pre-rendered JSX from server component via `highlight()` */\n initial?: JSX.Element\n /** Show line numbers. Default: false */\n showLineNumbers?: boolean\n /** Show copy button. Default: true */\n showCopyButton?: boolean\n}\n\n/**\n * Syntax-highlighted code block using shiki.\n *\n * @example Basic usage\n * ```tsx\n * <CodeBlock code=\"const x = 1\" language=\"typescript\" />\n * ```\n *\n * @example With server pre-rendering (Next.js)\n * ```tsx\n * // Server Component\n * const initial = await highlight(code, 'typescript')\n * return <CodeBlock code={code} language=\"typescript\" initial={initial} />\n * ```\n *\n * @example As RichTextContent block renderer\n * ```tsx\n * <RichTextContent\n * data={data}\n * blocks={{\n * Code: ({ node }) => (\n * <CodeBlock code={node.fields.code} language={node.fields.language} />\n * ),\n * }}\n * />\n * ```\n */\nexport function CodeBlock({\n code,\n language = 'typescript',\n theme = 'github-dark',\n className,\n initial,\n showLineNumbers = false,\n showCopyButton = true,\n}: CodeBlockProps) {\n const [nodes, setNodes] = useState<JSX.Element | undefined>(initial)\n const [copied, setCopied] = useState(false)\n\n useEffect(() => {\n let cancelled = false\n void highlight(code, language, theme).then((el) => {\n if (!cancelled) setNodes(el)\n })\n return () => {\n cancelled = true\n }\n }, [code, language, theme])\n\n const handleCopy = () => {\n void navigator.clipboard.writeText(code).then(\n () => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n },\n () => {},\n )\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy code\"\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n zIndex: 1,\n padding: '4px 8px',\n fontSize: 12,\n lineHeight: 1,\n border: '1px solid rgba(255,255,255,0.2)',\n borderRadius: 4,\n background: 'rgba(0,0,0,0.3)',\n color: '#ccc',\n cursor: 'pointer',\n opacity: 0.7,\n transition: 'opacity 0.15s',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '0.7'\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )}\n {showLineNumbers && nodes ? (\n <div style={{ display: 'flex' }}>\n <div\n aria-hidden\n style={{\n padding: '1em 0.5em 1em 1em',\n textAlign: 'right',\n userSelect: 'none',\n color: 'rgba(255,255,255,0.3)',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n {code.split('\\n').map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n <div style={{ flex: 1, overflow: 'auto' }}>{nodes}</div>\n </div>\n ) : (\n (nodes ?? (\n <pre\n style={{\n margin: 0,\n padding: '1em',\n overflow: 'auto',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n <code>{code}</code>\n </pre>\n ))\n )}\n </div>\n )\n}\n","import type { JSX } from 'react'\nimport { Fragment } from 'react'\nimport { jsx, jsxs } from 'react/jsx-runtime'\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime'\nimport { codeToHast, type BundledLanguage, type BundledTheme } from 'shiki'\n\nexport type { BundledLanguage, BundledTheme }\n\n/** Normalize language aliases to shiki-compatible language IDs */\nconst LANGUAGE_ALIASES: Record<string, string> = {\n js: 'javascript',\n ts: 'typescript',\n sh: 'bash',\n shell: 'bash',\n yml: 'yaml',\n py: 'python',\n rb: 'ruby',\n plaintext: 'text',\n}\n\nfunction normalizeLanguage(lang: string): string {\n return LANGUAGE_ALIASES[lang] || lang\n}\n\n/**\n * Highlight code to JSX using shiki.\n * Works in both Server and Client components.\n *\n * @example Server Component\n * ```tsx\n * const highlighted = await highlight('const x = 1', 'typescript')\n * return <div>{highlighted}</div>\n * ```\n */\nexport async function highlight(\n code: string,\n lang: string,\n theme: BundledTheme = 'github-dark',\n): Promise<JSX.Element> {\n const normalized = normalizeLanguage(lang)\n try {\n const hast = await codeToHast(code, {\n lang: normalized as BundledLanguage,\n theme,\n })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n } catch {\n // Fallback to plain text if language is not supported\n const hast = await codeToHast(code, { lang: 'text', theme })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/ui/CodeBlock/index.tsx","../../src/ui/CodeBlock/highlight.ts"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useRef, useState, type JSX } from 'react'\nimport { highlight, type BundledTheme } from './highlight'\n\nexport type { BundledTheme }\nexport { highlight }\n\nexport interface CodeBlockProps {\n /** Code string to highlight */\n code: string\n /** Language identifier (e.g. 'typescript', 'js', 'python') */\n language?: string\n /** Shiki theme name. Default: 'github-dark' */\n theme?: BundledTheme\n /** CSS class for the wrapper */\n className?: string\n /** Pre-rendered JSX from server component via `highlight()` */\n initial?: JSX.Element\n /** Show line numbers. Default: false */\n showLineNumbers?: boolean\n /** Show copy button. Default: true */\n showCopyButton?: boolean\n}\n\n/**\n * Syntax-highlighted code block using shiki.\n *\n * @example Basic usage\n * ```tsx\n * <CodeBlock code=\"const x = 1\" language=\"typescript\" />\n * ```\n *\n * @example With server pre-rendering (Next.js)\n * ```tsx\n * // Server Component\n * const initial = await highlight(code, 'typescript')\n * return <CodeBlock code={code} language=\"typescript\" initial={initial} />\n * ```\n *\n * @example As RichTextContent block renderer\n * ```tsx\n * <RichTextContent\n * data={data}\n * blocks={{\n * Code: ({ node }) => (\n * <CodeBlock code={node.fields.code} language={node.fields.language} />\n * ),\n * }}\n * />\n * ```\n */\nexport function CodeBlock({\n code,\n language = 'typescript',\n theme = 'github-dark',\n className,\n initial,\n showLineNumbers = false,\n showCopyButton = true,\n}: CodeBlockProps) {\n const [nodes, setNodes] = useState<JSX.Element | undefined>(initial)\n const [copied, setCopied] = useState(false)\n const initialCodeRef = useRef(code)\n\n useEffect(() => {\n // Skip re-highlighting if server pre-rendered and code hasn't changed\n if (initial && code === initialCodeRef.current && nodes === initial) return\n\n let cancelled = false\n void highlight(code, language, theme).then((el) => {\n if (!cancelled) setNodes(el)\n })\n return () => {\n cancelled = true\n }\n }, [code, language, theme, initial])\n\n const handleCopy = () => {\n void navigator.clipboard.writeText(code).then(\n () => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n },\n () => {},\n )\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy code\"\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n zIndex: 1,\n padding: '4px 8px',\n fontSize: 12,\n lineHeight: 1,\n border: '1px solid rgba(255,255,255,0.2)',\n borderRadius: 4,\n background: 'rgba(0,0,0,0.3)',\n color: '#ccc',\n cursor: 'pointer',\n opacity: 0.7,\n transition: 'opacity 0.15s',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '0.7'\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )}\n {showLineNumbers && nodes ? (\n <div style={{ display: 'flex' }}>\n <div\n aria-hidden\n style={{\n padding: '1em 0.5em 1em 1em',\n textAlign: 'right',\n userSelect: 'none',\n color: 'rgba(255,255,255,0.3)',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n {code.split('\\n').map((_, i) => (\n <div key={i}>{i + 1}</div>\n ))}\n </div>\n <div style={{ flex: 1, overflow: 'auto' }}>{nodes}</div>\n </div>\n ) : (\n (nodes ?? (\n <pre\n style={{\n margin: 0,\n padding: '1em',\n overflow: 'auto',\n fontFamily: 'monospace',\n fontSize: 13,\n lineHeight: 1.5,\n }}\n >\n <code>{code}</code>\n </pre>\n ))\n )}\n </div>\n )\n}\n","import type { JSX } from 'react'\nimport { Fragment } from 'react'\nimport { jsx, jsxs } from 'react/jsx-runtime'\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime'\nimport { codeToHast, type BundledLanguage, type BundledTheme } from 'shiki'\n\nexport type { BundledLanguage, BundledTheme }\n\n/** Normalize language aliases to shiki-compatible language IDs */\nconst LANGUAGE_ALIASES: Record<string, string> = {\n js: 'javascript',\n ts: 'typescript',\n sh: 'bash',\n shell: 'bash',\n yml: 'yaml',\n py: 'python',\n rb: 'ruby',\n plaintext: 'text',\n}\n\nfunction normalizeLanguage(lang: string): string {\n return LANGUAGE_ALIASES[lang] || lang\n}\n\n/**\n * Highlight code to JSX using shiki.\n * Works in both Server and Client components.\n *\n * @example Server Component\n * ```tsx\n * const highlighted = await highlight('const x = 1', 'typescript')\n * return <div>{highlighted}</div>\n * ```\n */\nexport async function highlight(\n code: string,\n lang: string,\n theme: BundledTheme = 'github-dark',\n): Promise<JSX.Element> {\n const normalized = normalizeLanguage(lang)\n try {\n const hast = await codeToHast(code, {\n lang: normalized as BundledLanguage,\n theme,\n })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n } catch {\n // Fallback to plain text if language is not supported\n const hast = await codeToHast(code, { lang: 'text', theme })\n return toJsxRuntime(hast, { Fragment, jsx, jsxs }) as JSX.Element\n }\n}\n"],"mappings":"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","names":[]}
package/dist/ui/flow.cjs CHANGED
@@ -2,7 +2,9 @@
2
2
  "use client";
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
+ var __defProps = Object.defineProperties;
5
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
8
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
9
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
10
  var __getProtoOf = Object.getPrototypeOf;
@@ -20,6 +22,7 @@ var __spreadValues = (a, b) => {
20
22
  }
21
23
  return a;
22
24
  };
25
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
26
  var __export = (target, all) => {
24
27
  for (var name in all)
25
28
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -68,13 +71,16 @@ __export(Flow_exports, {
68
71
  BUILT_IN_EDGE_TYPES: () => BUILT_IN_EDGE_TYPES,
69
72
  BUILT_IN_NODE_TYPES: () => BUILT_IN_NODE_TYPES,
70
73
  FlowRenderer: () => FlowRenderer,
74
+ getFrames: () => getFrames,
75
+ getNodeBounds: () => getNodeBounds,
71
76
  isDynamicNode: () => isDynamicNode,
72
77
  isFrameNode: () => isFrameNode,
73
- useFlow: () => useFlow
78
+ useFlow: () => useFlow,
79
+ useFlowData: () => useFlowData
74
80
  });
75
81
  module.exports = __toCommonJS(Flow_exports);
76
- var import_react2 = __toESM(require("react"), 1);
77
- var import_react3 = require("@xyflow/react");
82
+ var import_react3 = __toESM(require("react"), 1);
83
+ var import_react4 = require("@xyflow/react");
78
84
 
79
85
  // src/ui/Flow/types.ts
80
86
  function isDynamicNode(node) {
@@ -125,6 +131,21 @@ var BUILT_IN_EDGE_TYPES = [
125
131
  // src/ui/Flow/useFlow.ts
126
132
  var import_react_query = require("@tanstack/react-query");
127
133
  var import_react = require("react");
134
+
135
+ // src/core/query/query-keys.ts
136
+ function collectionKeys(collection) {
137
+ return {
138
+ all: [collection],
139
+ lists: () => [collection, "list"],
140
+ list: (options) => [collection, "list", options],
141
+ details: () => [collection, "detail"],
142
+ detail: (id, options) => [collection, "detail", id, options],
143
+ infinites: () => [collection, "infinite"],
144
+ infinite: (options) => [collection, "infinite", options]
145
+ };
146
+ }
147
+
148
+ // src/ui/Flow/useFlow.ts
128
149
  function toNodeTypeDef(doc) {
129
150
  var _a, _b, _c, _d;
130
151
  return {
@@ -160,7 +181,7 @@ function useFlow(options) {
160
181
  const identifier = (_a = id != null ? id : slug) != null ? _a : "";
161
182
  const flowQuery = (0, import_react_query.useQuery)(
162
183
  {
163
- queryKey: ["flows", identifier],
184
+ queryKey: collectionKeys("flows").detail(identifier),
164
185
  queryFn: () => __async(null, null, function* () {
165
186
  if (id) {
166
187
  return client.from("flows").findById(id);
@@ -179,7 +200,7 @@ function useFlow(options) {
179
200
  );
180
201
  const nodeTypesQuery = (0, import_react_query.useQuery)(
181
202
  {
182
- queryKey: ["flow-node-types"],
203
+ queryKey: collectionKeys("flow-node-types").lists(),
183
204
  queryFn: () => __async(null, null, function* () {
184
205
  const result = yield client.from("flow-node-types").find({ limit: 100 });
185
206
  return result.docs;
@@ -190,7 +211,7 @@ function useFlow(options) {
190
211
  );
191
212
  const edgeTypesQuery = (0, import_react_query.useQuery)(
192
213
  {
193
- queryKey: ["flow-edge-types"],
214
+ queryKey: collectionKeys("flow-edge-types").lists(),
194
215
  queryFn: () => __async(null, null, function* () {
195
216
  const result = yield client.from("flow-edge-types").find({ limit: 100 });
196
217
  return result.docs;
@@ -225,6 +246,104 @@ function useFlow(options) {
225
246
  };
226
247
  }
227
248
 
249
+ // src/ui/Flow/useFlowData.ts
250
+ var import_react2 = require("react");
251
+ function useFlowData(options) {
252
+ const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } = options;
253
+ const nodeTypeDefsMap = (0, import_react2.useMemo)(() => {
254
+ const allDefs = inputNodeDefs != null ? inputNodeDefs : BUILT_IN_NODE_TYPES;
255
+ return new Map(allDefs.map((d) => [d.slug, d]));
256
+ }, [inputNodeDefs]);
257
+ const edgeTypeDefsMap = (0, import_react2.useMemo)(() => {
258
+ const allDefs = inputEdgeDefs != null ? inputEdgeDefs : BUILT_IN_EDGE_TYPES;
259
+ return new Map(allDefs.map((d) => [d.slug, d]));
260
+ }, [inputEdgeDefs]);
261
+ const nodes = (0, import_react2.useMemo)(() => {
262
+ var _a;
263
+ return (_a = data == null ? void 0 : data.nodes) != null ? _a : [];
264
+ }, [data == null ? void 0 : data.nodes]);
265
+ const edges = (0, import_react2.useMemo)(() => {
266
+ var _a;
267
+ return (_a = data == null ? void 0 : data.edges) != null ? _a : [];
268
+ }, [data == null ? void 0 : data.edges]);
269
+ return {
270
+ nodes,
271
+ edges,
272
+ nodeTypeDefsMap,
273
+ edgeTypeDefsMap
274
+ };
275
+ }
276
+
277
+ // src/ui/Flow/utils.ts
278
+ function getNodeBounds(nodes, nodeIds) {
279
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
280
+ const idSet = new Set(nodeIds);
281
+ const targetNodes = nodes.filter((n) => idSet.has(n.id));
282
+ if (targetNodes.length === 0) return void 0;
283
+ const nodeMap = new Map(nodes.map((n) => [n.id, n]));
284
+ function getAbsolutePosition(node) {
285
+ let x = node.position.x;
286
+ let y = node.position.y;
287
+ let current = node;
288
+ const visited = /* @__PURE__ */ new Set([node.id]);
289
+ while (current.parentId) {
290
+ const parentId = current.parentId;
291
+ if (visited.has(parentId)) break;
292
+ const parent = nodeMap.get(parentId);
293
+ if (!parent) break;
294
+ visited.add(parent.id);
295
+ x += parent.position.x;
296
+ y += parent.position.y;
297
+ current = parent;
298
+ }
299
+ return { x, y };
300
+ }
301
+ let minX = Infinity;
302
+ let minY = Infinity;
303
+ let maxX = -Infinity;
304
+ let maxY = -Infinity;
305
+ for (const node of targetNodes) {
306
+ const abs = getAbsolutePosition(node);
307
+ const w = (_e = (_d = (_c = (_a = node.style) == null ? void 0 : _a.width) != null ? _c : (_b = node.measured) == null ? void 0 : _b.width) != null ? _d : node.width) != null ? _e : 200;
308
+ const h = (_j = (_i = (_h = (_f = node.style) == null ? void 0 : _f.height) != null ? _h : (_g = node.measured) == null ? void 0 : _g.height) != null ? _i : node.height) != null ? _j : 200;
309
+ minX = Math.min(minX, abs.x);
310
+ minY = Math.min(minY, abs.y);
311
+ maxX = Math.max(maxX, abs.x + w);
312
+ maxY = Math.max(maxY, abs.y + h);
313
+ }
314
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
315
+ }
316
+ function getFrames(nodes) {
317
+ const frames = nodes.filter((n) => n.type === "frame");
318
+ if (frames.length === 0) return [];
319
+ const nodeMap = new Map(nodes.map((n) => [n.id, n]));
320
+ function getAbsolutePosition(node) {
321
+ let x = node.position.x;
322
+ let y = node.position.y;
323
+ let current = node;
324
+ const visited = /* @__PURE__ */ new Set([node.id]);
325
+ while (current.parentId) {
326
+ const parentId = current.parentId;
327
+ if (visited.has(parentId)) break;
328
+ const parent = nodeMap.get(parentId);
329
+ if (!parent) break;
330
+ visited.add(parent.id);
331
+ x += parent.position.x;
332
+ y += parent.position.y;
333
+ current = parent;
334
+ }
335
+ return { x, y };
336
+ }
337
+ return frames.map((f) => {
338
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
339
+ const data = f.data;
340
+ const abs = getAbsolutePosition(f);
341
+ const w = (_e = (_d = (_c = (_a = f.style) == null ? void 0 : _a.width) != null ? _c : (_b = f.measured) == null ? void 0 : _b.width) != null ? _d : f.width) != null ? _e : 200;
342
+ const h = (_j = (_i = (_h = (_f = f.style) == null ? void 0 : _f.height) != null ? _h : (_g = f.measured) == null ? void 0 : _g.height) != null ? _i : f.height) != null ? _j : 200;
343
+ return { id: f.id, label: (_k = data.label) != null ? _k : "", bounds: { x: abs.x, y: abs.y, width: w, height: h } };
344
+ }).sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x);
345
+ }
346
+
228
347
  // src/ui/Flow/index.tsx
229
348
  function sanitizeUrl(url) {
230
349
  if (!url) return url;
@@ -237,8 +356,8 @@ function sanitizeUrl(url) {
237
356
  }
238
357
  }
239
358
  function toMarkerType(value) {
240
- if (value === "arrow") return import_react3.MarkerType.Arrow;
241
- if (value === "arrowclosed") return import_react3.MarkerType.ArrowClosed;
359
+ if (value === "arrow") return import_react4.MarkerType.Arrow;
360
+ if (value === "arrowclosed") return import_react4.MarkerType.ArrowClosed;
242
361
  return void 0;
243
362
  }
244
363
  function renderFieldValue(key, val, fieldDef) {
@@ -248,7 +367,7 @@ function renderFieldValue(key, val, fieldDef) {
248
367
  const imgUrl = typeof val === "string" ? val : val == null ? void 0 : val.url;
249
368
  const safeUrl = sanitizeUrl(imgUrl);
250
369
  if (!safeUrl) return null;
251
- return /* @__PURE__ */ import_react2.default.createElement(
370
+ return /* @__PURE__ */ import_react3.default.createElement(
252
371
  "img",
253
372
  {
254
373
  key,
@@ -259,7 +378,7 @@ function renderFieldValue(key, val, fieldDef) {
259
378
  }
260
379
  );
261
380
  }
262
- return /* @__PURE__ */ import_react2.default.createElement(
381
+ return /* @__PURE__ */ import_react3.default.createElement(
263
382
  "div",
264
383
  {
265
384
  key,
@@ -276,7 +395,7 @@ function renderFieldValue(key, val, fieldDef) {
276
395
  }
277
396
  function DefaultDynamicNode({ data }) {
278
397
  const d = data;
279
- return /* @__PURE__ */ import_react2.default.createElement(
398
+ return /* @__PURE__ */ import_react3.default.createElement(
280
399
  "div",
281
400
  {
282
401
  style: {
@@ -293,7 +412,7 @@ function EnhancedDynamicNode({
293
412
  data,
294
413
  typeDef
295
414
  }) {
296
- return /* @__PURE__ */ import_react2.default.createElement(
415
+ return /* @__PURE__ */ import_react3.default.createElement(
297
416
  "div",
298
417
  {
299
418
  style: {
@@ -322,7 +441,7 @@ function DefaultFrameNode({ data }) {
322
441
  if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`;
323
442
  return baseColor;
324
443
  })();
325
- return /* @__PURE__ */ import_react2.default.createElement(
444
+ return /* @__PURE__ */ import_react3.default.createElement(
326
445
  "div",
327
446
  {
328
447
  style: {
@@ -333,7 +452,7 @@ function DefaultFrameNode({ data }) {
333
452
  border: borderStyle === "none" ? "none" : `2px ${borderStyle} rgba(128,128,128,0.3)`
334
453
  }
335
454
  },
336
- /* @__PURE__ */ import_react2.default.createElement(
455
+ /* @__PURE__ */ import_react3.default.createElement(
337
456
  "div",
338
457
  {
339
458
  style: {
@@ -347,14 +466,15 @@ function DefaultFrameNode({ data }) {
347
466
  )
348
467
  );
349
468
  }
350
- function createNodeTypes(nodeRenderers, nodeTypeDefsMap) {
469
+ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
351
470
  const types = {};
352
471
  types.dynamic = ((props) => {
353
472
  const d = props.data;
354
473
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
355
474
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
475
+ let content;
356
476
  if (CustomRenderer) {
357
- return /* @__PURE__ */ import_react2.default.createElement(
477
+ content = /* @__PURE__ */ import_react3.default.createElement(
358
478
  CustomRenderer,
359
479
  {
360
480
  id: props.id,
@@ -364,15 +484,94 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap) {
364
484
  nodeTypeDef: typeDef
365
485
  }
366
486
  );
487
+ } else if (typeDef) {
488
+ content = /* @__PURE__ */ import_react3.default.createElement(EnhancedDynamicNode, { data: d, typeDef });
489
+ } else {
490
+ content = /* @__PURE__ */ import_react3.default.createElement(DefaultDynamicNode, __spreadValues({}, props));
367
491
  }
368
- if (typeDef) {
369
- return /* @__PURE__ */ import_react2.default.createElement(EnhancedDynamicNode, { data: d, typeDef });
492
+ if (renderNode) {
493
+ const slotProps = {
494
+ id: props.id,
495
+ nodeTypeSlug: d.nodeTypeSlug,
496
+ label: d.label,
497
+ fields: d.fields,
498
+ nodeTypeDef: typeDef
499
+ };
500
+ const result = renderNode(slotProps, content);
501
+ if (result !== null) content = result;
370
502
  }
371
- return /* @__PURE__ */ import_react2.default.createElement(DefaultDynamicNode, __spreadValues({}, props));
503
+ if (nodeWrapper) {
504
+ const Wrapper = nodeWrapper;
505
+ content = /* @__PURE__ */ import_react3.default.createElement(
506
+ Wrapper,
507
+ {
508
+ id: props.id,
509
+ nodeTypeSlug: d.nodeTypeSlug,
510
+ label: d.label,
511
+ selected: props.selected,
512
+ nodeTypeDef: typeDef
513
+ },
514
+ content
515
+ );
516
+ }
517
+ return content;
372
518
  });
373
- types.frame = DefaultFrameNode;
519
+ types.frame = frameRenderer ? ((props) => {
520
+ const d = props.data;
521
+ const Renderer = frameRenderer;
522
+ return /* @__PURE__ */ import_react3.default.createElement(
523
+ Renderer,
524
+ {
525
+ id: props.id,
526
+ label: d.label,
527
+ color: d.color,
528
+ padding: d.padding,
529
+ borderStyle: d.borderStyle,
530
+ opacity: d.opacity
531
+ }
532
+ );
533
+ }) : DefaultFrameNode;
534
+ return types;
535
+ }
536
+ function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
537
+ if (!edgeRenderers || Object.keys(edgeRenderers).length === 0) return void 0;
538
+ const types = {};
539
+ for (const [slug, Renderer] of Object.entries(edgeRenderers)) {
540
+ types[slug] = ((props) => {
541
+ var _a;
542
+ const def = edgeTypeDefsMap == null ? void 0 : edgeTypeDefsMap.get(slug);
543
+ return /* @__PURE__ */ import_react3.default.createElement(
544
+ Renderer,
545
+ {
546
+ id: props.id,
547
+ edgeTypeSlug: slug,
548
+ source: props.source,
549
+ target: props.target,
550
+ label: props.label,
551
+ fields: (_a = props.data) == null ? void 0 : _a.fields,
552
+ edgeTypeDef: def,
553
+ style: props.style
554
+ }
555
+ );
556
+ });
557
+ }
374
558
  return types;
375
559
  }
560
+ function FocusHandler({
561
+ bounds,
562
+ padding,
563
+ animation
564
+ }) {
565
+ const { fitBounds } = (0, import_react4.useReactFlow)();
566
+ const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
567
+ const boundsRef = import_react3.default.useRef(bounds);
568
+ boundsRef.current = bounds;
569
+ import_react3.default.useEffect(() => {
570
+ const duration = animation === true ? 300 : typeof animation === "number" ? animation : 0;
571
+ fitBounds(boundsRef.current, { padding, duration });
572
+ }, [boundsKey, padding, animation, fitBounds]);
573
+ return null;
574
+ }
376
575
  var EDGE_TYPE_MAP = {
377
576
  step: "step",
378
577
  smoothstep: "smoothstep",
@@ -419,50 +618,78 @@ function FlowRenderer({
419
618
  nodeRenderers,
420
619
  nodeTypeDefs,
421
620
  edgeTypeDefs,
422
- background = true,
621
+ background = false,
423
622
  interactive = false,
424
623
  fitView = true,
425
624
  onNodeClick,
426
- onEdgeClick
625
+ onEdgeClick,
626
+ frameRenderer,
627
+ edgeRenderers,
628
+ nodeWrapper,
629
+ controls,
630
+ minimap,
631
+ minimapNodeColor,
632
+ children,
633
+ renderNode,
634
+ onViewportChange,
635
+ defaultViewport: defaultViewportProp,
636
+ bounds,
637
+ focusPadding,
638
+ focusAnimation
427
639
  }) {
428
640
  var _a;
429
- const nodeTypeDefsMap = import_react2.default.useMemo(() => {
641
+ const nodeTypeDefsMap = import_react3.default.useMemo(() => {
430
642
  if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return void 0;
431
643
  return new Map(nodeTypeDefs.map((d) => [d.slug, d]));
432
644
  }, [nodeTypeDefs]);
433
- const edgeTypeDefsMap = import_react2.default.useMemo(() => {
645
+ const edgeTypeDefsMap = import_react3.default.useMemo(() => {
434
646
  if (!(edgeTypeDefs == null ? void 0 : edgeTypeDefs.length)) return void 0;
435
647
  return new Map(edgeTypeDefs.map((d) => [d.slug, d]));
436
648
  }, [edgeTypeDefs]);
437
- const nodeTypes = import_react2.default.useMemo(
438
- () => createNodeTypes(nodeRenderers, nodeTypeDefsMap),
439
- [nodeRenderers, nodeTypeDefsMap]
649
+ const nodeTypes = import_react3.default.useMemo(
650
+ () => createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode),
651
+ [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode]
440
652
  );
441
- const styledEdges = import_react2.default.useMemo(
442
- () => {
443
- var _a2;
444
- return applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
445
- },
446
- [data == null ? void 0 : data.edges, edgeTypeDefsMap]
653
+ const customEdgeTypes = import_react3.default.useMemo(
654
+ () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
655
+ [edgeRenderers, edgeTypeDefsMap]
447
656
  );
657
+ const styledEdges = import_react3.default.useMemo(() => {
658
+ var _a2;
659
+ let edges = applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
660
+ if (edgeRenderers) {
661
+ edges = edges.map((edge) => {
662
+ const slug = edge.edgeTypeSlug;
663
+ if (slug && edgeRenderers[slug]) {
664
+ return __spreadProps(__spreadValues({}, edge), { type: slug });
665
+ }
666
+ return edge;
667
+ });
668
+ }
669
+ return edges;
670
+ }, [data == null ? void 0 : data.edges, edgeTypeDefsMap, edgeRenderers]);
448
671
  if (!data) return null;
449
- const defaultViewport = !fitView && data.viewport ? data.viewport : void 0;
450
- return /* @__PURE__ */ import_react2.default.createElement(import_react3.ReactFlowProvider, null, /* @__PURE__ */ import_react2.default.createElement(
672
+ const resolvedDefaultViewport = defaultViewportProp != null ? defaultViewportProp : !fitView && data.viewport ? data.viewport : void 0;
673
+ return /* @__PURE__ */ import_react3.default.createElement(import_react4.ReactFlowProvider, null, /* @__PURE__ */ import_react3.default.createElement(
451
674
  "div",
452
675
  {
453
676
  className,
454
677
  style: __spreadValues({ width: "100%", height: "100%" }, style)
455
678
  },
456
- /* @__PURE__ */ import_react2.default.createElement(
457
- import_react3.ReactFlow,
679
+ /* @__PURE__ */ import_react3.default.createElement(
680
+ import_react4.ReactFlow,
458
681
  {
459
682
  nodes: (_a = data.nodes) != null ? _a : [],
460
683
  edges: styledEdges,
461
684
  nodeTypes,
462
- defaultViewport,
685
+ edgeTypes: customEdgeTypes,
686
+ defaultViewport: resolvedDefaultViewport,
463
687
  fitView,
464
688
  onNodeClick,
465
689
  onEdgeClick,
690
+ onMoveEnd: onViewportChange ? ((_, vp) => {
691
+ onViewportChange(vp);
692
+ }) : void 0,
466
693
  nodesDraggable: interactive ? void 0 : false,
467
694
  nodesConnectable: false,
468
695
  elementsSelectable: interactive || !!onNodeClick || !!onEdgeClick,
@@ -471,7 +698,23 @@ function FlowRenderer({
471
698
  zoomOnPinch: interactive,
472
699
  zoomOnDoubleClick: false
473
700
  },
474
- background && /* @__PURE__ */ import_react2.default.createElement(import_react3.Background, null)
701
+ background && /* @__PURE__ */ import_react3.default.createElement(import_react4.Background, null),
702
+ controls && /* @__PURE__ */ import_react3.default.createElement(import_react4.Controls, null),
703
+ minimap && /* @__PURE__ */ import_react3.default.createElement(
704
+ import_react4.MiniMap,
705
+ {
706
+ nodeColor: minimapNodeColor
707
+ }
708
+ ),
709
+ bounds && /* @__PURE__ */ import_react3.default.createElement(
710
+ FocusHandler,
711
+ {
712
+ bounds,
713
+ padding: focusPadding != null ? focusPadding : 0.1,
714
+ animation: focusAnimation != null ? focusAnimation : true
715
+ }
716
+ ),
717
+ children
475
718
  )
476
719
  ));
477
720
  }