{"version":3,"file":"index-DIi7ls1d.cjs","sources":["../src/app/pages/AddEditNodePage/MetricQueryField.jsx","../src/app/pages/AddEditNodePage/catalogTables.js","../src/app/pages/AddEditNodePage/djNodeBadges.js","../src/app/pages/AddEditNodePage/djEditorTheme.js","../src/app/pages/AddEditNodePage/NodeQueryField.jsx","../src/app/pages/AddEditNodePage/MetricMetadataFields.jsx","../src/app/pages/AddEditNodePage/UpstreamNodeField.jsx","../src/app/pages/AddEditNodePage/OwnersField.jsx","../src/app/pages/AddEditNodePage/TagsField.jsx","../src/app/pages/AddEditNodePage/NamespaceField.jsx","../src/app/pages/AddEditNodePage/AlertMessage.jsx","../src/app/pages/AddEditNodePage/DisplayNameField.jsx","../src/app/pages/AddEditNodePage/DescriptionField.jsx","../src/app/pages/AddEditNodePage/NodeModeField.jsx","../src/app/pages/AddEditNodePage/RequiredDimensionsSelect.jsx","../src/app/pages/AddEditNodePage/ColumnsSelect.jsx","../src/app/pages/AddEditNodePage/CustomMetadataField.jsx","../src/app/pages/AddEditNodePage/index.jsx"],"sourcesContent":["/**\n * Metric aggregate expression input field, which consists of a CodeMirror SQL\n * editor with autocompletion for node columns and syntax highlighting.\n *\n * Supports both:\n * - Regular metrics: autocomplete from upstream node columns\n * - Derived metrics: autocomplete from available metric names\n */\nimport React from 'react';\nimport { ErrorMessage, Field, useFormikContext } from 'formik';\nimport CodeMirror from '@uiw/react-codemirror';\nimport { langs } from '@uiw/codemirror-extensions-langs';\n\nexport const MetricQueryField = ({ djClient, value }) => {\n  const [schema, setSchema] = React.useState({});\n  const [availableMetrics, setAvailableMetrics] = React.useState([]);\n  const formik = useFormikContext();\n  const upstreamNode = formik.values['upstream_node'];\n  // Memoize the sql extension on schema so it only rebuilds when the schema\n  // actually changes. Without this, every parent render produces a new\n  // sqlExt reference and CodeMirror re-registers extensions — which closes\n  // any open autocomplete dropdown.\n  const sqlExt = React.useMemo(() => langs.sql({ schema }), [schema]);\n\n  // Load available metrics for derived metric autocomplete\n  React.useEffect(() => {\n    async function fetchMetrics() {\n      try {\n        const metrics = await djClient.metrics();\n        setAvailableMetrics(metrics || []);\n      } catch (err) {\n        console.error('Failed to load metrics for autocomplete:', err);\n      }\n    }\n    fetchMetrics();\n  }, [djClient]);\n\n  // Build the autocomplete schema once when upstream node or metrics change.\n  // Doing this from inside an autocomplete source (per keystroke) caused a\n  // re-render mid-completion which dismissed the dropdown.\n  React.useEffect(() => {\n    let cancelled = false;\n    async function loadSchema() {\n      const next = {};\n      if (upstreamNode && upstreamNode.trim() !== '') {\n        try {\n          const nodeDetails = await djClient.node(upstreamNode);\n          nodeDetails?.columns?.forEach(col => {\n            next[col.name] = [];\n          });\n        } catch (err) {\n          console.error('Failed to load upstream node columns:', err);\n        }\n      }\n      availableMetrics.forEach(metricName => {\n        next[metricName] = [];\n      });\n      if (!cancelled) setSchema(next);\n    }\n    loadSchema();\n    return () => {\n      cancelled = true;\n    };\n  }, [djClient, upstreamNode, availableMetrics]);\n\n  const updateFormik = val => {\n    formik.setFieldValue('aggregate_expression', val);\n  };\n\n  // Determine the label and help text based on whether upstream is selected\n  const isDerivedMode = !upstreamNode || upstreamNode.trim() === '';\n  const labelText = isDerivedMode\n    ? 'Derived Metric Expression *'\n    : 'Aggregate Expression *';\n  const helpText = isDerivedMode\n    ? 'Reference other metrics using their full names (e.g., namespace.metric_name / namespace.other_metric)'\n    : 'Use aggregate functions on columns from the upstream node (e.g., SUM(column_name))';\n\n  return (\n    <div className=\"QueryInput MetricQueryInput NodeCreationInput\">\n      <ErrorMessage name=\"query\" component=\"span\" />\n      <label htmlFor=\"Query\">{labelText}</label>\n      <p\n        className=\"field-help-text\"\n        style={{ fontSize: '0.85em', color: '#666', marginBottom: '8px' }}\n      >\n        {helpText}\n      </p>\n      <Field\n        type=\"textarea\"\n        style={{ display: 'none' }}\n        as=\"textarea\"\n        name=\"aggregate_expression\"\n        id=\"Query\"\n      />\n      <div role=\"button\" tabIndex={0} className=\"relative flex bg-[#282a36]\">\n        <CodeMirror\n          id={'aggregate_expression'}\n          name={'aggregate_expression'}\n          extensions={[sqlExt]}\n          value={value}\n          options={{\n            theme: 'default',\n            lineNumbers: true,\n          }}\n          width=\"100%\"\n          height=\"100px\"\n          style={{\n            margin: '0 0 23px 0',\n            flex: 1,\n            fontSize: '110%',\n            textAlign: 'left',\n          }}\n          onChange={(value, viewUpdate) => {\n            updateFormik(value);\n          }}\n        />\n      </div>\n    </div>\n  );\n};\n","// Matches catalog.schema.table (3-part dot-separated identifiers, backtick-quoted or plain)\nconst CATALOG_TABLE_PATTERN =\n  /`?([a-zA-Z_][a-zA-Z0-9_]*)`?\\.`?([a-zA-Z_][a-zA-Z0-9_]*)`?\\.`?([a-zA-Z_][a-zA-Z0-9_]*)`?/;\n\n/**\n * Extracts all `catalog.schema.table` references in `sql` whose catalog is in\n * `knownCatalogs` (case-insensitive). Returns deduplicated [catalog, schema, table] tuples.\n */\nexport function extractCatalogTables(sql, knownCatalogs) {\n  const re = new RegExp(CATALOG_TABLE_PATTERN.source, 'g');\n  const known = new Set(knownCatalogs.map(c => c.toLowerCase()));\n  const seen = new Set();\n  const out = [];\n  let m;\n  while ((m = re.exec(sql)) !== null) {\n    const [, catalog, schema, table] = m;\n    if (!known.has(catalog.toLowerCase())) continue;\n    const key = `${catalog}.${schema}.${table}`;\n    if (seen.has(key)) continue;\n    seen.add(key);\n    out.push([catalog, schema, table]);\n  }\n  return out;\n}\n","/**\n * CodeMirror 6 extension that styles DJ node references in the SQL editor\n * as inline chips with a status indicator.\n *\n * Catalog-qualified tables (`catalog.schema.table`, where `catalog` is in\n * the known-catalogs list) get wrapped in a chip whose color + trailing icon\n * reflect the auto-register flow:\n *\n *   ⟳  registering   ✓  valid (registered or already known)   ✗  invalid\n *\n * The extension is purely a display layer — it reads status from a\n * caller-provided `getStatus(key)` and never writes data itself. The host\n * component (NodeQueryField) drives the registration flow and dispatches\n * `refreshBadges` whenever status changes so decorations rebuild even when\n * the doc itself hasn't changed.\n */\nimport { ViewPlugin, Decoration, hoverTooltip } from '@codemirror/view';\nimport { StateEffect } from '@codemirror/state';\n\n// Match dotted identifiers of any length (2+ segments). Greedy `+` keeps\n// `a.b.c.d` as a single match instead of splitting into `a.b` + `.c.d`.\n// Each segment is `[a-zA-Z_]\\w*`, optionally backtick-quoted.\nconst DOTTED_REF_RE =\n  /`?[a-zA-Z_][a-zA-Z0-9_]*`?(?:\\.`?[a-zA-Z_][a-zA-Z0-9_]*`?)+/g;\n\nfunction unbacktick(s) {\n  return s.replace(/`/g, '');\n}\n\nexport const refreshBadges = StateEffect.define();\n\nfunction classForStatus(statusKind) {\n  switch (statusKind) {\n    case 'registering':\n      return 'dj-node-chip--registering';\n    case 'valid':\n      return 'dj-node-chip--valid';\n    case 'warning':\n      return 'dj-node-chip--warning';\n    case 'invalid':\n      return 'dj-node-chip--invalid';\n    default:\n      return 'dj-node-chip--unknown';\n  }\n}\n\nfunction buildDecorations(view, getStatus, getKnownCatalogs) {\n  const known = new Set((getKnownCatalogs() || []).map(c => c.toLowerCase()));\n  const doc = view.state.doc;\n  const ranges = [];\n\n  for (const { from, to } of view.visibleRanges) {\n    const slice = doc.sliceString(from, to);\n    DOTTED_REF_RE.lastIndex = 0;\n    let m;\n    while ((m = DOTTED_REF_RE.exec(slice)) !== null) {\n      const whole = m[0];\n      const key = unbacktick(whole);\n      const status = getStatus(key);\n      const segments = key.split('.');\n\n      let refType;\n      if (status?.refType) {\n        // validateNode told us what this is; honor that.\n        refType = status.refType;\n      } else if (\n        segments.length === 3 &&\n        known.has(segments[0].toLowerCase())\n      ) {\n        // 3-part with a known catalog: candidate source registration.\n        refType = 'source';\n      } else {\n        // No status entry and not a catalog-qualified table — skip.\n        // This avoids false positives on `alias.column` patterns.\n        continue;\n      }\n\n      const cls = `dj-node-chip dj-node-chip--${refType} ${classForStatus(\n        status?.kind,\n      )}`;\n      const start = from + m.index;\n      const end = start + whole.length;\n      ranges.push({\n        from: start,\n        to: end,\n        deco: Decoration.mark({\n          class: cls,\n          attributes: status?.message ? { title: status.message } : undefined,\n        }),\n      });\n    }\n  }\n\n  ranges.sort((a, b) => a.from - b.from || a.to - b.to);\n  return Decoration.set(ranges.map(r => r.deco.range(r.from, r.to)));\n}\n\n/**\n * Factory. Returns a CodeMirror extension that decorates DJ node refs.\n *\n *   getStatus(key)       — returns { kind, message? } | undefined for `catalog.schema.table`\n *   getKnownCatalogs()   — returns string[] (lowercase catalog names)\n *\n * Both are read on every rebuild, so pass ref-backed closures and update\n * the ref synchronously before dispatching `refreshBadges` — otherwise the\n * extension reads pre-update state.\n */\nexport function djNodeBadges({ getStatus, getKnownCatalogs }) {\n  return ViewPlugin.fromClass(\n    class {\n      constructor(view) {\n        this.decorations = buildDecorations(view, getStatus, getKnownCatalogs);\n      }\n      update(update) {\n        const refreshed = update.transactions.some(tr =>\n          tr.effects.some(e => e.is(refreshBadges)),\n        );\n        if (update.docChanged || update.viewportChanged || refreshed) {\n          this.decorations = buildDecorations(\n            update.view,\n            getStatus,\n            getKnownCatalogs,\n          );\n        }\n      }\n    },\n    { decorations: v => v.decorations },\n  );\n}\n\n/**\n * Find the dotted ref under a given document position. Returns\n * `{ key, from, to }` if the position falls inside a 2+-segment dotted\n * identifier, else null. Used by the hover tooltip to identify which chip\n * the cursor is on.\n */\nexport function refAtPos(view, pos) {\n  const line = view.state.doc.lineAt(pos);\n  DOTTED_REF_RE.lastIndex = 0;\n  let m;\n  while ((m = DOTTED_REF_RE.exec(line.text)) !== null) {\n    const start = line.from + m.index;\n    const end = start + m[0].length;\n    if (pos >= start && pos <= end) {\n      return { key: unbacktick(m[0]), from: start, to: end };\n    }\n  }\n  return null;\n}\n\nexport function renderTooltipDom(status, refKey) {\n  const wrap = document.createElement('div');\n  wrap.className = 'dj-node-tooltip';\n\n  const node = status.node || {};\n\n  // Header — type pill + qualified name.\n  const header = document.createElement('div');\n  header.className = 'dj-node-tooltip__header';\n\n  const pill = document.createElement('span');\n  pill.className = `dj-node-chip dj-node-chip--${status.refType || 'node'}`;\n  pill.textContent = status.refType || 'node';\n  header.appendChild(pill);\n\n  const name = document.createElement('span');\n  name.className = 'dj-node-tooltip__name';\n  name.textContent = node.name || refKey;\n  header.appendChild(name);\n\n  wrap.appendChild(header);\n\n  // Special-case transient + error states — no metadata grid, just one line.\n  if (status.kind === 'invalid') {\n    const note = document.createElement('div');\n    note.className = 'dj-node-tooltip__note';\n    note.textContent = 'Not found in DJ.';\n    wrap.appendChild(note);\n    return wrap;\n  }\n  if (status.kind === 'registering') {\n    const note = document.createElement('div');\n    note.className = 'dj-node-tooltip__note';\n    note.textContent = 'Registering…';\n    wrap.appendChild(note);\n    return wrap;\n  }\n\n  // Metadata grid (2 columns of label/value pairs).\n  const grid = document.createElement('div');\n  grid.className = 'dj-node-tooltip__grid';\n  const addCell = (label, value) => {\n    if (value == null || value === '') return;\n    const cell = document.createElement('div');\n    cell.className = 'dj-node-tooltip__cell';\n    const l = document.createElement('span');\n    l.className = 'dj-node-tooltip__label';\n    l.textContent = label;\n    const v = document.createElement('span');\n    v.className = 'dj-node-tooltip__value';\n    v.textContent = value;\n    cell.appendChild(l);\n    cell.appendChild(v);\n    grid.appendChild(cell);\n  };\n  if (node.status) addCell('Status', node.status);\n  if (node.version) addCell('Version', node.version);\n  if (node.mode) addCell('Mode', node.mode);\n  if (Array.isArray(node.columns)) {\n    addCell('Columns', String(node.columns.length));\n  }\n  if (grid.childElementCount > 0) wrap.appendChild(grid);\n\n  // Description (truncated if long).\n  if (node.description) {\n    const d = document.createElement('div');\n    d.className = 'dj-node-tooltip__description';\n    const text = node.description;\n    d.textContent = text.length > 280 ? text.slice(0, 277) + '…' : text;\n    wrap.appendChild(d);\n  }\n\n  // Column list — scrollable. The point of the popover for someone writing\n  // SQL is to see what's available to SELECT without leaving the editor.\n  if (Array.isArray(node.columns) && node.columns.length > 0) {\n    const list = document.createElement('div');\n    list.className = 'dj-node-tooltip__columns';\n    for (const col of node.columns) {\n      const row = document.createElement('div');\n      row.className = 'dj-node-tooltip__col-row';\n\n      const n = document.createElement('span');\n      n.className = 'dj-node-tooltip__col-name';\n      n.textContent = col.name;\n      row.appendChild(n);\n\n      // Mark columns that link to a dimension — useful signal for cube/SQL work.\n      if (col.dimension || col.dimension_column) {\n        const tag = document.createElement('span');\n        tag.className = 'dj-node-tooltip__col-tag';\n        tag.textContent = 'dim';\n        tag.title = col.dimension?.name\n          ? `Links to ${col.dimension.name}`\n          : 'Linked dimension';\n        row.appendChild(tag);\n      }\n\n      const t = document.createElement('span');\n      t.className = 'dj-node-tooltip__col-type';\n      // Struct/array types can be enormous (multi-line) — keep it on one line\n      // and let CSS clamp; full info is on the node page.\n      t.textContent = (col.type || '').split('\\n')[0];\n      t.title = col.type || '';\n      row.appendChild(t);\n\n      list.appendChild(row);\n    }\n    wrap.appendChild(list);\n  }\n\n  // Footer link.\n  if (node.name) {\n    const foot = document.createElement('div');\n    foot.className = 'dj-node-tooltip__footer';\n    const link = document.createElement('a');\n    link.href = `/nodes/${encodeURIComponent(node.name)}`;\n    link.target = '_blank';\n    link.rel = 'noreferrer noopener';\n    link.textContent = 'Open node →';\n    foot.appendChild(link);\n    wrap.appendChild(foot);\n  }\n\n  return wrap;\n}\n\n// Cache of node-detail fetches so re-hovering the same chip doesn't refetch.\n// Lives at module scope (one editor + dom = one cache) — small enough that\n// not bothering with an LRU.\nconst nodeDetailsCache = new Map();\n\n/**\n * Hover tooltip extension. Pairs with djNodeBadges so the same\n * `getStatus` source of truth drives the popover content. Additionally\n * lazy-fetches the full node (columns, description, mode, version) on\n * hover via `fetchNodeDetails`, and re-renders the tooltip in place\n * when the promise resolves.\n */\nexport function djNodeHoverTooltip({\n  getStatus,\n  getKnownCatalogs,\n  fetchNodeDetails,\n}) {\n  return hoverTooltip(\n    (view, pos) => {\n      const hit = refAtPos(view, pos);\n      if (!hit) return null;\n      const status = getStatus(hit.key);\n      if (!status) {\n        // No status entry; only show tooltip for catalog-qualified refs that\n        // would render as a chip — otherwise we'd pop up on every `t.column`.\n        const known = new Set(\n          (getKnownCatalogs() || []).map(c => c.toLowerCase()),\n        );\n        const segments = hit.key.split('.');\n        if (segments.length !== 3 || !known.has(segments[0].toLowerCase())) {\n          return null;\n        }\n      }\n      return {\n        pos: hit.from,\n        end: hit.to,\n        above: true,\n        create: () => {\n          const baseStatus = status || { refType: 'source' };\n          const dom = renderTooltipDom(baseStatus, hit.key);\n\n          // Lazy-fetch the full node so we can show columns + description.\n          // The validateNode dep object only carries {name, type, status}.\n          if (\n            fetchNodeDetails &&\n            baseStatus.kind !== 'invalid' &&\n            baseStatus.kind !== 'registering'\n          ) {\n            const cached = nodeDetailsCache.get(hit.key);\n            const promise = cached || fetchNodeDetails(hit.key);\n            if (!cached) nodeDetailsCache.set(hit.key, promise);\n\n            Promise.resolve(promise)\n              .then(full => {\n                if (!full) return;\n                const richDom = renderTooltipDom(\n                  {\n                    ...baseStatus,\n                    node: { ...(baseStatus.node || {}), ...full },\n                  },\n                  hit.key,\n                );\n                if (dom.parentNode) {\n                  dom.parentNode.replaceChild(richDom, dom);\n                } else {\n                  // Tooltip already detached — swap children so future refs\n                  // see the rich content.\n                  dom.replaceChildren(...richDom.childNodes);\n                }\n              })\n              .catch(() => {\n                // Soft-fail — leave the bare header tooltip in place.\n              });\n          }\n\n          return { dom };\n        },\n      };\n    },\n    { hoverTime: 150 },\n  );\n}\n","/**\n * CodeMirror 6 theme tuned to share a palette with the rest of the DJ UI\n * (especially the `.node_type__*` pills and the `.dj-node-chip--*` chips\n * rendered inline by djNodeBadges). The goal: syntax colors and chip\n * colors come from the same family, so chips read as theme-native rather\n * than as foreign decoration.\n */\nimport { EditorView } from '@codemirror/view';\nimport { HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { tags as t } from '@lezer/highlight';\n\n// Palette — kept in one place so it stays in sync with node-creation.scss.\nconst palette = {\n  bg: '#fbfbfd',\n  surface: '#f6f6f9',\n  gutter: '#9aa2b1',\n  selection: '#dbe2ec',\n  caret: '#3b3f46',\n  text: '#27303d',\n  muted: '#8b94a5',\n  keyword: '#6b3aa0', // matches cube/dimension violet family\n  string: '#0e7c5a', // forest green\n  number: '#a96621', // warm amber (same as dimension chip)\n  operator: '#475569',\n  functionName: '#0063b4', // transform blue\n  punctuation: '#5c6573',\n  comment: '#9ca3af',\n};\n\nexport const djEditorTheme = EditorView.theme(\n  {\n    '&': {\n      color: palette.text,\n      backgroundColor: palette.bg,\n      fontSize: '13px',\n    },\n    '.cm-content': {\n      caretColor: palette.caret,\n      fontFamily:\n        '\"JetBrains Mono\", \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace',\n    },\n    '.cm-cursor, .cm-dropCursor': { borderLeftColor: palette.caret },\n    '&.cm-focused .cm-selectionBackground, ::selection, .cm-selectionBackground':\n      {\n        backgroundColor: palette.selection,\n      },\n    '.cm-activeLine': {\n      backgroundColor: 'rgba(99, 102, 241, 0.05)',\n    },\n    '.cm-gutters': {\n      backgroundColor: palette.surface,\n      color: palette.gutter,\n      border: 'none',\n    },\n    '.cm-activeLineGutter': {\n      backgroundColor: 'rgba(99, 102, 241, 0.08)',\n      color: palette.text,\n    },\n    '.cm-lineNumbers .cm-gutterElement': {\n      padding: '0 8px 0 6px',\n    },\n    '.cm-foldGutter .cm-gutterElement': {\n      color: palette.muted,\n    },\n    '.cm-tooltip': {\n      background: '#ffffff',\n      border: '1px solid #e2e8f0',\n      borderRadius: '6px',\n      boxShadow: '0 4px 12px rgba(15, 23, 42, 0.06)',\n    },\n    '.cm-tooltip-autocomplete > ul > li[aria-selected]': {\n      background: '#eef2ff',\n      color: palette.text,\n    },\n    '.cm-matchingBracket, .cm-nonmatchingBracket': {\n      backgroundColor: '#fef3c7',\n      outline: 'none',\n    },\n    '.cm-panels': {\n      backgroundColor: palette.surface,\n      color: palette.text,\n    },\n  },\n  { dark: false },\n);\n\nconst highlight = HighlightStyle.define([\n  {\n    tag: [t.keyword, t.modifier, t.controlKeyword, t.operatorKeyword],\n    color: palette.keyword,\n    fontWeight: '500',\n  },\n  { tag: [t.string, t.special(t.string)], color: palette.string },\n  { tag: [t.number, t.bool, t.null], color: palette.number },\n  {\n    tag: [t.function(t.variableName), t.function(t.propertyName)],\n    color: palette.functionName,\n  },\n  {\n    tag: [t.operator, t.compareOperator, t.arithmeticOperator, t.logicOperator],\n    color: palette.operator,\n  },\n  {\n    tag: [t.punctuation, t.paren, t.brace, t.bracket, t.separator],\n    color: palette.punctuation,\n  },\n  {\n    tag: [t.variableName, t.propertyName, t.attributeName],\n    color: palette.text,\n  },\n  { tag: [t.typeName, t.className], color: palette.functionName },\n  {\n    tag: [t.comment, t.lineComment, t.blockComment],\n    color: palette.comment,\n    fontStyle: 'italic',\n  },\n  { tag: t.invalid, color: '#cc2222' },\n]);\n\nexport const djEditorExtensions = [\n  djEditorTheme,\n  syntaxHighlighting(highlight),\n];\n","/**\n * SQL query input field, which consists of a CodeMirror SQL editor with autocompletion\n * (for node names and columns) and syntax highlighting.\n */\nimport React from 'react';\nimport { ErrorMessage, Field, useFormikContext } from 'formik';\nimport CodeMirror from '@uiw/react-codemirror';\nimport { langs } from '@uiw/codemirror-extensions-langs';\nimport { extractCatalogTables } from './catalogTables';\nimport {\n  djNodeBadges,\n  djNodeHoverTooltip,\n  refreshBadges,\n} from './djNodeBadges';\nimport { djEditorExtensions } from './djEditorTheme';\n\n// Friendly labels for the most common DJ error codes the validate endpoint\n// returns from a node query. Falls back to a title-cased version of the code.\nconst ERROR_CODE_LABELS = {\n  INVALID_SQL_QUERY: 'Invalid SQL',\n  TYPE_INFERENCE: 'Type inference',\n  INVALID_COLUMN: 'Invalid column',\n  INVALID_ARGUMENTS_TO_FUNCTION: 'Invalid function arguments',\n  MISSING_COLUMNS: 'Missing columns',\n  UNKNOWN_NODE: 'Unknown node',\n  MISSING_PARENT: 'Missing parent',\n  NODE_TYPE_ERROR: 'Node type',\n  NOT_IMPLEMENTED_ERROR: 'Not implemented',\n};\n\nconst errorLabel = code => {\n  if (code === undefined || code === null || code === '') return 'Error';\n  const key = String(code);\n  if (ERROR_CODE_LABELS[key]) return ERROR_CODE_LABELS[key];\n  return key\n    .toLowerCase()\n    .split('_')\n    .map(word => (word ? word[0].toUpperCase() + word.slice(1) : ''))\n    .join(' ');\n};\n\nexport const NodeQueryField = ({ djClient, value }) => {\n  // Schema is `{ [nodeName]: string[] }` — passed to @codemirror/lang-sql so\n  // it can offer table + column autocompletion. Must be an OBJECT, not array,\n  // and every update must produce a new reference so React re-renders and\n  // langs.sql() rebuilds with the latest map.\n  const [schema, setSchema] = React.useState({});\n  const formik = useFormikContext();\n  const sqlExt = React.useMemo(() => langs.sql({ schema }), [schema]);\n  const autoRegisterTimer = React.useRef(null);\n  const validateTimer = React.useRef(null);\n  const registeredTables = React.useRef(new Set());\n  // useRef so the onChange closure always sees the latest catalog list\n  const knownCatalogsRef = React.useRef([]);\n\n  // Query-level validation errors (parse failures, type-inference failures, etc.)\n  // surfaced from /nodes/validate's `errors` field. Rendered as a banner under\n  // the editor so the user sees *why* their SQL is invalid, not just that it is.\n  const [queryErrors, setQueryErrors] = React.useState([]);\n\n  // Per-`catalog.schema.table` registration status, surfaced as badges in\n  // the editor. Mirrored into a ref so the CodeMirror extension (built once,\n  // memoized below) can read the latest value without rebuilding.\n  const [tableStatus, setTableStatus] = React.useState({});\n  const tableStatusRef = React.useRef(tableStatus);\n  React.useEffect(() => {\n    tableStatusRef.current = tableStatus;\n  }, [tableStatus]);\n  const editorViewRef = React.useRef(null);\n  const setStatus = React.useCallback((key, status) => {\n    // Update the ref synchronously so the ViewPlugin's getStatus() closure\n    // sees the new value on the redraw we're about to dispatch.\n    // setTableStatus only schedules the React rerender (next tick) which is\n    // too late for the dispatch below.\n    tableStatusRef.current = { ...tableStatusRef.current, [key]: status };\n    setTableStatus(tableStatusRef.current);\n    if (editorViewRef.current) {\n      editorViewRef.current.dispatch({ effects: refreshBadges.of(null) });\n    }\n  }, []);\n\n  React.useEffect(() => {\n    if (typeof djClient.catalogs !== 'function') return;\n    Promise.resolve(djClient.catalogs())\n      .then(catalogs => {\n        knownCatalogsRef.current = (catalogs || []).map(c =>\n          c.name.toLowerCase(),\n        );\n      })\n      .catch(() => {\n        // Auto-register is best-effort; failing to load catalogs just disables it.\n      });\n  }, [djClient]);\n\n  const initialAutocomplete = async context => {\n    // Based on the parsed prefix, we load node names with that prefix\n    // into the autocomplete schema. At this stage we don't load the columns\n    // to save on unnecessary calls\n    const word = context.matchBefore(/[\\.\\w]*/);\n    const matches = await djClient.nodes(word.text);\n    setSchema(prev => {\n      const next = { ...prev };\n      let changed = false;\n      for (const nodeName of matches) {\n        if (next[nodeName] === undefined) {\n          next[nodeName] = [];\n          changed = true;\n        }\n      }\n      return changed ? next : prev;\n    });\n  };\n\n  const updateFormik = val => {\n    formik.setFieldValue('query', val);\n  };\n\n  const updateAutocomplete = async (value, _) => {\n    // If a particular node has been chosen, load the columns of that node into\n    // the autocomplete schema for column-level autocompletion. Mutate via a\n    // functional setState so every update produces a new map reference and\n    // langs.sql sees the change.\n    for (const nodeName of Object.keys(schema)) {\n      if (value.includes(nodeName) && schema[nodeName].length === 0) {\n        const nodeDetails = await djClient.node(nodeName);\n        const cols = (nodeDetails?.columns || []).map(col => col.name);\n        setSchema(prev => ({ ...prev, [nodeName]: cols }));\n      }\n    }\n\n    // Auto-register any catalog-qualified tables typed in the SQL\n    if (knownCatalogsRef.current.length > 0) {\n      clearTimeout(autoRegisterTimer.current);\n      autoRegisterTimer.current = setTimeout(\n        () => autoRegisterCatalogTables(value),\n        600,\n      );\n    }\n\n    // Validate the in-progress query against DJ to discover which 2-part\n    // refs (`namespace.name`) resolve to real nodes vs. are missing.\n    clearTimeout(validateTimer.current);\n    validateTimer.current = setTimeout(() => validateRefs(value), 700);\n  };\n\n  const validateRefs = async sql => {\n    if (typeof djClient.validateNode !== 'function') return;\n    const fv = formik.values || {};\n    if (!fv.type) return; // need a node type to validate\n    let response;\n    try {\n      response = await djClient.validateNode(\n        fv.type,\n        fv.name || '__draft__',\n        fv.display_name || 'Draft',\n        fv.description || '',\n        sql,\n      );\n    } catch {\n      return; // best-effort; ignore network failures\n    }\n    const json = response?.json || {};\n    const deps = json.dependencies || [];\n    const missing = json.missing_parents || [];\n    setQueryErrors(Array.isArray(json.errors) ? json.errors : []);\n    // Update the ref synchronously in one shot before dispatching, so the\n    // ViewPlugin only redraws once even though we set many keys.\n    const next = { ...tableStatusRef.current };\n    for (const dep of deps) {\n      // `dependencies` is a list of full node objects ({name, type, status, ...}).\n      // Use `type` to color the chip per node kind (source/dimension/…) and\n      // `status` to flag nodes that resolve but are themselves unhealthy\n      // (e.g. broken upstream, drifted columns). We also keep the whole\n      // object around so the hover popover can show description / version\n      // / mode without re-fetching.\n      const name = typeof dep === 'string' ? dep : dep?.name;\n      if (!name) continue;\n      const nodeType = typeof dep === 'object' ? dep.type : undefined;\n      const nodeStatus = typeof dep === 'object' ? dep.status : undefined;\n      const kind = nodeStatus && nodeStatus !== 'valid' ? 'warning' : 'valid';\n      next[name] = {\n        kind,\n        refType: nodeType || 'node',\n        node: typeof dep === 'object' ? dep : undefined,\n        message:\n          kind === 'warning' ? `Node \\`${name}\\` is ${nodeStatus}` : undefined,\n      };\n    }\n    for (const m of missing) {\n      // `missing_parents` is a list of bare name strings.\n      const name = typeof m === 'string' ? m : m?.name;\n      if (!name) continue;\n      next[name] = {\n        kind: 'invalid',\n        refType: 'node',\n        message: `Node \\`${name}\\` not found`,\n      };\n    }\n    tableStatusRef.current = next;\n    setTableStatus(next);\n    if (editorViewRef.current) {\n      editorViewRef.current.dispatch({ effects: refreshBadges.of(null) });\n    }\n  };\n\n  const autoRegisterCatalogTables = async sql => {\n    const tables = extractCatalogTables(sql, knownCatalogsRef.current);\n    for (const [catalog, tableSchema, table] of tables) {\n      const key = `${catalog}.${tableSchema}.${table}`;\n      if (registeredTables.current.has(key)) continue;\n      // If autocomplete already saw this node, DJ knows about it — skip silently\n      if (schema[key] !== undefined) {\n        registeredTables.current.add(key);\n        setStatus(key, { kind: 'valid' });\n        continue;\n      }\n      registeredTables.current.add(key);\n      setStatus(key, { kind: 'registering' });\n\n      let response;\n      try {\n        response = await djClient.registerTable(\n          catalog,\n          tableSchema,\n          table,\n          '',\n        );\n      } catch (err) {\n        registeredTables.current.delete(key);\n        setStatus(key, {\n          kind: 'invalid',\n          message: err?.message || 'Failed to register table',\n        });\n        continue;\n      }\n      const { status, json } = response;\n      if (status === 200 || status === 201) {\n        const nodeName = json?.name || key;\n        const columns = (json?.columns || []).map(col => col.name);\n        setSchema(prev => {\n          const next = { ...prev, [nodeName]: columns };\n          if (table && table !== nodeName) next[table] = columns;\n          return next;\n        });\n        setStatus(key, { kind: 'valid' });\n      } else if (status === 409) {\n        // 409 = already exists; treat as valid.\n        setStatus(key, { kind: 'valid' });\n      } else {\n        registeredTables.current.delete(key);\n        setStatus(key, {\n          kind: 'invalid',\n          message: json?.message || `Registration failed (HTTP ${status})`,\n        });\n      }\n    }\n  };\n\n  const badgeExt = React.useMemo(\n    () =>\n      djNodeBadges({\n        getStatus: key => tableStatusRef.current[key],\n        getKnownCatalogs: () => knownCatalogsRef.current,\n      }),\n    [],\n  );\n\n  const hoverExt = React.useMemo(\n    () =>\n      djNodeHoverTooltip({\n        getStatus: key => tableStatusRef.current[key],\n        getKnownCatalogs: () => knownCatalogsRef.current,\n        fetchNodeDetails: name => djClient.node(name).catch(() => null),\n      }),\n    [djClient],\n  );\n\n  return (\n    <div className=\"QueryInput NodeCreationInput\">\n      <ErrorMessage name=\"query\" component=\"span\" />\n      <label htmlFor=\"Query\">Query *</label>\n      <Field\n        type=\"textarea\"\n        style={{ display: 'none' }}\n        as=\"textarea\"\n        name=\"query\"\n        id=\"Query\"\n      />\n      {queryErrors.length > 0 && (\n        <div className=\"query-validation-errors\" role=\"alert\">\n          {queryErrors.map((err, idx) => (\n            <div key={idx} className=\"query-validation-error\">\n              <span className=\"query-validation-error-code\">\n                {errorLabel(err.code)}\n              </span>\n              <span className=\"query-validation-error-message\">\n                {err.message}\n              </span>\n            </div>\n          ))}\n        </div>\n      )}\n      <div role=\"button\" tabIndex={0} className=\"relative flex bg-[#282a36]\">\n        <CodeMirror\n          id={'query'}\n          name={'query'}\n          extensions={[\n            sqlExt,\n            sqlExt.language.data.of({\n              autocomplete: initialAutocomplete,\n            }),\n            ...djEditorExtensions,\n            badgeExt,\n            hoverExt,\n          ]}\n          onCreateEditor={view => {\n            editorViewRef.current = view;\n          }}\n          value={value}\n          placeholder={\n            'SELECT\\n\\tprimary_key,\\n\\tmeasure1,\\n\\tmeasure2,\\n\\tforeign_key_for_dimension1,\\n\\tforeign_key_for_dimension2\\nFROM source.source_node\\nWHERE ...'\n          }\n          options={{\n            theme: 'default',\n            lineNumbers: true,\n          }}\n          width=\"100%\"\n          height=\"400px\"\n          style={{\n            margin: '0 0 23px 0',\n            flex: 1,\n            fontSize: '110%',\n            textAlign: 'left',\n          }}\n          onChange={(value, viewUpdate) => {\n            updateFormik(value);\n            updateAutocomplete(value, viewUpdate);\n          }}\n        />\n      </div>\n    </div>\n  );\n};\n","/**\n * Metric unit select component\n */\nimport { ErrorMessage, Field } from 'formik';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { labelize } from '../../../utils/form';\n\nexport const MetricMetadataFields = () => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // Metric metadata\n  const [metricUnits, setMetricUnits] = useState([]);\n  const [metricDirections, setMetricDirections] = useState([]);\n\n  // Get metric metadata values\n  useEffect(() => {\n    const fetchData = async () => {\n      const metadata = await djClient.listMetricMetadata();\n      setMetricDirections(metadata.directions);\n      setMetricUnits(metadata.units);\n    };\n    fetchData().catch(console.error);\n  }, [djClient]);\n\n  return (\n    <div className=\"MetricMetadataFields node-row\">\n      <div className=\"NodeCreationInput NodeModeInput\">\n        <ErrorMessage name=\"metric_direction\" component=\"span\" />\n        <label htmlFor=\"MetricDirection\">Direction</label>\n        <Field as=\"select\" name=\"metric_direction\" id=\"MetricDirection\">\n          <option value=\"\"></option>\n          {metricDirections.map(direction => (\n            <option value={direction} key={direction}>\n              {labelize(direction)}\n            </option>\n          ))}\n        </Field>\n      </div>\n      <div className=\"NodeCreationInput NodeModeInput\">\n        <ErrorMessage name=\"metric_unit\" component=\"span\" />\n        <label htmlFor=\"MetricUnit\">Unit</label>\n        <Field as=\"select\" name=\"metric_unit\" id=\"MetricUnit\">\n          <option value=\"\"></option>\n          {metricUnits.map(unit => (\n            <option value={unit.name} key={unit.name}>\n              {unit.label}\n            </option>\n          ))}\n        </Field>\n      </div>\n      <div className=\"NodeCreationInput NodeModeInput\">\n        <ErrorMessage name=\"significant_digits\" component=\"span\" />\n        <label htmlFor=\"SignificantDigits\">Significant Digits</label>\n        <Field as=\"select\" name=\"significant_digits\" id=\"SignificantDigits\">\n          <option value=\"\"></option>\n          {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(val => (\n            <option value={val} key={val}>\n              {val}\n            </option>\n          ))}\n        </Field>\n      </div>\n    </div>\n  );\n};\n","/**\n * Upstream node select field.\n *\n * For regular metrics: Select a source, transform, or dimension node.\n * For derived metrics: Leave empty and reference other metrics directly in the expression.\n */\nimport { ErrorMessage } from 'formik';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { FormikSelect } from './FormikSelect';\n\nexport const UpstreamNodeField = ({ defaultValue }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // All available nodes (sources, transforms, dimensions)\n  const [availableNodes, setAvailableNodes] = useState([]);\n\n  useEffect(() => {\n    async function fetchData() {\n      const sources = await djClient.nodesWithType('source');\n      const transforms = await djClient.nodesWithType('transform');\n      const dimensions = await djClient.nodesWithType('dimension');\n      const nodes = sources.concat(transforms).concat(dimensions);\n      setAvailableNodes(\n        nodes.map(node => {\n          return {\n            value: node,\n            label: node,\n          };\n        }),\n      );\n    }\n    fetchData();\n  }, [djClient]);\n\n  return (\n    <div className=\"NodeCreationInput\">\n      <ErrorMessage name=\"upstream_node\" component=\"span\" />\n      <label htmlFor=\"upstream_node\">Upstream Node</label>\n      <p\n        className=\"field-help-text\"\n        style={{ fontSize: '0.85em', color: '#666', marginBottom: '8px' }}\n      >\n        Select a source, transform, or dimension for regular metrics. Leave\n        empty for <strong>derived metrics</strong> that reference other metrics\n        (e.g., <code>namespace.metric_a / namespace.metric_b</code>).\n      </p>\n      <span data-testid=\"select-upstream-node\">\n        <FormikSelect\n          className=\"\"\n          defaultValue={defaultValue}\n          selectOptions={availableNodes}\n          formikFieldName=\"upstream_node\"\n          placeholder=\"Select Upstream Node (optional for derived metrics)\"\n          isMulti={false}\n          isClearable={true}\n        />\n      </span>\n    </div>\n  );\n};\n","/**\n * Owner select field\n */\nimport { ErrorMessage, useField } from 'formik';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { useCurrentUser } from '../../providers/UserProvider';\nimport { FormikSelect } from './FormikSelect';\n\nexport const OwnersField = ({ defaultValue }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const { currentUser } = useCurrentUser();\n  const [, meta, helpers] = useField('owners');\n\n  const [availableUsers, setAvailableUsers] = useState([]);\n\n  useEffect(() => {\n    async function fetchData() {\n      const users = await djClient.users();\n      setAvailableUsers(\n        users.map(user => {\n          return {\n            value: user.username,\n            label: user.username,\n          };\n        }),\n      );\n    }\n    fetchData();\n  }, [djClient]);\n\n  // Seed the Formik `owners` field — FormikSelect's `defaultValue` prop\n  // is ignored because the inner <Select> uses Formik's field state.\n  // - Edit mode: seed from `defaultValue` (option objects)\n  // - Add mode: seed with currentUser so creators don't have to set\n  //   themselves as an owner manually\n  // Only seed if the field is still empty (the user hasn't touched it).\n  useEffect(() => {\n    if (meta.value && meta.value.length > 0) return;\n    if (defaultValue && defaultValue.length > 0) {\n      helpers.setValue(defaultValue.map(d => d.value));\n    } else if (currentUser) {\n      helpers.setValue([currentUser.username]);\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [defaultValue, currentUser]);\n\n  return defaultValue || currentUser ? (\n    <div className=\"NodeCreationInput\">\n      <ErrorMessage name=\"owners\" component=\"span\" />\n      <label htmlFor=\"Owners\">Owners</label>\n      <span data-testid=\"select-owner\">\n        <FormikSelect\n          className=\"\"\n          selectOptions={availableUsers}\n          formikFieldName=\"owners\"\n          placeholder=\"Select Owners\"\n          isMulti={true}\n        />\n      </span>\n    </div>\n  ) : (\n    ''\n  );\n};\n","/**\n * Tags select field\n */\nimport { ErrorMessage } from 'formik';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { FormikSelect } from './FormikSelect';\n\nexport const TagsField = ({ defaultValue }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // All available tags\n  const [tags, setTags] = useState([]);\n\n  useEffect(() => {\n    const fetchData = async () => {\n      const tags = await djClient.listTags();\n      setTags(\n        tags.map(tag => ({\n          value: tag.name,\n          label: tag.display_name,\n        })),\n      );\n    };\n    fetchData().catch(console.error);\n  }, [djClient]);\n\n  return (\n    <div className=\"TagsInput NodeCreationInput\">\n      <ErrorMessage name=\"tags\" component=\"span\" />\n      <label htmlFor=\"tags\">Tags</label>\n      <span data-testid=\"select-tags\">\n        <FormikSelect\n          isMulti={true}\n          selectOptions={tags}\n          formikFieldName=\"tags\"\n          className=\"\"\n          placeholder=\"Choose Tags\"\n          defaultValue={defaultValue}\n        />\n      </span>\n    </div>\n  );\n};\n","import { ErrorMessage } from 'formik';\nimport { FormikSelect } from './FormikSelect';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\n\nexport const NamespaceField = ({ initialNamespace }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  const [namespaces, setNamespaces] = useState([]);\n\n  // Get namespaces, only necessary when creating a node\n  useEffect(() => {\n    const fetchData = async () => {\n      const namespaces = await djClient.namespaces();\n      setNamespaces(\n        namespaces.map(m => ({\n          value: m['namespace'],\n          label: m['namespace'],\n        })),\n      );\n    };\n    fetchData().catch(console.error);\n  }, [djClient]);\n\n  return (\n    <div className=\"NamespaceInput\">\n      <ErrorMessage name=\"namespace\" component=\"span\" />\n      <label htmlFor=\"namespace\">Namespace *</label>\n      <FormikSelect\n        className=\"\"\n        selectOptions={namespaces}\n        formikFieldName=\"namespace\"\n        placeholder=\"Choose Namespace\"\n        defaultValue={{\n          value: initialNamespace,\n          label: initialNamespace,\n        }}\n      />\n    </div>\n  );\n};\n","import AlertIcon from '../../icons/AlertIcon';\n\nexport const AlertMessage = ({ message }) => {\n  return (\n    <div className=\"message alert\">\n      <AlertIcon />\n      {message}\n    </div>\n  );\n};\n","import { ErrorMessage, Field } from 'formik';\n\nexport const DisplayNameField = () => {\n  return (\n    <div className=\"DisplayNameInput NodeCreationInput\">\n      <ErrorMessage name=\"display_name\" component=\"span\" />\n      <label htmlFor=\"displayName\">Display Name *</label>\n      <Field\n        type=\"text\"\n        name=\"display_name\"\n        id=\"displayName\"\n        placeholder=\"Human readable display name\"\n      />\n    </div>\n  );\n};\n","import { ErrorMessage, Field } from 'formik';\n\nexport const DescriptionField = () => {\n  return (\n    <div className=\"DescriptionInput NodeCreationInput\">\n      <ErrorMessage name=\"description\" component=\"span\" />\n      <label htmlFor=\"Description\">Description</label>\n      <Field\n        type=\"textarea\"\n        as=\"textarea\"\n        name=\"description\"\n        id=\"Description\"\n        placeholder=\"Describe your node\"\n      />\n    </div>\n  );\n};\n","import { ErrorMessage, Field } from 'formik';\n\nexport const NodeModeField = () => {\n  return (\n    <div className=\"NodeModeInput NodeCreationInput\">\n      <ErrorMessage name=\"mode\" component=\"span\" />\n      <label htmlFor=\"Mode\">Mode</label>\n      <Field as=\"select\" name=\"mode\" id=\"Mode\">\n        <option value=\"draft\">Draft</option>\n        <option value=\"published\">Published</option>\n      </Field>\n    </div>\n  );\n};\n","/**\n * Required dimensions select component\n */\nimport { ErrorMessage, useFormikContext } from 'formik';\nimport React, { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { FormikSelect } from './FormikSelect';\n\nexport const RequiredDimensionsSelect = ({\n  defaultValue,\n  style,\n  className = '',\n}) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // Used to pull out current form values for node validation\n  const { values } = useFormikContext();\n\n  // Select options, i.e., the available dimensions\n  const [selectOptions, setSelectOptions] = useState([]);\n\n  useEffect(() => {\n    const fetchData = async () => {\n      if (values.upstream_node) {\n        const data = await djClient.node(values.upstream_node);\n        setSelectOptions(\n          data.columns.map(col => {\n            return {\n              value: col.name,\n              label: col.name,\n            };\n          }),\n        );\n      }\n    };\n    fetchData().catch(console.error);\n  }, [djClient, values.upstream_node]);\n\n  return (\n    <div className=\"RequiredDimensionsInput CubeCreationInput\">\n      <ErrorMessage name=\"required_dimensions\" component=\"span\" />\n      <label htmlFor=\"requiredDimensions\">Required Dimensions</label>\n      <FormikSelect\n        className={className}\n        defaultValue={defaultValue}\n        selectOptions={selectOptions}\n        formikFieldName={'required_dimensions'}\n        placeholder={'Choose Required Dimensions'}\n        styles={style}\n        isMulti={true}\n      />\n    </div>\n  );\n};\n","/**\n * Component for selecting node columns based on the current form state\n */\nimport { ErrorMessage, useFormikContext } from 'formik';\nimport { useContext, useMemo, useState, useEffect } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { FormikSelect } from './FormikSelect';\n\nexport const ColumnsSelect = ({\n  defaultValue,\n  fieldName,\n  label,\n  labelStyle = {},\n  isMulti = false,\n  isClearable = true,\n}) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // Used to pull out current form values for node validation\n  const { values } = useFormikContext();\n\n  // The available columns, determined from validating the node query\n  const [availableColumns, setAvailableColumns] = useState([]);\n  const [validationError, setValidationError] = useState(null);\n  const selectableOptions = useMemo(() => {\n    if (availableColumns && availableColumns.length > 0) {\n      return availableColumns;\n    }\n    return [];\n  }, [availableColumns]);\n\n  // Fetch columns by validating the latest node query\n  const fetchColumns = async () => {\n    try {\n      const { status, json } = await djClient.validateNode(\n        values.type,\n        values.name,\n        values.display_name,\n        values.description,\n        values.query,\n      );\n      if (json?.columns) {\n        setAvailableColumns(\n          json.columns.map(col => ({ value: col.name, label: col.name })),\n        );\n        setValidationError(null);\n      } else {\n        // Prefer the structured per-error messages (e.g. parse failures with\n        // INVALID_SQL_QUERY) over the generic `Node X is invalid.` summary.\n        const detailed = Array.isArray(json?.errors)\n          ? json.errors\n              .map(e => e.message)\n              .filter(Boolean)\n              .join('\\n')\n          : '';\n        setValidationError(detailed || json?.message || null);\n        setAvailableColumns([]);\n      }\n    } catch (error) {\n      console.error('Error fetching columns:', error);\n      setValidationError(\n        error.message ||\n          'Failed to validate query. Please check your query syntax.',\n      );\n      setAvailableColumns([]);\n    }\n  };\n\n  useEffect(() => {\n    fetchColumns();\n  }, [values.type, values.name, values.query]);\n\n  return (\n    <div className=\"CubeCreationInput\">\n      <ErrorMessage name={fieldName} component=\"span\" />\n      <label htmlFor={fieldName} style={labelStyle}>\n        {label}\n      </label>\n      {validationError && (\n        <div\n          className=\"validation-error\"\n          style={{\n            color: '#d32f2f',\n            fontSize: '0.875rem',\n            marginBottom: '8px',\n            padding: '8px',\n            backgroundColor: '#ffebee',\n            borderRadius: '4px',\n            border: '1px solid #ef9a9a',\n          }}\n        >\n          <strong>Validation Error:</strong> {validationError}\n        </div>\n      )}\n      <span data-testid={`select-${fieldName}`}>\n        <FormikSelect\n          className=\"\"\n          defaultValue={\n            isMulti\n              ? defaultValue.map(val => {\n                  return {\n                    value: val,\n                    label: val,\n                  };\n                })\n              : defaultValue\n              ? { value: defaultValue, label: defaultValue }\n              : null\n          }\n          selectOptions={selectableOptions}\n          formikFieldName={fieldName}\n          onFocus={event => fetchColumns(event)}\n          isMulti={isMulti}\n          isClearable={isClearable}\n        />\n      </span>\n    </div>\n  );\n};\n","/**\n * Custom metadata field component for nodes\n */\nimport { ErrorMessage, Field, useFormikContext } from 'formik';\nimport CodeMirror from '@uiw/react-codemirror';\nimport { langs } from '@uiw/codemirror-extensions-langs';\nimport { useState, useEffect } from 'react';\n\nexport const CustomMetadataField = ({ value }) => {\n  const formik = useFormikContext();\n  const jsonExt = langs.json();\n  const [hasError, setHasError] = useState(false);\n\n  useEffect(() => {\n    if (!value || value === '') {\n      setHasError(false);\n      return;\n    }\n\n    const stringValue =\n      typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n\n    try {\n      JSON.parse(stringValue);\n      setHasError(false);\n    } catch (err) {\n      setHasError(true);\n    }\n  }, [value]);\n\n  const formatValue = value => {\n    if (value === null || value === undefined) {\n      return '';\n    }\n    if (typeof value === 'string') {\n      return value;\n    }\n    return JSON.stringify(value, null, 2);\n  };\n\n  const updateFormik = val => {\n    formik.setFieldValue('custom_metadata', val);\n    formik.setFieldTouched('custom_metadata', true);\n\n    if (!val || val.trim() === '') {\n      setHasError(false);\n    } else {\n      try {\n        JSON.parse(val);\n        setHasError(false);\n      } catch (err) {\n        setHasError(true);\n      }\n    }\n  };\n\n  return (\n    <div className=\"QueryInput NodeCreationInput\">\n      <details>\n        <summary style={{ cursor: 'pointer' }}>\n          <label\n            style={{\n              paddingLeft: '3px',\n              display: 'inline-block',\n              pointerEvents: 'none',\n            }}\n          >\n            Custom Metadata (JSON)\n          </label>\n        </summary>\n        <ErrorMessage name=\"custom_metadata\" component=\"span\" />\n        <Field\n          type=\"textarea\"\n          style={{ display: 'none' }}\n          as=\"textarea\"\n          name=\"custom_metadata\"\n          id=\"CustomMetadata\"\n          validate={value => {\n            if (!value || value.trim() === '') {\n              return undefined;\n            }\n            try {\n              const parsed = JSON.parse(value);\n\n              if (\n                typeof parsed === 'object' &&\n                parsed !== null &&\n                !Array.isArray(parsed)\n              ) {\n                const keys = Object.keys(parsed);\n                const originalKeyMatches = value.match(/\"([^\"]+)\"\\s*:/g);\n                if (\n                  originalKeyMatches &&\n                  originalKeyMatches.length > keys.length\n                ) {\n                  return 'Duplicate keys detected';\n                }\n              }\n\n              return undefined;\n            } catch (err) {\n              return 'Invalid JSON format';\n            }\n          }}\n        />\n        <div\n          role=\"button\"\n          tabIndex={0}\n          className={`relative flex ${\n            hasError ? 'bg-red-900/20' : 'bg-[#282a36]'\n          }`}\n          style={{\n            border: hasError ? '2px solid #ef4444' : 'none',\n            borderRadius: '4px',\n            boxShadow: hasError ? '0 0 0 1px rgba(239, 68, 68, 0.3)' : 'none',\n          }}\n        >\n          <CodeMirror\n            id={'custom_metadata'}\n            name={'custom_metadata'}\n            extensions={[jsonExt]}\n            value={formatValue(value)}\n            placeholder={'{\\n  \"key\": \"value\"\\n}'}\n            options={{\n              theme: 'default',\n              lineNumbers: true,\n            }}\n            width=\"100%\"\n            height=\"200px\"\n            style={{\n              margin: '0 0 23px 0',\n              flex: 1,\n              fontSize: '110%',\n              textAlign: 'left',\n            }}\n            onChange={(value, viewUpdate) => {\n              updateFormik(value);\n            }}\n          />\n        </div>\n      </details>\n    </div>\n  );\n};\n","/**\n * Node add + edit page for transforms, metrics, and dimensions. The creation and edit flow for these\n * node types is largely the same, with minor differences handled server-side. For the `query`\n * field, this page will render a CodeMirror SQL editor with autocompletion and syntax highlighting.\n */\nimport { ErrorMessage, Form, Formik } from 'formik';\nimport NamespaceHeader from '../../components/NamespaceHeader';\nimport { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport 'styles/node-creation.scss';\nimport './styles.css';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { FullNameField } from './FullNameField';\nimport { MetricQueryField } from './MetricQueryField';\nimport { displayMessageAfterSubmit } from '../../../utils/form';\nimport { NodeQueryField } from './NodeQueryField';\nimport { MetricMetadataFields } from './MetricMetadataFields';\nimport { UpstreamNodeField } from './UpstreamNodeField';\nimport { OwnersField } from './OwnersField';\nimport { TagsField } from './TagsField';\nimport { NamespaceField } from './NamespaceField';\nimport { AlertMessage } from './AlertMessage';\nimport { DisplayNameField } from './DisplayNameField';\nimport { DescriptionField } from './DescriptionField';\nimport { NodeModeField } from './NodeModeField';\nimport { RequiredDimensionsSelect } from './RequiredDimensionsSelect';\nimport LoadingIcon from '../../icons/LoadingIcon';\nimport { ColumnsSelect } from './ColumnsSelect';\nimport { CustomMetadataField } from './CustomMetadataField';\n\nclass Action {\n  static Add = new Action('add');\n  static Edit = new Action('edit');\n\n  constructor(name) {\n    this.name = name;\n  }\n}\n\nexport function AddEditNodePage({ extensions = {} }) {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const navigate = useNavigate();\n\n  let { nodeType, initialNamespace, name } = useParams();\n  const action = name !== undefined ? Action.Edit : Action.Add;\n\n  // A read-only (git-managed) node can't be edited in the UI. If someone hits\n  // the edit route directly, send them back to the node view once the\n  // namespace's read-only verdict (from NamespaceHeader) is known.\n  const [isReadOnly, setIsReadOnly] = useState(undefined);\n  useEffect(() => {\n    if (action === Action.Edit && isReadOnly === true) {\n      navigate(`/nodes/${name}`, { replace: true });\n    }\n  }, [action, isReadOnly, name, navigate]);\n\n  const headerNamespace = initialNamespace\n    ? initialNamespace\n    : name\n    ? name.substring(0, name.lastIndexOf('.'))\n    : '';\n\n  const initialValues = {\n    name: action === Action.Edit ? name : '',\n    namespace: action === Action.Add ? initialNamespace : '',\n    display_name: '',\n    query: '',\n    type: nodeType,\n    description: '',\n    primary_key: '',\n    mode: 'published',\n    owners: [],\n    custom_metadata: '',\n  };\n\n  const validator = values => {\n    const errors = {};\n    // Display name drives the synthesized full name (`namespace.display_name`).\n    // Without it the full name collapses to `namespace.` — non-empty but\n    // useless. Validate the user-facing field instead of the derived one.\n    if (action === Action.Add && !values.display_name?.trim()) {\n      errors.display_name = 'Required';\n    }\n    if (\n      !values.name ||\n      values.name.endsWith('.') ||\n      values.name.startsWith('.') ||\n      values.name.includes('..')\n    ) {\n      errors.name = 'Required';\n    }\n    if (values.type !== 'metric' && !values.query) {\n      errors.query = 'Required';\n    }\n    return errors;\n  };\n\n  const handleSubmit = async (values, { setSubmitting, setStatus }) => {\n    if (action === Action.Add) {\n      await createNode(values, setStatus).then(_ => {\n        window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });\n        setSubmitting(false);\n      });\n    } else {\n      await patchNode(values, setStatus).then(_ => {\n        window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });\n        setSubmitting(false);\n      });\n    }\n  };\n  const submitHandlers = [handleSubmit];\n\n  const pageTitle =\n    action === Action.Add ? (\n      <h2>\n        Create{' '}\n        <span className={`node_type__${nodeType} node_type_creation_heading`}>\n          {nodeType}\n        </span>\n      </h2>\n    ) : (\n      <h2>Edit</h2>\n    );\n\n  const staticFieldsInEdit = node => (\n    <>\n      <div className=\"NodeNameInput NodeCreationInput\">\n        <label>Name</label> {name}\n      </div>\n      <div className=\"NodeNameInput NodeCreationInput\">\n        <label>Type</label> {node.type}\n      </div>\n    </>\n  );\n\n  const primaryKeyToList = primaryKey => {\n    return primaryKey.map(columnName => columnName.trim());\n  };\n\n  const parseCustomMetadata = customMetadata => {\n    if (!customMetadata || customMetadata.trim() === '') {\n      return null;\n    }\n    try {\n      return JSON.parse(customMetadata);\n    } catch (err) {\n      return null;\n    }\n  };\n\n  /**\n   * Build the metric query based on whether an upstream node is provided.\n   * - With upstream node: `SELECT <expression> FROM <upstream_node>` (regular metric)\n   * - Without upstream node: `SELECT <expression>` (derived metric referencing other metrics)\n   */\n  const buildMetricQuery = (aggregateExpression, upstreamNode) => {\n    if (upstreamNode && upstreamNode.trim() !== '') {\n      return `SELECT ${aggregateExpression} \\n FROM ${upstreamNode}`;\n    }\n    // Derived metric - no FROM clause needed, expression references other metrics directly\n    return `SELECT ${aggregateExpression}`;\n  };\n\n  const createNode = async (values, setStatus) => {\n    const { status, json } = await djClient.createNode(\n      nodeType,\n      values.name,\n      values.display_name,\n      values.description,\n      values.type === 'metric'\n        ? buildMetricQuery(values.aggregate_expression, values.upstream_node)\n        : values.query,\n      values.mode,\n      values.namespace,\n      values.primary_key ? primaryKeyToList(values.primary_key) : null,\n      values.metric_direction,\n      values.metric_unit,\n      // Only send required_dimensions if it's set (for metrics)\n      values.required_dimensions && Array.isArray(values.required_dimensions)\n        ? values.required_dimensions\n        : undefined,\n      parseCustomMetadata(values.custom_metadata),\n    );\n    if (status === 200 || status === 201) {\n      if (values.tags) {\n        await djClient.tagsNode(values.name, values.tags);\n      }\n      setStatus({\n        success: (\n          <>\n            Successfully created {json.type} node{' '}\n            <a href={`/nodes/${json.name}`}>{json.name}</a>!\n          </>\n        ),\n      });\n    } else {\n      setStatus({\n        failure: `${json.message}`,\n      });\n    }\n  };\n\n  const patchNode = async (values, setStatus) => {\n    const { status, json } = await djClient.patchNode(\n      values.name,\n      values.display_name,\n      values.description,\n      values.type === 'metric'\n        ? buildMetricQuery(values.aggregate_expression, values.upstream_node)\n        : values.query,\n      values.mode,\n      values.primary_key ? primaryKeyToList(values.primary_key) : null,\n      values.metric_direction,\n      values.metric_unit,\n      values.significant_digits,\n      // Only send required_dimensions if it's set (for metrics)\n      values.required_dimensions && Array.isArray(values.required_dimensions)\n        ? values.required_dimensions\n        : undefined,\n      values.owners,\n      parseCustomMetadata(values.custom_metadata),\n    );\n    const tagsResponse = await djClient.tagsNode(\n      values.name,\n      values.tags.map(tag => tag),\n    );\n    if ((status === 200 || status === 201) && tagsResponse.status === 200) {\n      setStatus({\n        success: (\n          <>\n            Successfully updated {json.type} node{' '}\n            <a href={`/nodes/${json.name}`}>{json.name}</a>!\n          </>\n        ),\n      });\n    } else {\n      setStatus({\n        failure: `${json.message}`,\n      });\n    }\n  };\n\n  const fullNameInput = (\n    <div className=\"FullNameInput NodeCreationInput\">\n      <ErrorMessage name=\"name\" component=\"span\" />\n      <label htmlFor=\"FullName\">Full Name *</label>\n      <FullNameField type=\"text\" name=\"name\" />\n    </div>\n  );\n\n  const nodeCanBeEdited = nodeType => {\n    return new Set(['transform', 'metric', 'dimension']).has(nodeType);\n  };\n\n  const getExistingNodeData = async name => {\n    const node = await djClient.getNodeForEditing(name);\n    if (node === null) {\n      return { message: `Node ${name} does not exist` };\n    }\n    const baseData = {\n      name: node.name,\n      type: node.type.toLowerCase(),\n      display_name: node.current.displayName,\n      description: node.current.description,\n      primary_key: node.current.primaryKey,\n      query: node.current.query,\n      tags: node.tags,\n      mode: node.current.mode.toLowerCase(),\n      owners: node.owners,\n      custom_metadata: node.current.customMetadata,\n    };\n\n    if (node.type === 'METRIC') {\n      // Check if this is a derived metric (any parent is a metric)\n      const isDerivedMetric = node.current.isDerivedMetric;\n      // For regular metrics, get the first non-metric parent as upstream node\n      const nonMetricParent = node.current.parents.find(\n        p => p.type !== 'METRIC',\n      );\n\n      if (isDerivedMetric) {\n        // Derived metric: no upstream node, expression is the full query projection\n        // Parse the expression from the query (format: \"SELECT <expression>\")\n        const query = node.current.query || '';\n        const selectMatch = query.match(/SELECT\\s+(.+)/is);\n        const derivedExpression = selectMatch\n          ? selectMatch[1].trim()\n          : node.current.metricMetadata?.expression || '';\n\n        return {\n          ...baseData,\n          metric_direction:\n            node.current.metricMetadata?.direction?.toLowerCase(),\n          metric_unit: node.current.metricMetadata?.unit?.name?.toLowerCase(),\n          significant_digits: node.current.metricMetadata?.significantDigits,\n          required_dimensions: node.current.requiredDimensions.map(\n            dim => dim.name,\n          ),\n          upstream_node: '', // Derived metrics have no upstream node\n          aggregate_expression: derivedExpression,\n        };\n      } else {\n        // Regular metric: has upstream node (first non-metric parent)\n        return {\n          ...baseData,\n          metric_direction:\n            node.current.metricMetadata?.direction?.toLowerCase(),\n          metric_unit: node.current.metricMetadata?.unit?.name?.toLowerCase(),\n          significant_digits: node.current.metricMetadata?.significantDigits,\n          required_dimensions: node.current.requiredDimensions.map(\n            dim => dim.name,\n          ),\n          upstream_node: nonMetricParent?.name || '',\n          aggregate_expression: node.current.metricMetadata?.expression,\n        };\n      }\n    }\n    return baseData;\n  };\n\n  const runValidityChecks = (data, setNode, setMessage) => {\n    // Check if node exists\n    if (data.message !== undefined) {\n      setNode(null);\n      setMessage(`Node ${name} does not exist!`);\n      return;\n    }\n    // Check if node type can be edited\n    if (!nodeCanBeEdited(data.type)) {\n      setNode(null);\n      if (data.type === 'cube') {\n        navigate(`/nodes/${data.name}/edit-cube`);\n      }\n      setMessage(`Node ${name} is of type ${data.type} and cannot be edited`);\n    }\n  };\n\n  const updateFieldsWithNodeData = (\n    data,\n    setFieldValue,\n    setNode,\n    setSelectTags,\n    setSelectPrimaryKey,\n    setSelectUpstreamNode,\n    setSelectRequiredDims,\n    setSelectOwners,\n  ) => {\n    // Update fields with existing data to prepare for edit\n    const fields = [\n      'display_name',\n      'query',\n      'type',\n      'description',\n      'primary_key',\n      'mode',\n      'tags',\n      'aggregate_expression',\n      'upstream_node',\n      'metric_unit',\n      'metric_direction',\n      'significant_digits',\n      'required_dimensions',\n      'owners',\n      'custom_metadata',\n    ];\n    fields.forEach(field => {\n      if (field === 'tags') {\n        setFieldValue(\n          field,\n          data[field].map(tag => tag.name),\n        );\n      } else if (field === 'owners') {\n        setFieldValue(\n          field,\n          data[field].map(owner => owner.username),\n        );\n      } else if (field === 'custom_metadata') {\n        const value = data[field] ? JSON.stringify(data[field], null, 2) : '';\n        setFieldValue(field, value, false);\n      } else {\n        setFieldValue(field, data[field] || '', false);\n      }\n    });\n    setNode(data);\n\n    // For react-select fields, we have to explicitly set the entire\n    // field rather than just the values\n    setSelectTags(\n      <TagsField\n        defaultValue={data.tags.map(t => {\n          return { value: t.name, label: t.displayName };\n        })}\n      />,\n    );\n    setSelectPrimaryKey(\n      <ColumnsSelect\n        defaultValue={data.primary_key}\n        fieldName=\"primary_key\"\n        label=\"Primary Key\"\n        isMulti={true}\n      />,\n    );\n    if (data.required_dimensions) {\n      setSelectRequiredDims(\n        <RequiredDimensionsSelect\n          defaultValue={data.required_dimensions.map(dim => {\n            return { value: dim, label: dim };\n          })}\n        />,\n      );\n    }\n    // For derived metrics, upstream_node is empty - pass null to clear the select\n    setSelectUpstreamNode(\n      <UpstreamNodeField\n        defaultValue={\n          data.upstream_node\n            ? { value: data.upstream_node, label: data.upstream_node }\n            : null\n        }\n      />,\n    );\n    if (data.owners) {\n      setSelectOwners(\n        <OwnersField\n          defaultValue={data.owners.map(owner => {\n            return { value: owner.username, label: owner.username };\n          })}\n        />,\n      );\n    }\n  };\n\n  // Editing a node we can't yet confirm is editable (verdict still loading) or\n  // one that is read-only: render just the header (which resolves the verdict\n  // and triggers the redirect above) — never the editor form. Avoids flashing\n  // the editor before redirecting a read-only node.\n  if (action === Action.Edit && isReadOnly !== false) {\n    return (\n      <div className=\"mid\">\n        <NamespaceHeader\n          namespace={headerNamespace}\n          onReadOnlyChange={setIsReadOnly}\n        />\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"mid\">\n      <NamespaceHeader\n        namespace={headerNamespace}\n        onReadOnlyChange={setIsReadOnly}\n      />\n      <div className=\"node-builder\">\n        <div className=\"node-builder-main\">\n          <Formik\n            initialValues={initialValues}\n            validate={validator}\n            validateOnChange={true}\n            validateOnBlur={true}\n            onSubmit={async (values, { setSubmitting, setStatus }) => {\n              try {\n                for (const handler of submitHandlers) {\n                  await handler(values, { setSubmitting, setStatus });\n                }\n              } catch (error) {\n                console.error('Error in submission', error);\n              } finally {\n                setSubmitting(false);\n              }\n            }}\n          >\n            {function Render(formikProps) {\n              const {\n                isSubmitting,\n                status,\n                setFieldValue,\n                errors,\n                touched,\n                isValid,\n                dirty,\n              } = formikProps;\n              const [node, setNode] = useState([]);\n              const [selectPrimaryKey, setSelectPrimaryKey] = useState(null);\n              const [selectRequiredDims, setSelectRequiredDims] =\n                useState(null);\n              const [selectUpstreamNode, setSelectUpstreamNode] =\n                useState(null);\n              const [selectOwners, setSelectOwners] = useState(null);\n              const [selectTags, setSelectTags] = useState(null);\n              const [message, setMessage] = useState('');\n\n              useEffect(() => {\n                const fetchData = async () => {\n                  if (action === Action.Edit) {\n                    const data = await getExistingNodeData(name);\n                    runValidityChecks(data, setNode, setMessage);\n                    updateFieldsWithNodeData(\n                      data,\n                      setFieldValue,\n                      setNode,\n                      setSelectTags,\n                      setSelectPrimaryKey,\n                      setSelectUpstreamNode,\n                      setSelectRequiredDims,\n                      setSelectOwners,\n                    );\n                  }\n                };\n                fetchData().catch(console.error);\n              }, [setFieldValue]);\n              return (\n                <Form>\n                  {displayMessageAfterSubmit(status)}\n                  {action === Action.Edit && message ? (\n                    <AlertMessage message={message} />\n                  ) : (\n                    <>\n                      <div className=\"node-builder-form-header\">\n                        {pageTitle}\n                        <NodeModeField />\n                      </div>\n\n                      <div className=\"node-group\">\n                        <div className=\"node-row\">\n                          {action === Action.Add ? (\n                            <NamespaceField\n                              initialNamespace={initialNamespace}\n                            />\n                          ) : (\n                            staticFieldsInEdit(node)\n                          )}\n                          <DisplayNameField />\n                        </div>\n                        {action === Action.Add ? fullNameInput : ''}\n                        <DescriptionField />\n                      </div>\n\n                      <div className=\"node-group\">\n                        {nodeType === 'metric' || node?.type === 'metric' ? (\n                          action === Action.Edit ? (\n                            selectUpstreamNode\n                          ) : (\n                            <UpstreamNodeField />\n                          )\n                        ) : null}\n                        {nodeType === 'metric' || node.type === 'metric' ? (\n                          <MetricQueryField\n                            djClient={djClient}\n                            value={\n                              node.aggregate_expression\n                                ? node.aggregate_expression\n                                : ''\n                            }\n                          />\n                        ) : (\n                          <NodeQueryField\n                            djClient={djClient}\n                            value={node.query ? node.query : ''}\n                          />\n                        )}\n                        {(nodeType === 'metric' || node.type === 'metric') && (\n                          <MetricMetadataFields />\n                        )}\n                      </div>\n\n                      <div className=\"node-group\">\n                        {nodeType !== 'metric' && node.type !== 'metric' ? (\n                          action === Action.Edit ? (\n                            selectPrimaryKey\n                          ) : (\n                            <ColumnsSelect\n                              defaultValue={[]}\n                              fieldName=\"primary_key\"\n                              label=\"Primary Key\"\n                              isMulti={true}\n                            />\n                          )\n                        ) : action === Action.Edit ? (\n                          selectRequiredDims\n                        ) : (\n                          <RequiredDimensionsSelect />\n                        )}\n                      </div>\n\n                      <div className=\"node-group\">\n                        <div className=\"node-row\">\n                          {action === Action.Edit ? (\n                            selectOwners\n                          ) : (\n                            <OwnersField />\n                          )}\n                          {action === Action.Edit ? selectTags : <TagsField />}\n                        </div>\n                      </div>\n\n                      {Object.entries(extensions).map(\n                        ([key, ExtensionComponent]) => (\n                          <div key={key} className=\"node-group\">\n                            <ExtensionComponent\n                              node={node}\n                              action={action}\n                              registerSubmitHandler={(\n                                onSubmit,\n                                { prepend } = {},\n                              ) => {\n                                if (!submitHandlers.includes(onSubmit)) {\n                                  if (prepend) {\n                                    submitHandlers.unshift(onSubmit);\n                                  } else {\n                                    submitHandlers.push(onSubmit);\n                                  }\n                                }\n                              }}\n                            />\n                          </div>\n                        ),\n                      )}\n\n                      <div className=\"node-group node-group-last\">\n                        <CustomMetadataField\n                          value={\n                            node.custom_metadata ? node.custom_metadata : ''\n                          }\n                        />\n                      </div>\n\n                      <button\n                        type=\"submit\"\n                        disabled={isSubmitting || !isValid}\n                        className={`save-node-btn${\n                          isSubmitting ? ' save-node-btn--loading' : ''\n                        }`}\n                      >\n                        {isSubmitting ? (\n                          <>\n                            <LoadingIcon />\n                            Saving...\n                          </>\n                        ) : (\n                          (action === Action.Add ? 'Create ' : 'Save ') +\n                          (nodeType ? nodeType : '')\n                        )}\n                      </button>\n                    </>\n                  )}\n                </Form>\n              );\n            }}\n          </Formik>\n        </div>\n      </div>\n    </div>\n  );\n}\n"],"names":["MetricQueryField","djClient","value","schema","setSchema","React","availableMetrics","setAvailableMetrics","formik","useFormikContext","upstreamNode","sqlExt","langs","fetchMetrics","metrics","err","cancelled","loadSchema","next","nodeDetails","_a","col","metricName","updateFormik","val","isDerivedMode","labelText","helpText","jsxs","jsx","ErrorMessage","Field","CodeMirror","viewUpdate","CATALOG_TABLE_PATTERN","extractCatalogTables","sql","knownCatalogs","re","known","c","seen","out","m","catalog","table","key","DOTTED_REF_RE","unbacktick","refreshBadges","StateEffect","classForStatus","statusKind","buildDecorations","view","getStatus","getKnownCatalogs","doc","ranges","from","to","slice","whole","status","segments","refType","cls","start","end","Decoration","a","b","r","djNodeBadges","ViewPlugin","update","refreshed","tr","e","v","refAtPos","pos","line","renderTooltipDom","refKey","wrap","node","header","pill","name","note","grid","addCell","label","cell","l","d","text","list","row","n","tag","t","foot","link","nodeDetailsCache","djNodeHoverTooltip","fetchNodeDetails","hoverTooltip","hit","baseStatus","dom","cached","promise","full","richDom","palette","djEditorTheme","EditorView","highlight","HighlightStyle","djEditorExtensions","syntaxHighlighting","ERROR_CODE_LABELS","errorLabel","code","word","NodeQueryField","autoRegisterTimer","validateTimer","registeredTables","knownCatalogsRef","queryErrors","setQueryErrors","tableStatus","setTableStatus","tableStatusRef","editorViewRef","setStatus","catalogs","initialAutocomplete","context","matches","prev","changed","nodeName","updateAutocomplete","_","cols","autoRegisterCatalogTables","validateRefs","fv","response","json","deps","missing","dep","nodeType","nodeStatus","kind","tables","tableSchema","columns","badgeExt","hoverExt","idx","MetricMetadataFields","useContext","DJClientContext","metricUnits","setMetricUnits","useState","metricDirections","setMetricDirections","useEffect","metadata","direction","labelize","unit","UpstreamNodeField","defaultValue","availableNodes","setAvailableNodes","fetchData","sources","transforms","dimensions","nodes","FormikSelect","OwnersField","currentUser","useCurrentUser","meta","helpers","useField","availableUsers","setAvailableUsers","users","user","TagsField","tags","setTags","NamespaceField","initialNamespace","namespaces","setNamespaces","AlertMessage","message","AlertIcon","DisplayNameField","DescriptionField","NodeModeField","RequiredDimensionsSelect","style","className","values","selectOptions","setSelectOptions","data","ColumnsSelect","fieldName","labelStyle","isMulti","isClearable","availableColumns","setAvailableColumns","validationError","setValidationError","selectableOptions","useMemo","fetchColumns","detailed","error","event","CustomMetadataField","jsonExt","hasError","setHasError","stringValue","formatValue","parsed","keys","originalKeyMatches","_Action","__publicField","Action","AddEditNodePage","extensions","navigate","useNavigate","useParams","action","isReadOnly","setIsReadOnly","headerNamespace","initialValues","validator","errors","submitHandlers","setSubmitting","createNode","patchNode","pageTitle","staticFieldsInEdit","Fragment","primaryKeyToList","primaryKey","columnName","parseCustomMetadata","customMetadata","buildMetricQuery","aggregateExpression","tagsResponse","fullNameInput","FullNameField","nodeCanBeEdited","getExistingNodeData","baseData","isDerivedMetric","nonMetricParent","p","selectMatch","derivedExpression","_c","_b","_f","_e","_d","_g","dim","_i","_h","_l","_k","_j","_m","_n","runValidityChecks","setNode","setMessage","updateFieldsWithNodeData","setFieldValue","setSelectTags","setSelectPrimaryKey","setSelectUpstreamNode","setSelectRequiredDims","setSelectOwners","field","owner","NamespaceHeader","Formik","handler","formikProps","isSubmitting","touched","isValid","dirty","selectPrimaryKey","selectRequiredDims","selectUpstreamNode","selectOwners","selectTags","Form","displayMessageAfterSubmit","ExtensionComponent","onSubmit","prepend","LoadingIcon"],"mappings":"6ZAaaA,GAAmB,CAAC,CAAE,SAAAC,EAAU,MAAAC,KAAY,CACvD,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAM,SAAS,CAAA,CAAE,EACvC,CAACC,EAAkBC,CAAmB,EAAIF,EAAM,SAAS,CAAA,CAAE,EAC3DG,EAASC,EAAAA,iBAAA,EACTC,EAAeF,EAAO,OAAO,cAK7BG,EAASN,EAAM,QAAQ,IAAMO,EAAAA,MAAM,IAAI,CAAE,OAAAT,CAAA,CAAQ,EAAG,CAACA,CAAM,CAAC,EAGlEE,EAAM,UAAU,IAAM,CACpB,eAAeQ,GAAe,CAC5B,GAAI,CACF,MAAMC,EAAU,MAAMb,EAAS,QAAA,EAC/BM,EAAoBO,GAAW,EAAE,CACnC,OAASC,EAAK,CACZ,QAAQ,MAAM,2CAA4CA,CAAG,CAC/D,CACF,CACAF,EAAA,CACF,EAAG,CAACZ,CAAQ,CAAC,EAKbI,EAAM,UAAU,IAAM,CACpB,IAAIW,EAAY,GAChB,eAAeC,GAAa,OAC1B,MAAMC,EAAO,CAAA,EACb,GAAIR,GAAgBA,EAAa,KAAA,IAAW,GAC1C,GAAI,CACF,MAAMS,EAAc,MAAMlB,EAAS,KAAKS,CAAY,GACpDU,EAAAD,GAAA,YAAAA,EAAa,UAAb,MAAAC,EAAsB,QAAQC,GAAO,CACnCH,EAAKG,EAAI,IAAI,EAAI,CAAA,CACnB,EACF,OAASN,EAAK,CACZ,QAAQ,MAAM,wCAAyCA,CAAG,CAC5D,CAEFT,EAAiB,QAAQgB,GAAc,CACrCJ,EAAKI,CAAU,EAAI,CAAA,CACrB,CAAC,EACIN,GAAWZ,EAAUc,CAAI,CAChC,CACA,OAAAD,EAAA,EACO,IAAM,CACXD,EAAY,EACd,CACF,EAAG,CAACf,EAAUS,EAAcJ,CAAgB,CAAC,EAE7C,MAAMiB,EAAeC,GAAO,CAC1BhB,EAAO,cAAc,uBAAwBgB,CAAG,CAClD,EAGMC,EAAgB,CAACf,GAAgBA,EAAa,SAAW,GACzDgB,EAAYD,EACd,8BACA,yBACEE,EAAWF,EACb,wGACA,qFAEJ,OACEG,EAAAA,KAAC,MAAA,CAAI,UAAU,gDACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,QAAQ,UAAU,OAAO,EAC5CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,QAAS,SAAAH,EAAU,EAClCG,EAAAA,IAAC,IAAA,CACC,UAAU,kBACV,MAAO,CAAE,SAAU,SAAU,MAAO,OAAQ,aAAc,KAAA,EAEzD,SAAAF,CAAA,CAAA,EAEHE,EAAAA,IAACE,EAAAA,MAAA,CACC,KAAK,WACL,MAAO,CAAE,QAAS,MAAA,EAClB,GAAG,WACH,KAAK,uBACL,GAAG,OAAA,CAAA,QAEJ,MAAA,CAAI,KAAK,SAAS,SAAU,EAAG,UAAU,6BACxC,SAAAF,EAAAA,IAACG,EAAAA,gBAAA,CACC,GAAI,uBACJ,KAAM,uBACN,WAAY,CAACrB,CAAM,EACnB,MAAAT,EACA,QAAS,CACP,MAAO,UACP,YAAa,EAAA,EAEf,MAAM,OACN,OAAO,QACP,MAAO,CACL,OAAQ,aACR,KAAM,EACN,SAAU,OACV,UAAW,MAAA,EAEb,SAAU,CAACA,EAAO+B,IAAe,CAC/BV,EAAarB,CAAK,CACpB,CAAA,CAAA,CACF,CACF,CAAA,EACF,CAEJ,ECvHMgC,GACJ,2FAMK,SAASC,GAAqBC,EAAKC,EAAe,CACvD,MAAMC,EAAK,IAAI,OAAOJ,GAAsB,OAAQ,GAAG,EACjDK,EAAQ,IAAI,IAAIF,EAAc,IAAIG,GAAKA,EAAE,YAAW,CAAE,CAAC,EACvDC,EAAO,IAAI,IACXC,EAAM,CAAA,EACZ,IAAIC,EACJ,MAAQA,EAAIL,EAAG,KAAKF,CAAG,KAAO,MAAM,CAClC,KAAM,EAAGQ,EAASzC,EAAQ0C,CAAK,EAAIF,EACnC,GAAI,CAACJ,EAAM,IAAIK,EAAQ,YAAW,CAAE,EAAG,SACvC,MAAME,EAAM,GAAGF,CAAO,IAAIzC,CAAM,IAAI0C,CAAK,GACrCJ,EAAK,IAAIK,CAAG,IAChBL,EAAK,IAAIK,CAAG,EACZJ,EAAI,KAAK,CAACE,EAASzC,EAAQ0C,CAAK,CAAC,EACnC,CACA,OAAOH,CACT,CCDA,MAAMK,EACJ,+DAEF,SAASC,GAAW,EAAG,CACrB,OAAO,EAAE,QAAQ,KAAM,EAAE,CAC3B,CAEO,MAAMC,GAAgBC,EAAAA,YAAY,OAAM,EAE/C,SAASC,GAAeC,EAAY,CAClC,OAAQA,EAAU,CAChB,IAAK,cACH,MAAO,4BACT,IAAK,QACH,MAAO,sBACT,IAAK,UACH,MAAO,wBACT,IAAK,UACH,MAAO,wBACT,QACE,MAAO,uBACb,CACA,CAEA,SAASC,GAAiBC,EAAMC,EAAWC,EAAkB,CAC3D,MAAMjB,EAAQ,IAAI,KAAKiB,EAAgB,GAAM,IAAI,IAAIhB,GAAKA,EAAE,YAAW,CAAE,CAAC,EACpEiB,EAAMH,EAAK,MAAM,IACjBI,EAAS,CAAA,EAEf,SAAW,CAAE,KAAAC,EAAM,GAAAC,CAAE,IAAMN,EAAK,cAAe,CAC7C,MAAMO,EAAQJ,EAAI,YAAYE,EAAMC,CAAE,EACtCb,EAAc,UAAY,EAC1B,IAAIJ,EACJ,MAAQA,EAAII,EAAc,KAAKc,CAAK,KAAO,MAAM,CAC/C,MAAMC,EAAQnB,EAAE,CAAC,EACXG,EAAME,GAAWc,CAAK,EACtBC,EAASR,EAAUT,CAAG,EACtBkB,EAAWlB,EAAI,MAAM,GAAG,EAE9B,IAAImB,EACJ,GAAIF,GAAA,MAAAA,EAAQ,QAEVE,EAAUF,EAAO,gBAEjBC,EAAS,SAAW,GACpBzB,EAAM,IAAIyB,EAAS,CAAC,EAAE,YAAW,CAAE,EAGnCC,EAAU,aAIV,UAGF,MAAMC,EAAM,8BAA8BD,CAAO,IAAId,GACnDY,GAAA,YAAAA,EAAQ,IAChB,CAAO,GACKI,EAAQR,EAAOhB,EAAE,MACjByB,EAAMD,EAAQL,EAAM,OAC1BJ,EAAO,KAAK,CACV,KAAMS,EACN,GAAIC,EACJ,KAAMC,EAAAA,WAAW,KAAK,CACpB,MAAOH,EACP,WAAYH,GAAA,MAAAA,EAAQ,QAAU,CAAE,MAAOA,EAAO,OAAO,EAAK,MACpE,CAAS,CACT,CAAO,CACH,CACF,CAEA,OAAAL,EAAO,KAAK,CAACY,EAAGC,IAAMD,EAAE,KAAOC,EAAE,MAAQD,EAAE,GAAKC,EAAE,EAAE,EAC7CF,EAAAA,WAAW,IAAIX,EAAO,IAAIc,GAAKA,EAAE,KAAK,MAAMA,EAAE,KAAMA,EAAE,EAAE,CAAC,CAAC,CACnE,CAYO,SAASC,GAAa,CAAE,UAAAlB,EAAW,iBAAAC,GAAoB,CAC5D,OAAOkB,EAAAA,WAAW,UAChB,KAAM,CACJ,YAAYpB,EAAM,CAChB,KAAK,YAAcD,GAAiBC,EAAMC,EAAWC,CAAgB,CACvE,CACA,OAAOmB,EAAQ,CACb,MAAMC,EAAYD,EAAO,aAAa,KAAKE,GACzCA,EAAG,QAAQ,KAAKC,GAAKA,EAAE,GAAG7B,EAAa,CAAC,CAClD,GACY0B,EAAO,YAAcA,EAAO,iBAAmBC,KACjD,KAAK,YAAcvB,GACjBsB,EAAO,KACPpB,EACAC,CACZ,EAEM,CACN,EACI,CAAE,YAAauB,GAAKA,EAAE,WAAW,CACrC,CACA,CAQO,SAASC,GAAS1B,EAAM2B,EAAK,CAClC,MAAMC,EAAO5B,EAAK,MAAM,IAAI,OAAO2B,CAAG,EACtClC,EAAc,UAAY,EAC1B,IAAIJ,EACJ,MAAQA,EAAII,EAAc,KAAKmC,EAAK,IAAI,KAAO,MAAM,CACnD,MAAMf,EAAQe,EAAK,KAAOvC,EAAE,MACtByB,EAAMD,EAAQxB,EAAE,CAAC,EAAE,OACzB,GAAIsC,GAAOd,GAASc,GAAOb,EACzB,MAAO,CAAE,IAAKpB,GAAWL,EAAE,CAAC,CAAC,EAAG,KAAMwB,EAAO,GAAIC,CAAG,CAExD,CACA,OAAO,IACT,CAEO,SAASe,GAAiBpB,EAAQqB,EAAQ,OAC/C,MAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,kBAEjB,MAAMC,EAAOvB,EAAO,MAAQ,CAAA,EAGtBwB,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,0BAEnB,MAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,8BAA8BzB,EAAO,SAAW,MAAM,GACvEyB,EAAK,YAAczB,EAAO,SAAW,OACrCwB,EAAO,YAAYC,CAAI,EAEvB,MAAMC,EAAO,SAAS,cAAc,MAAM,EAQ1C,GAPAA,EAAK,UAAY,wBACjBA,EAAK,YAAcH,EAAK,MAAQF,EAChCG,EAAO,YAAYE,CAAI,EAEvBJ,EAAK,YAAYE,CAAM,EAGnBxB,EAAO,OAAS,UAAW,CAC7B,MAAM2B,EAAO,SAAS,cAAc,KAAK,EACzC,OAAAA,EAAK,UAAY,wBACjBA,EAAK,YAAc,mBACnBL,EAAK,YAAYK,CAAI,EACdL,CACT,CACA,GAAItB,EAAO,OAAS,cAAe,CACjC,MAAM2B,EAAO,SAAS,cAAc,KAAK,EACzC,OAAAA,EAAK,UAAY,wBACjBA,EAAK,YAAc,eACnBL,EAAK,YAAYK,CAAI,EACdL,CACT,CAGA,MAAMM,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,wBACjB,MAAMC,EAAU,CAACC,EAAO3F,IAAU,CAChC,GAAIA,GAAS,MAAQA,IAAU,GAAI,OACnC,MAAM4F,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,wBACjB,MAAMC,EAAI,SAAS,cAAc,MAAM,EACvCA,EAAE,UAAY,yBACdA,EAAE,YAAcF,EAChB,MAAMd,EAAI,SAAS,cAAc,MAAM,EACvCA,EAAE,UAAY,yBACdA,EAAE,YAAc7E,EAChB4F,EAAK,YAAYC,CAAC,EAClBD,EAAK,YAAYf,CAAC,EAClBY,EAAK,YAAYG,CAAI,CACvB,EAUA,GATIR,EAAK,QAAQM,EAAQ,SAAUN,EAAK,MAAM,EAC1CA,EAAK,SAASM,EAAQ,UAAWN,EAAK,OAAO,EAC7CA,EAAK,MAAMM,EAAQ,OAAQN,EAAK,IAAI,EACpC,MAAM,QAAQA,EAAK,OAAO,GAC5BM,EAAQ,UAAW,OAAON,EAAK,QAAQ,MAAM,CAAC,EAE5CK,EAAK,kBAAoB,GAAGN,EAAK,YAAYM,CAAI,EAGjDL,EAAK,YAAa,CACpB,MAAMU,EAAI,SAAS,cAAc,KAAK,EACtCA,EAAE,UAAY,+BACd,MAAMC,EAAOX,EAAK,YAClBU,EAAE,YAAcC,EAAK,OAAS,IAAMA,EAAK,MAAM,EAAG,GAAG,EAAI,IAAMA,EAC/DZ,EAAK,YAAYW,CAAC,CACpB,CAIA,GAAI,MAAM,QAAQV,EAAK,OAAO,GAAKA,EAAK,QAAQ,OAAS,EAAG,CAC1D,MAAMY,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,2BACjB,UAAW7E,KAAOiE,EAAK,QAAS,CAC9B,MAAMa,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,2BAEhB,MAAMC,EAAI,SAAS,cAAc,MAAM,EAMvC,GALAA,EAAE,UAAY,4BACdA,EAAE,YAAc/E,EAAI,KACpB8E,EAAI,YAAYC,CAAC,EAGb/E,EAAI,WAAaA,EAAI,iBAAkB,CACzC,MAAMgF,EAAM,SAAS,cAAc,MAAM,EACzCA,EAAI,UAAY,2BAChBA,EAAI,YAAc,MAClBA,EAAI,OAAQjF,EAAAC,EAAI,YAAJ,MAAAD,EAAe,KACvB,YAAYC,EAAI,UAAU,IAAI,GAC9B,mBACJ8E,EAAI,YAAYE,CAAG,CACrB,CAEA,MAAMC,EAAI,SAAS,cAAc,MAAM,EACvCA,EAAE,UAAY,4BAGdA,EAAE,aAAejF,EAAI,MAAQ,IAAI,MAAM;AAAA,CAAI,EAAE,CAAC,EAC9CiF,EAAE,MAAQjF,EAAI,MAAQ,GACtB8E,EAAI,YAAYG,CAAC,EAEjBJ,EAAK,YAAYC,CAAG,CACtB,CACAd,EAAK,YAAYa,CAAI,CACvB,CAGA,GAAIZ,EAAK,KAAM,CACb,MAAMiB,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,0BACjB,MAAMC,EAAO,SAAS,cAAc,GAAG,EACvCA,EAAK,KAAO,UAAU,mBAAmBlB,EAAK,IAAI,CAAC,GACnDkB,EAAK,OAAS,SACdA,EAAK,IAAM,sBACXA,EAAK,YAAc,cACnBD,EAAK,YAAYC,CAAI,EACrBnB,EAAK,YAAYkB,CAAI,CACvB,CAEA,OAAOlB,CACT,CAKA,MAAMoB,GAAmB,IAAI,IAStB,SAASC,GAAmB,CACjC,UAAAnD,EACA,iBAAAC,EACA,iBAAAmD,CACF,EAAG,CACD,OAAOC,EAAAA,aACL,CAACtD,EAAM2B,IAAQ,CACb,MAAM4B,EAAM7B,GAAS1B,EAAM2B,CAAG,EAC9B,GAAI,CAAC4B,EAAK,OAAO,KACjB,MAAM9C,EAASR,EAAUsD,EAAI,GAAG,EAChC,GAAI,CAAC9C,EAAQ,CAGX,MAAMxB,EAAQ,IAAI,KACfiB,EAAgB,GAAM,IAAI,IAAIhB,GAAKA,EAAE,aAAa,CAC7D,EACcwB,EAAW6C,EAAI,IAAI,MAAM,GAAG,EAClC,GAAI7C,EAAS,SAAW,GAAK,CAACzB,EAAM,IAAIyB,EAAS,CAAC,EAAE,YAAW,CAAE,EAC/D,OAAO,IAEX,CACA,MAAO,CACL,IAAK6C,EAAI,KACT,IAAKA,EAAI,GACT,MAAO,GACP,OAAQ,IAAM,CACZ,MAAMC,EAAa/C,GAAU,CAAE,QAAS,QAAQ,EAC1CgD,EAAM5B,GAAiB2B,EAAYD,EAAI,GAAG,EAIhD,GACEF,GACAG,EAAW,OAAS,WACpBA,EAAW,OAAS,cACpB,CACA,MAAME,EAASP,GAAiB,IAAII,EAAI,GAAG,EACrCI,EAAUD,GAAUL,EAAiBE,EAAI,GAAG,EAC7CG,GAAQP,GAAiB,IAAII,EAAI,IAAKI,CAAO,EAElD,QAAQ,QAAQA,CAAO,EACpB,KAAKC,GAAQ,CACZ,GAAI,CAACA,EAAM,OACX,MAAMC,EAAUhC,GACd,CACE,GAAG2B,EACH,KAAM,CAAE,GAAIA,EAAW,MAAQ,CAAA,EAAK,GAAGI,CAAI,CAC/D,EACkBL,EAAI,GACtB,EACoBE,EAAI,WACNA,EAAI,WAAW,aAAaI,EAASJ,CAAG,EAIxCA,EAAI,gBAAgB,GAAGI,EAAQ,UAAU,CAE7C,CAAC,EACA,MAAM,IAAM,CAEb,CAAC,CACL,CAEA,MAAO,CAAE,IAAAJ,CAAG,CACd,CACR,CACI,EACA,CAAE,UAAW,GAAG,CACpB,CACA,CCzVA,MAAMK,EAAU,CACd,GAAI,UACJ,QAAS,UACT,OAAQ,UACR,UAAW,UACX,MAAO,UACP,KAAM,UACN,MAAO,UACP,QAAS,UACT,OAAQ,UACR,OAAQ,UACR,SAAU,UACV,aAAc,UACd,YAAa,UACb,QAAS,SACX,EAEaC,GAAgBC,EAAAA,WAAW,MACtC,CACE,IAAK,CACH,MAAOF,EAAQ,KACf,gBAAiBA,EAAQ,GACzB,SAAU,MAChB,EACI,cAAe,CACb,WAAYA,EAAQ,MACpB,WACE,4EACR,EACI,6BAA8B,CAAE,gBAAiBA,EAAQ,KAAK,EAC9D,6EACE,CACE,gBAAiBA,EAAQ,SACjC,EACI,iBAAkB,CAChB,gBAAiB,0BACvB,EACI,cAAe,CACb,gBAAiBA,EAAQ,QACzB,MAAOA,EAAQ,OACf,OAAQ,MACd,EACI,uBAAwB,CACtB,gBAAiB,2BACjB,MAAOA,EAAQ,IACrB,EACI,oCAAqC,CACnC,QAAS,aACf,EACI,mCAAoC,CAClC,MAAOA,EAAQ,KACrB,EACI,cAAe,CACb,WAAY,UACZ,OAAQ,oBACR,aAAc,MACd,UAAW,mCACjB,EACI,oDAAqD,CACnD,WAAY,UACZ,MAAOA,EAAQ,IACrB,EACI,8CAA+C,CAC7C,gBAAiB,UACjB,QAAS,MACf,EACI,aAAc,CACZ,gBAAiBA,EAAQ,QACzB,MAAOA,EAAQ,IACrB,CACA,EACE,CAAE,KAAM,EAAK,CACf,EAEMG,GAAYC,EAAAA,eAAe,OAAO,CACtC,CACE,IAAK,CAAClB,OAAE,QAASA,EAAAA,KAAE,SAAUA,OAAE,eAAgBA,EAAAA,KAAE,eAAe,EAChE,MAAOc,EAAQ,QACf,WAAY,KAChB,EACE,CAAE,IAAK,CAACd,OAAE,OAAQA,EAAAA,KAAE,QAAQA,EAAAA,KAAE,MAAM,CAAC,EAAG,MAAOc,EAAQ,MAAM,EAC7D,CAAE,IAAK,CAACd,OAAE,OAAQA,EAAAA,KAAE,KAAMA,EAAAA,KAAE,IAAI,EAAG,MAAOc,EAAQ,MAAM,EACxD,CACE,IAAK,CAACd,EAAAA,KAAE,SAASA,OAAE,YAAY,EAAGA,EAAAA,KAAE,SAASA,OAAE,YAAY,CAAC,EAC5D,MAAOc,EAAQ,YACnB,EACE,CACE,IAAK,CAACd,OAAE,SAAUA,EAAAA,KAAE,gBAAiBA,OAAE,mBAAoBA,EAAAA,KAAE,aAAa,EAC1E,MAAOc,EAAQ,QACnB,EACE,CACE,IAAK,CAACd,EAAAA,KAAE,YAAaA,EAAAA,KAAE,MAAOA,OAAE,MAAOA,EAAAA,KAAE,QAASA,EAAAA,KAAE,SAAS,EAC7D,MAAOc,EAAQ,WACnB,EACE,CACE,IAAK,CAACd,EAAAA,KAAE,aAAcA,EAAAA,KAAE,aAAcA,EAAAA,KAAE,aAAa,EACrD,MAAOc,EAAQ,IACnB,EACE,CAAE,IAAK,CAACd,EAAAA,KAAE,SAAUA,EAAAA,KAAE,SAAS,EAAG,MAAOc,EAAQ,YAAY,EAC7D,CACE,IAAK,CAACd,EAAAA,KAAE,QAASA,EAAAA,KAAE,YAAaA,EAAAA,KAAE,YAAY,EAC9C,MAAOc,EAAQ,QACf,UAAW,QACf,EACE,CAAE,IAAKd,EAAAA,KAAE,QAAS,MAAO,SAAS,CACpC,CAAC,EAEYmB,GAAqB,CAChCJ,GACAK,EAAAA,mBAAmBH,EAAS,CAC9B,ECxGMI,GAAoB,CACxB,kBAAmB,cACnB,eAAgB,iBAChB,eAAgB,iBAChB,8BAA+B,6BAC/B,gBAAiB,kBACjB,aAAc,eACd,eAAgB,iBAChB,gBAAiB,YACjB,sBAAuB,iBACzB,EAEMC,GAAaC,GAAQ,CACzB,GAA0BA,GAAS,MAAQA,IAAS,GAAI,MAAO,QAC/D,MAAM/E,EAAM,OAAO+E,CAAI,EACvB,OAAIF,GAAkB7E,CAAG,EAAU6E,GAAkB7E,CAAG,EACjDA,EACJ,cACA,MAAM,GAAG,EACT,OAAagF,EAAOA,EAAK,CAAC,EAAE,cAAgBA,EAAK,MAAM,CAAC,EAAI,EAAG,EAC/D,KAAK,GAAG,CACb,EAEaC,GAAiB,CAAC,CAAE,SAAA9H,EAAU,MAAAC,KAAY,CAKrD,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAM,SAAS,CAAA,CAAE,EACvCG,EAASC,EAAAA,iBAAA,EACTE,EAASN,EAAM,QAAQ,IAAMO,EAAAA,MAAM,IAAI,CAAE,OAAAT,CAAA,CAAQ,EAAG,CAACA,CAAM,CAAC,EAC5D6H,EAAoB3H,EAAM,OAAO,IAAI,EACrC4H,EAAgB5H,EAAM,OAAO,IAAI,EACjC6H,EAAmB7H,EAAM,OAAO,IAAI,GAAK,EAEzC8H,EAAmB9H,EAAM,OAAO,EAAE,EAKlC,CAAC+H,EAAaC,CAAc,EAAIhI,EAAM,SAAS,CAAA,CAAE,EAKjD,CAACiI,EAAaC,CAAc,EAAIlI,EAAM,SAAS,CAAA,CAAE,EACjDmI,EAAiBnI,EAAM,OAAOiI,CAAW,EAC/CjI,EAAM,UAAU,IAAM,CACpBmI,EAAe,QAAUF,CAC3B,EAAG,CAACA,CAAW,CAAC,EAChB,MAAMG,EAAgBpI,EAAM,OAAO,IAAI,EACjCqI,EAAYrI,EAAM,YAAY,CAACyC,EAAKiB,IAAW,CAKnDyE,EAAe,QAAU,CAAE,GAAGA,EAAe,QAAS,CAAC1F,CAAG,EAAGiB,CAAA,EAC7DwE,EAAeC,EAAe,OAAO,EACjCC,EAAc,SAChBA,EAAc,QAAQ,SAAS,CAAE,QAASxF,GAAc,GAAG,IAAI,EAAG,CAEtE,EAAG,CAAA,CAAE,EAEL5C,EAAM,UAAU,IAAM,CAChB,OAAOJ,EAAS,UAAa,YACjC,QAAQ,QAAQA,EAAS,SAAA,CAAU,EAChC,KAAK0I,GAAY,CAChBR,EAAiB,SAAWQ,GAAY,CAAA,GAAI,IAAInG,GAC9CA,EAAE,KAAK,YAAA,CAAY,CAEvB,CAAC,EACA,MAAM,IAAM,CAEb,CAAC,CACL,EAAG,CAACvC,CAAQ,CAAC,EAEb,MAAM2I,EAAsB,MAAMC,GAAW,CAI3C,MAAMf,EAAOe,EAAQ,YAAY,SAAS,EACpCC,EAAU,MAAM7I,EAAS,MAAM6H,EAAK,IAAI,EAC9C1H,EAAU2I,GAAQ,CAChB,MAAM7H,EAAO,CAAE,GAAG6H,CAAA,EAClB,IAAIC,EAAU,GACd,UAAWC,KAAYH,EACjB5H,EAAK+H,CAAQ,IAAM,SACrB/H,EAAK+H,CAAQ,EAAI,CAAA,EACjBD,EAAU,IAGd,OAAOA,EAAU9H,EAAO6H,CAC1B,CAAC,CACH,EAEMxH,EAAeC,GAAO,CAC1BhB,EAAO,cAAc,QAASgB,CAAG,CACnC,EAEM0H,EAAqB,MAAOhJ,EAAOiJ,IAAM,CAK7C,UAAWF,KAAY,OAAO,KAAK9I,CAAM,EACvC,GAAID,EAAM,SAAS+I,CAAQ,GAAK9I,EAAO8I,CAAQ,EAAE,SAAW,EAAG,CAC7D,MAAM9H,EAAc,MAAMlB,EAAS,KAAKgJ,CAAQ,EAC1CG,IAAQjI,GAAA,YAAAA,EAAa,UAAW,CAAA,GAAI,IAAIE,GAAOA,EAAI,IAAI,EAC7DjB,EAAU2I,IAAS,CAAE,GAAGA,EAAM,CAACE,CAAQ,EAAGG,GAAO,CACnD,CAIEjB,EAAiB,QAAQ,OAAS,IACpC,aAAaH,EAAkB,OAAO,EACtCA,EAAkB,QAAU,WAC1B,IAAMqB,EAA0BnJ,CAAK,EACrC,GAAA,GAMJ,aAAa+H,EAAc,OAAO,EAClCA,EAAc,QAAU,WAAW,IAAMqB,EAAapJ,CAAK,EAAG,GAAG,CACnE,EAEMoJ,EAAe,MAAMlH,GAAO,CAChC,GAAI,OAAOnC,EAAS,cAAiB,WAAY,OACjD,MAAMsJ,EAAK/I,EAAO,QAAU,CAAA,EAC5B,GAAI,CAAC+I,EAAG,KAAM,OACd,IAAIC,EACJ,GAAI,CACFA,EAAW,MAAMvJ,EAAS,aACxBsJ,EAAG,KACHA,EAAG,MAAQ,YACXA,EAAG,cAAgB,QACnBA,EAAG,aAAe,GAClBnH,CAAA,CAEJ,MAAQ,CACN,MACF,CACA,MAAMqH,GAAOD,GAAA,YAAAA,EAAU,OAAQ,CAAA,EACzBE,EAAOD,EAAK,cAAgB,CAAA,EAC5BE,EAAUF,EAAK,iBAAmB,CAAA,EACxCpB,EAAe,MAAM,QAAQoB,EAAK,MAAM,EAAIA,EAAK,OAAS,EAAE,EAG5D,MAAMvI,EAAO,CAAE,GAAGsH,EAAe,OAAA,EACjC,UAAWoB,KAAOF,EAAM,CAOtB,MAAMjE,EAAO,OAAOmE,GAAQ,SAAWA,EAAMA,GAAA,YAAAA,EAAK,KAClD,GAAI,CAACnE,EAAM,SACX,MAAMoE,EAAW,OAAOD,GAAQ,SAAWA,EAAI,KAAO,OAChDE,EAAa,OAAOF,GAAQ,SAAWA,EAAI,OAAS,OACpDG,EAAOD,GAAcA,IAAe,QAAU,UAAY,QAChE5I,EAAKuE,CAAI,EAAI,CACX,KAAAsE,EACA,QAASF,GAAY,OACrB,KAAM,OAAOD,GAAQ,SAAWA,EAAM,OACtC,QACEG,IAAS,UAAY,UAAUtE,CAAI,SAASqE,CAAU,GAAK,MAAA,CAEjE,CACA,UAAWnH,KAAKgH,EAAS,CAEvB,MAAMlE,EAAO,OAAO9C,GAAM,SAAWA,EAAIA,GAAA,YAAAA,EAAG,KACvC8C,IACLvE,EAAKuE,CAAI,EAAI,CACX,KAAM,UACN,QAAS,OACT,QAAS,UAAUA,CAAI,cAAA,EAE3B,CACA+C,EAAe,QAAUtH,EACzBqH,EAAerH,CAAI,EACfuH,EAAc,SAChBA,EAAc,QAAQ,SAAS,CAAE,QAASxF,GAAc,GAAG,IAAI,EAAG,CAEtE,EAEMoG,EAA4B,MAAMjH,GAAO,CAC7C,MAAM4H,EAAS7H,GAAqBC,EAAK+F,EAAiB,OAAO,EACjE,SAAW,CAACvF,EAASqH,EAAapH,CAAK,IAAKmH,EAAQ,CAClD,MAAMlH,EAAM,GAAGF,CAAO,IAAIqH,CAAW,IAAIpH,CAAK,GAC9C,GAAIqF,EAAiB,QAAQ,IAAIpF,CAAG,EAAG,SAEvC,GAAI3C,EAAO2C,CAAG,IAAM,OAAW,CAC7BoF,EAAiB,QAAQ,IAAIpF,CAAG,EAChC4F,EAAU5F,EAAK,CAAE,KAAM,OAAA,CAAS,EAChC,QACF,CACAoF,EAAiB,QAAQ,IAAIpF,CAAG,EAChC4F,EAAU5F,EAAK,CAAE,KAAM,aAAA,CAAe,EAEtC,IAAI0G,EACJ,GAAI,CACFA,EAAW,MAAMvJ,EAAS,cACxB2C,EACAqH,EACApH,EACA,EAAA,CAEJ,OAAS9B,EAAK,CACZmH,EAAiB,QAAQ,OAAOpF,CAAG,EACnC4F,EAAU5F,EAAK,CACb,KAAM,UACN,SAAS/B,GAAA,YAAAA,EAAK,UAAW,0BAAA,CAC1B,EACD,QACF,CACA,KAAM,CAAE,OAAAgD,EAAQ,KAAA0F,CAAA,EAASD,EACzB,GAAIzF,IAAW,KAAOA,IAAW,IAAK,CACpC,MAAMkF,GAAWQ,GAAA,YAAAA,EAAM,OAAQ3G,EACzBoH,IAAWT,GAAA,YAAAA,EAAM,UAAW,CAAA,GAAI,IAAIpI,GAAOA,EAAI,IAAI,EACzDjB,EAAU2I,GAAQ,CAChB,MAAM7H,EAAO,CAAE,GAAG6H,EAAM,CAACE,CAAQ,EAAGiB,CAAA,EACpC,OAAIrH,GAASA,IAAUoG,IAAU/H,EAAK2B,CAAK,EAAIqH,GACxChJ,CACT,CAAC,EACDwH,EAAU5F,EAAK,CAAE,KAAM,OAAA,CAAS,CAClC,MAAWiB,IAAW,IAEpB2E,EAAU5F,EAAK,CAAE,KAAM,OAAA,CAAS,GAEhCoF,EAAiB,QAAQ,OAAOpF,CAAG,EACnC4F,EAAU5F,EAAK,CACb,KAAM,UACN,SAAS2G,GAAA,YAAAA,EAAM,UAAW,6BAA6B1F,CAAM,GAAA,CAC9D,EAEL,CACF,EAEMoG,EAAW9J,EAAM,QACrB,IACEoE,GAAa,CACX,UAAW3B,GAAO0F,EAAe,QAAQ1F,CAAG,EAC5C,iBAAkB,IAAMqF,EAAiB,OAAA,CAC1C,EACH,CAAA,CAAC,EAGGiC,GAAW/J,EAAM,QACrB,IACEqG,GAAmB,CACjB,UAAW5D,GAAO0F,EAAe,QAAQ1F,CAAG,EAC5C,iBAAkB,IAAMqF,EAAiB,QACzC,oBAA0BlI,EAAS,KAAKwF,CAAI,EAAE,MAAM,IAAM,IAAI,CAAA,CAC/D,EACH,CAACxF,CAAQ,CAAA,EAGX,OACE2B,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,QAAQ,UAAU,OAAO,EAC5CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,QAAQ,SAAA,UAAO,EAC9BA,EAAAA,IAACE,EAAAA,MAAA,CACC,KAAK,WACL,MAAO,CAAE,QAAS,MAAA,EAClB,GAAG,WACH,KAAK,QACL,GAAG,OAAA,CAAA,EAEJqG,EAAY,OAAS,GACpBvG,MAAC,MAAA,CAAI,UAAU,0BAA0B,KAAK,QAC3C,SAAAuG,EAAY,IAAI,CAACrH,EAAKsJ,IACrBzI,EAAAA,KAAC,MAAA,CAAc,UAAU,yBACvB,SAAA,CAAAC,MAAC,QAAK,UAAU,8BACb,SAAA+F,GAAW7G,EAAI,IAAI,EACtB,EACAc,EAAAA,IAAC,OAAA,CAAK,UAAU,iCACb,WAAI,OAAA,CACP,CAAA,GANQwI,CAOV,CACD,EACH,QAED,MAAA,CAAI,KAAK,SAAS,SAAU,EAAG,UAAU,6BACxC,SAAAxI,EAAAA,IAACG,EAAAA,gBAAA,CACC,GAAI,QACJ,KAAM,QACN,WAAY,CACVrB,EACAA,EAAO,SAAS,KAAK,GAAG,CACtB,aAAciI,CAAA,CACf,EACD,GAAGnB,GACH0C,EACAC,EAAA,EAEF,eAAgB9G,GAAQ,CACtBmF,EAAc,QAAUnF,CAC1B,EACA,MAAApD,EACA,YACE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAEF,QAAS,CACP,MAAO,UACP,YAAa,EAAA,EAEf,MAAM,OACN,OAAO,QACP,MAAO,CACL,OAAQ,aACR,KAAM,EACN,SAAU,OACV,UAAW,MAAA,EAEb,SAAU,CAACA,EAAO+B,IAAe,CAC/BV,EAAarB,CAAK,EAClBgJ,EAAmBhJ,CAAiB,CACtC,CAAA,CAAA,CACF,CACF,CAAA,EACF,CAEJ,EC9UaoK,GAAuB,IAAM,CACxC,MAAMrK,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAGvC,CAACC,EAAaC,CAAc,EAAIC,EAAAA,SAAS,CAAA,CAAE,EAC3C,CAACC,EAAkBC,CAAmB,EAAIF,EAAAA,SAAS,CAAA,CAAE,EAG3DG,OAAAA,EAAAA,UAAU,IAAM,EACI,SAAY,CAC5B,MAAMC,EAAW,MAAM9K,EAAS,mBAAA,EAChC4K,EAAoBE,EAAS,UAAU,EACvCL,EAAeK,EAAS,KAAK,CAC/B,KACY,MAAM,QAAQ,KAAK,CACjC,EAAG,CAAC9K,CAAQ,CAAC,EAGX2B,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,mBAAmB,UAAU,OAAO,EACvDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,kBAAkB,SAAA,YAAS,SACzCE,EAAAA,MAAA,CAAM,GAAG,SAAS,KAAK,mBAAmB,GAAG,kBAC5C,SAAA,CAAAF,EAAAA,IAAC,SAAA,CAAO,MAAM,EAAA,CAAG,EAChB+I,EAAiB,IAAII,GACpBnJ,EAAAA,IAAC,SAAA,CAAO,MAAOmJ,EACZ,SAAAC,EAAAA,SAASD,CAAS,CAAA,EADUA,CAE/B,CACD,CAAA,CAAA,CACH,CAAA,EACF,EACApJ,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,cAAc,UAAU,OAAO,EAClDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,aAAa,SAAA,OAAI,SAC/BE,EAAAA,MAAA,CAAM,GAAG,SAAS,KAAK,cAAc,GAAG,aACvC,SAAA,CAAAF,EAAAA,IAAC,SAAA,CAAO,MAAM,EAAA,CAAG,EAChB4I,EAAY,IAAIS,GACfrJ,EAAAA,IAAC,SAAA,CAAO,MAAOqJ,EAAK,KACjB,SAAAA,EAAK,KAAA,EADuBA,EAAK,IAEpC,CACD,CAAA,CAAA,CACH,CAAA,EACF,EACAtJ,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,qBAAqB,UAAU,OAAO,EACzDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,oBAAoB,SAAA,qBAAkB,SACpDE,EAAAA,MAAA,CAAM,GAAG,SAAS,KAAK,qBAAqB,GAAG,oBAC9C,SAAA,CAAAF,EAAAA,IAAC,SAAA,CAAO,MAAM,EAAA,CAAG,EAChB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAE,EAAE,OAC/BA,EAAAA,IAAC,SAAA,CAAO,MAAOL,EACZ,SAAAA,CAAA,EADsBA,CAEzB,CACD,CAAA,CAAA,CACH,CAAA,CAAA,CACF,CAAA,EACF,CAEJ,ECtDa2J,GAAoB,CAAC,CAAE,aAAAC,KAAmB,CACrD,MAAMnL,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAGvC,CAACa,EAAgBC,CAAiB,EAAIX,EAAAA,SAAS,CAAA,CAAE,EAEvDG,OAAAA,EAAAA,UAAU,IAAM,CACd,eAAeS,GAAY,CACzB,MAAMC,EAAU,MAAMvL,EAAS,cAAc,QAAQ,EAC/CwL,EAAa,MAAMxL,EAAS,cAAc,WAAW,EACrDyL,EAAa,MAAMzL,EAAS,cAAc,WAAW,EACrD0L,EAAQH,EAAQ,OAAOC,CAAU,EAAE,OAAOC,CAAU,EAC1DJ,EACEK,EAAM,IAAIrG,IACD,CACL,MAAOA,EACP,MAAOA,CAAA,EAEV,CAAA,CAEL,CACAiG,EAAA,CACF,EAAG,CAACtL,CAAQ,CAAC,EAGX2B,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,gBAAgB,UAAU,OAAO,EACpDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,gBAAgB,SAAA,gBAAa,EAC5CD,EAAAA,KAAC,IAAA,CACC,UAAU,kBACV,MAAO,CAAE,SAAU,SAAU,MAAO,OAAQ,aAAc,KAAA,EAC3D,SAAA,CAAA,iFAEWC,EAAAA,IAAC,UAAO,SAAA,iBAAA,CAAe,EAAS,wCACnCA,EAAAA,IAAC,QAAK,SAAA,yCAAA,CAAuC,EAAO,IAAA,CAAA,CAAA,EAE7DA,EAAAA,IAAC,OAAA,CAAK,cAAY,uBAChB,SAAAA,EAAAA,IAAC+J,EAAAA,aAAA,CACC,UAAU,GACV,aAAAR,EACA,cAAeC,EACf,gBAAgB,gBAChB,YAAY,sDACZ,QAAS,GACT,YAAa,EAAA,CAAA,CACf,CACF,CAAA,EACF,CAEJ,ECnDaQ,GAAc,CAAC,CAAE,aAAAT,KAAmB,CAC/C,MAAMnL,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBACvC,CAAE,YAAAsB,CAAA,EAAgBC,iBAAA,EAClB,CAAA,CAAGC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,QAAQ,EAErC,CAACC,EAAgBC,CAAiB,EAAIzB,EAAAA,SAAS,CAAA,CAAE,EAEvDG,OAAAA,EAAAA,UAAU,IAAM,CACd,eAAeS,GAAY,CACzB,MAAMc,EAAQ,MAAMpM,EAAS,MAAA,EAC7BmM,EACEC,EAAM,IAAIC,IACD,CACL,MAAOA,EAAK,SACZ,MAAOA,EAAK,QAAA,EAEf,CAAA,CAEL,CACAf,EAAA,CACF,EAAG,CAACtL,CAAQ,CAAC,EAQb6K,EAAAA,UAAU,IAAM,CACVkB,EAAK,OAASA,EAAK,MAAM,OAAS,IAClCZ,GAAgBA,EAAa,OAAS,EACxCa,EAAQ,SAASb,EAAa,IAAIpF,GAAKA,EAAE,KAAK,CAAC,EACtC8F,GACTG,EAAQ,SAAS,CAACH,EAAY,QAAQ,CAAC,EAG3C,EAAG,CAACV,EAAcU,CAAW,CAAC,EAEvBV,GAAgBU,EACrBlK,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,SAAS,UAAU,OAAO,EAC7CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,SAAS,SAAA,SAAM,EAC9BA,EAAAA,IAAC,OAAA,CAAK,cAAY,eAChB,SAAAA,EAAAA,IAAC+J,EAAAA,aAAA,CACC,UAAU,GACV,cAAeO,EACf,gBAAgB,SAChB,YAAY,gBACZ,QAAS,EAAA,CAAA,CACX,CACF,CAAA,CAAA,CACF,EAEA,EAEJ,ECxDaI,GAAY,CAAC,CAAE,aAAAnB,KAAmB,CAC7C,MAAMnL,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAGvC,CAACgC,EAAMC,CAAO,EAAI9B,EAAAA,SAAS,CAAA,CAAE,EAEnCG,OAAAA,EAAAA,UAAU,IAAM,EACI,SAAY,CAC5B,MAAM0B,EAAO,MAAMvM,EAAS,SAAA,EAC5BwM,EACED,EAAK,IAAInG,IAAQ,CACf,MAAOA,EAAI,KACX,MAAOA,EAAI,YAAA,EACX,CAAA,CAEN,KACY,MAAM,QAAQ,KAAK,CACjC,EAAG,CAACpG,CAAQ,CAAC,EAGX2B,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,OAAO,UAAU,OAAO,EAC3CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,OAAO,SAAA,OAAI,EAC1BA,EAAAA,IAAC,OAAA,CAAK,cAAY,cAChB,SAAAA,EAAAA,IAAC+J,EAAAA,aAAA,CACC,QAAS,GACT,cAAeY,EACf,gBAAgB,OAChB,UAAU,GACV,YAAY,cACZ,aAAApB,CAAA,CAAA,CACF,CACF,CAAA,EACF,CAEJ,ECtCasB,GAAiB,CAAC,CAAE,iBAAAC,KAAuB,CACtD,MAAM1M,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAEvC,CAACoC,EAAYC,CAAa,EAAIlC,EAAAA,SAAS,CAAA,CAAE,EAG/CG,OAAAA,EAAAA,UAAU,IAAM,EACI,SAAY,CAC5B,MAAM8B,EAAa,MAAM3M,EAAS,WAAA,EAClC4M,EACED,EAAW,IAAIjK,IAAM,CACnB,MAAOA,EAAE,UACT,MAAOA,EAAE,SAAW,EACpB,CAAA,CAEN,KACY,MAAM,QAAQ,KAAK,CACjC,EAAG,CAAC1C,CAAQ,CAAC,EAGX2B,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,YAAY,UAAU,OAAO,EAChDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,YAAY,SAAA,cAAW,EACtCA,EAAAA,IAAC+J,EAAAA,aAAA,CACC,UAAU,GACV,cAAegB,EACf,gBAAgB,YAChB,YAAY,mBACZ,aAAc,CACZ,MAAOD,EACP,MAAOA,CAAA,CACT,CAAA,CACF,EACF,CAEJ,ECtCaG,GAAe,CAAC,CAAE,QAAAC,KAE3BnL,EAAAA,KAAC,MAAA,CAAI,UAAU,gBACb,SAAA,CAAAC,EAAAA,IAACmL,EAAAA,UAAA,EAAU,EACVD,CAAA,EACH,ECLSE,GAAmB,IAE5BrL,EAAAA,KAAC,MAAA,CAAI,UAAU,qCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,eAAe,UAAU,OAAO,EACnDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,cAAc,SAAA,iBAAc,EAC3CA,EAAAA,IAACE,EAAAA,MAAA,CACC,KAAK,OACL,KAAK,eACL,GAAG,cACH,YAAY,6BAAA,CAAA,CACd,EACF,ECXSmL,GAAmB,IAE5BtL,EAAAA,KAAC,MAAA,CAAI,UAAU,qCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,cAAc,UAAU,OAAO,EAClDD,EAAAA,IAAC,QAAA,CAAM,QAAQ,cAAc,SAAA,cAAW,EACxCA,EAAAA,IAACE,EAAAA,MAAA,CACC,KAAK,WACL,GAAG,WACH,KAAK,cACL,GAAG,cACH,YAAY,oBAAA,CAAA,CACd,EACF,ECZSoL,GAAgB,IAEzBvL,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,OAAO,UAAU,OAAO,EAC3CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,OAAO,SAAA,OAAI,SACzBE,EAAAA,MAAA,CAAM,GAAG,SAAS,KAAK,OAAO,GAAG,OAChC,SAAA,CAAAF,EAAAA,IAAC,SAAA,CAAO,MAAM,QAAQ,SAAA,QAAK,EAC3BA,EAAAA,IAAC,SAAA,CAAO,MAAM,YAAY,SAAA,WAAA,CAAS,CAAA,CAAA,CACrC,CAAA,EACF,ECHSuL,GAA2B,CAAC,CACvC,aAAAhC,EACA,MAAAiC,EACA,UAAAC,EAAY,EACd,IAAM,CACJ,MAAMrN,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAGvC,CAAE,OAAA+C,CAAA,EAAW9M,mBAAA,EAGb,CAAC+M,EAAeC,CAAgB,EAAI9C,EAAAA,SAAS,CAAA,CAAE,EAErDG,OAAAA,EAAAA,UAAU,IAAM,EACI,SAAY,CAC5B,GAAIyC,EAAO,cAAe,CACxB,MAAMG,EAAO,MAAMzN,EAAS,KAAKsN,EAAO,aAAa,EACrDE,EACEC,EAAK,QAAQ,IAAIrM,IACR,CACL,MAAOA,EAAI,KACX,MAAOA,EAAI,IAAA,EAEd,CAAA,CAEL,CACF,KACY,MAAM,QAAQ,KAAK,CACjC,EAAG,CAACpB,EAAUsN,EAAO,aAAa,CAAC,EAGjC3L,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,sBAAsB,UAAU,OAAO,EAC1DD,EAAAA,IAAC,QAAA,CAAM,QAAQ,qBAAqB,SAAA,sBAAmB,EACvDA,EAAAA,IAAC+J,EAAAA,aAAA,CACC,UAAA0B,EACA,aAAAlC,EACA,cAAAoC,EACA,gBAAiB,sBACjB,YAAa,6BACb,OAAQH,EACR,QAAS,EAAA,CAAA,CACX,EACF,CAEJ,EC7CaM,GAAgB,CAAC,CAC5B,aAAAvC,EACA,UAAAwC,EACA,MAAA/H,EACA,WAAAgI,EAAa,CAAA,EACb,QAAAC,EAAU,GACV,YAAAC,EAAc,EAChB,IAAM,CACJ,MAAM9N,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBAGvC,CAAE,OAAA+C,CAAA,EAAW9M,mBAAA,EAGb,CAACuN,EAAkBC,CAAmB,EAAItD,EAAAA,SAAS,CAAA,CAAE,EACrD,CAACuD,EAAiBC,CAAkB,EAAIxD,EAAAA,SAAS,IAAI,EACrDyD,EAAoBC,EAAAA,QAAQ,IAC5BL,GAAoBA,EAAiB,OAAS,EACzCA,EAEF,CAAA,EACN,CAACA,CAAgB,CAAC,EAGfM,EAAe,SAAY,CAC/B,GAAI,CACF,KAAM,CAAE,OAAAvK,EAAQ,KAAA0F,GAAS,MAAMxJ,EAAS,aACtCsN,EAAO,KACPA,EAAO,KACPA,EAAO,aACPA,EAAO,YACPA,EAAO,KAAA,EAET,GAAI9D,GAAA,MAAAA,EAAM,QACRwE,EACExE,EAAK,QAAQ,IAAIpI,IAAQ,CAAE,MAAOA,EAAI,KAAM,MAAOA,EAAI,IAAA,EAAO,CAAA,EAEhE8M,EAAmB,IAAI,MAClB,CAGL,MAAMI,EAAW,MAAM,QAAQ9E,GAAA,YAAAA,EAAM,MAAM,EACvCA,EAAK,OACF,IAAI3E,GAAKA,EAAE,OAAO,EAClB,OAAO,OAAO,EACd,KAAK;AAAA,CAAI,EACZ,GACJqJ,EAAmBI,IAAY9E,GAAA,YAAAA,EAAM,UAAW,IAAI,EACpDwE,EAAoB,CAAA,CAAE,CACxB,CACF,OAASO,EAAO,CACd,QAAQ,MAAM,0BAA2BA,CAAK,EAC9CL,EACEK,EAAM,SACJ,2DAAA,EAEJP,EAAoB,CAAA,CAAE,CACxB,CACF,EAEAnD,OAAAA,EAAAA,UAAU,IAAM,CACdwD,EAAA,CACF,EAAG,CAACf,EAAO,KAAMA,EAAO,KAAMA,EAAO,KAAK,CAAC,EAGzC3L,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAM8L,EAAW,UAAU,OAAO,QAC/C,QAAA,CAAM,QAASA,EAAW,MAAOC,EAC/B,SAAAhI,EACH,EACCqI,GACCtM,EAAAA,KAAC,MAAA,CACC,UAAU,mBACV,MAAO,CACL,MAAO,UACP,SAAU,WACV,aAAc,MACd,QAAS,MACT,gBAAiB,UACjB,aAAc,MACd,OAAQ,mBAAA,EAGV,SAAA,CAAAC,EAAAA,IAAC,UAAO,SAAA,mBAAA,CAAiB,EAAS,IAAEqM,CAAA,CAAA,CAAA,EAGxCrM,MAAC,OAAA,CAAK,cAAa,UAAU+L,CAAS,GACpC,SAAA/L,EAAAA,IAAC+J,EAAAA,aAAA,CACC,UAAU,GACV,aACEkC,EACI1C,EAAa,IAAI5J,IACR,CACL,MAAOA,EACP,MAAOA,CAAA,EAEV,EACD4J,EACA,CAAE,MAAOA,EAAc,MAAOA,GAC9B,KAEN,cAAegD,EACf,gBAAiBR,EACjB,QAASa,GAASH,EAAkB,EACpC,QAAAR,EACA,YAAAC,CAAA,CAAA,CACF,CACF,CAAA,EACF,CAEJ,EC9GaW,GAAsB,CAAC,CAAE,MAAAxO,KAAY,CAChD,MAAMM,EAASC,EAAAA,iBAAA,EACTkO,EAAU/N,EAAAA,MAAM,KAAA,EAChB,CAACgO,EAAUC,CAAW,EAAIlE,EAAAA,SAAS,EAAK,EAE9CG,EAAAA,UAAU,IAAM,CACd,GAAI,CAAC5K,GAASA,IAAU,GAAI,CAC1B2O,EAAY,EAAK,EACjB,MACF,CAEA,MAAMC,EACJ,OAAO5O,GAAU,SAAWA,EAAQ,KAAK,UAAUA,EAAO,KAAM,CAAC,EAEnE,GAAI,CACF,KAAK,MAAM4O,CAAW,EACtBD,EAAY,EAAK,CACnB,MAAc,CACZA,EAAY,EAAI,CAClB,CACF,EAAG,CAAC3O,CAAK,CAAC,EAEV,MAAM6O,EAAc7O,GACdA,GAAU,KACL,GAEL,OAAOA,GAAU,SACZA,EAEF,KAAK,UAAUA,EAAO,KAAM,CAAC,EAGhCqB,EAAeC,GAAO,CAI1B,GAHAhB,EAAO,cAAc,kBAAmBgB,CAAG,EAC3ChB,EAAO,gBAAgB,kBAAmB,EAAI,EAE1C,CAACgB,GAAOA,EAAI,KAAA,IAAW,GACzBqN,EAAY,EAAK,MAEjB,IAAI,CACF,KAAK,MAAMrN,CAAG,EACdqN,EAAY,EAAK,CACnB,MAAc,CACZA,EAAY,EAAI,CAClB,CAEJ,EAEA,OACEhN,EAAAA,IAAC,MAAA,CAAI,UAAU,+BACb,gBAAC,UAAA,CACC,SAAA,CAAAA,EAAAA,IAAC,UAAA,CAAQ,MAAO,CAAE,OAAQ,WACxB,SAAAA,EAAAA,IAAC,QAAA,CACC,MAAO,CACL,YAAa,MACb,QAAS,eACT,cAAe,MAAA,EAElB,SAAA,wBAAA,CAAA,EAGH,EACAA,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,kBAAkB,UAAU,OAAO,EACtDD,EAAAA,IAACE,EAAAA,MAAA,CACC,KAAK,WACL,MAAO,CAAE,QAAS,MAAA,EAClB,GAAG,WACH,KAAK,kBACL,GAAG,iBACH,SAAU7B,GAAS,CACjB,GAAI,GAACA,GAASA,EAAM,KAAA,IAAW,IAG/B,GAAI,CACF,MAAM8O,EAAS,KAAK,MAAM9O,CAAK,EAE/B,GACE,OAAO8O,GAAW,UAClBA,IAAW,MACX,CAAC,MAAM,QAAQA,CAAM,EACrB,CACA,MAAMC,EAAO,OAAO,KAAKD,CAAM,EACzBE,EAAqBhP,EAAM,MAAM,gBAAgB,EACvD,GACEgP,GACAA,EAAmB,OAASD,EAAK,OAEjC,MAAO,yBAEX,CAEA,MACF,MAAc,CACZ,MAAO,qBACT,CACF,CAAA,CAAA,EAEFpN,EAAAA,IAAC,MAAA,CACC,KAAK,SACL,SAAU,EACV,UAAW,iBACT+M,EAAW,gBAAkB,cAC/B,GACA,MAAO,CACL,OAAQA,EAAW,oBAAsB,OACzC,aAAc,MACd,UAAWA,EAAW,mCAAqC,MAAA,EAG7D,SAAA/M,EAAAA,IAACG,EAAAA,gBAAA,CACC,GAAI,kBACJ,KAAM,kBACN,WAAY,CAAC2M,CAAO,EACpB,MAAOI,EAAY7O,CAAK,EACxB,YAAa;AAAA;AAAA,GACb,QAAS,CACP,MAAO,UACP,YAAa,EAAA,EAEf,MAAM,OACN,OAAO,QACP,MAAO,CACL,OAAQ,aACR,KAAM,EACN,SAAU,OACV,UAAW,MAAA,EAEb,SAAU,CAACA,EAAO+B,IAAe,CAC/BV,EAAarB,CAAK,CACpB,CAAA,CAAA,CACF,CAAA,CACF,CAAA,CACF,CAAA,CACF,CAEJ,ECjHMiP,EAAN,MAAMA,CAAO,CAIX,YAAY1J,EAAM,CAChB,KAAK,KAAOA,CACd,CACF,EANE2J,GADID,EACG,MAAM,IAAIA,EAAO,KAAK,GAC7BC,GAFID,EAEG,OAAO,IAAIA,EAAO,MAAM,GAFjC,IAAME,EAANF,EASO,SAASG,GAAgB,CAAE,WAAAC,EAAa,CAAA,GAAM,CACnD,MAAMtP,EAAWsK,EAAAA,WAAWC,EAAAA,eAAe,EAAE,gBACvCgF,EAAWC,GAAAA,YAAA,EAEjB,GAAI,CAAE,SAAA5F,EAAU,iBAAA8C,EAAkB,KAAAlH,CAAA,EAASiK,GAAAA,UAAA,EAC3C,MAAMC,EAASlK,IAAS,OAAY4J,EAAO,KAAOA,EAAO,IAKnD,CAACO,EAAYC,CAAa,EAAIlF,EAAAA,SAAS,MAAS,EACtDG,EAAAA,UAAU,IAAM,CACV6E,IAAWN,EAAO,MAAQO,IAAe,IAC3CJ,EAAS,UAAU/J,CAAI,GAAI,CAAE,QAAS,GAAM,CAEhD,EAAG,CAACkK,EAAQC,EAAYnK,EAAM+J,CAAQ,CAAC,EAEvC,MAAMM,EAAkBnD,IAEpBlH,EACAA,EAAK,UAAU,EAAGA,EAAK,YAAY,GAAG,CAAC,EACvC,IAEEsK,EAAgB,CACpB,KAAMJ,IAAWN,EAAO,KAAO5J,EAAO,GACtC,UAAWkK,IAAWN,EAAO,IAAM1C,EAAmB,GACtD,aAAc,GACd,MAAO,GACP,KAAM9C,EACN,YAAa,GACb,YAAa,GACb,KAAM,YACN,OAAQ,CAAA,EACR,gBAAiB,EAAA,EAGbmG,EAAYzC,GAAU,OAC1B,MAAM0C,EAAS,CAAA,EAIf,OAAIN,IAAWN,EAAO,KAAO,GAACjO,EAAAmM,EAAO,eAAP,MAAAnM,EAAqB,UACjD6O,EAAO,aAAe,aAGtB,CAAC1C,EAAO,MACRA,EAAO,KAAK,SAAS,GAAG,GACxBA,EAAO,KAAK,WAAW,GAAG,GAC1BA,EAAO,KAAK,SAAS,IAAI,KAEzB0C,EAAO,KAAO,YAEZ1C,EAAO,OAAS,UAAY,CAACA,EAAO,QACtC0C,EAAO,MAAQ,YAEVA,CACT,EAeMC,EAAiB,CAbF,MAAO3C,EAAQ,CAAE,cAAA4C,EAAe,UAAAzH,KAAgB,CAC/DiH,IAAWN,EAAO,IACpB,MAAMe,EAAW7C,EAAQ7E,CAAS,EAAE,KAAKS,GAAK,CAC5C,OAAO,SAAS,CAAE,IAAK,EAAG,KAAM,EAAG,SAAU,SAAU,EACvDgH,EAAc,EAAK,CACrB,CAAC,EAED,MAAME,EAAU9C,EAAQ7E,CAAS,EAAE,KAAKS,GAAK,CAC3C,OAAO,SAAS,CAAE,IAAK,EAAG,KAAM,EAAG,SAAU,SAAU,EACvDgH,EAAc,EAAK,CACrB,CAAC,CAEL,CACoC,EAE9BG,EACJX,IAAWN,EAAO,WACf,KAAA,CAAG,SAAA,CAAA,SACK,UACN,OAAA,CAAK,UAAW,cAAcxF,CAAQ,8BACpC,SAAAA,CAAA,CACH,CAAA,CAAA,CACF,EAEAhI,EAAAA,IAAC,KAAA,CAAG,SAAA,MAAA,CAAI,EAGN0O,KACJ3O,EAAAA,KAAA4O,EAAAA,SAAA,CACE,SAAA,CAAA5O,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAAC,SAAM,SAAA,MAAA,CAAI,EAAQ,IAAE4D,CAAA,EACvB,EACA7D,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAAC,SAAM,SAAA,MAAA,CAAI,EAAQ,IAAEyD,EAAK,IAAA,CAAA,CAC5B,CAAA,EACF,EAGImL,EAAmBC,GAChBA,EAAW,IAAIC,GAAcA,EAAW,MAAM,EAGjDC,EAAsBC,GAAkB,CAC5C,GAAI,CAACA,GAAkBA,EAAe,KAAA,IAAW,GAC/C,OAAO,KAET,GAAI,CACF,OAAO,KAAK,MAAMA,CAAc,CAClC,MAAc,CACZ,OAAO,IACT,CACF,EAOMC,EAAmB,CAACC,EAAqBrQ,IACzCA,GAAgBA,EAAa,KAAA,IAAW,GACnC,UAAUqQ,CAAmB;AAAA,QAAYrQ,CAAY,GAGvD,UAAUqQ,CAAmB,GAGhCX,EAAa,MAAO7C,EAAQ7E,IAAc,CAC9C,KAAM,CAAE,OAAA3E,EAAQ,KAAA0F,GAAS,MAAMxJ,EAAS,WACtC4J,EACA0D,EAAO,KACPA,EAAO,aACPA,EAAO,YACPA,EAAO,OAAS,SACZuD,EAAiBvD,EAAO,qBAAsBA,EAAO,aAAa,EAClEA,EAAO,MACXA,EAAO,KACPA,EAAO,UACPA,EAAO,YAAckD,EAAiBlD,EAAO,WAAW,EAAI,KAC5DA,EAAO,iBACPA,EAAO,YAEPA,EAAO,qBAAuB,MAAM,QAAQA,EAAO,mBAAmB,EAClEA,EAAO,oBACP,OACJqD,EAAoBrD,EAAO,eAAe,CAAA,EAExCxJ,IAAW,KAAOA,IAAW,KAC3BwJ,EAAO,MACT,MAAMtN,EAAS,SAASsN,EAAO,KAAMA,EAAO,IAAI,EAElD7E,EAAU,CACR,QACE9G,EAAAA,KAAA4O,WAAA,CAAE,SAAA,CAAA,wBACsB/G,EAAK,KAAK,QAAM,IACtC5H,EAAAA,IAAC,KAAE,KAAM,UAAU4H,EAAK,IAAI,GAAK,WAAK,IAAA,CAAK,EAAI,GAAA,CAAA,CACjD,CAAA,CAEH,GAEDf,EAAU,CACR,QAAS,GAAGe,EAAK,OAAO,EAAA,CACzB,CAEL,EAEM4G,EAAY,MAAO9C,EAAQ7E,IAAc,CAC7C,KAAM,CAAE,OAAA3E,EAAQ,KAAA0F,GAAS,MAAMxJ,EAAS,UACtCsN,EAAO,KACPA,EAAO,aACPA,EAAO,YACPA,EAAO,OAAS,SACZuD,EAAiBvD,EAAO,qBAAsBA,EAAO,aAAa,EAClEA,EAAO,MACXA,EAAO,KACPA,EAAO,YAAckD,EAAiBlD,EAAO,WAAW,EAAI,KAC5DA,EAAO,iBACPA,EAAO,YACPA,EAAO,mBAEPA,EAAO,qBAAuB,MAAM,QAAQA,EAAO,mBAAmB,EAClEA,EAAO,oBACP,OACJA,EAAO,OACPqD,EAAoBrD,EAAO,eAAe,CAAA,EAEtCyD,EAAe,MAAM/Q,EAAS,SAClCsN,EAAO,KACPA,EAAO,KAAK,IAAIlH,GAAOA,CAAG,CAAA,GAEvBtC,IAAW,KAAOA,IAAW,MAAQiN,EAAa,SAAW,IAChEtI,EAAU,CACR,QACE9G,EAAAA,KAAA4O,WAAA,CAAE,SAAA,CAAA,wBACsB/G,EAAK,KAAK,QAAM,IACtC5H,EAAAA,IAAC,KAAE,KAAM,UAAU4H,EAAK,IAAI,GAAK,WAAK,IAAA,CAAK,EAAI,GAAA,CAAA,CACjD,CAAA,CAEH,EAEDf,EAAU,CACR,QAAS,GAAGe,EAAK,OAAO,EAAA,CACzB,CAEL,EAEMwH,EACJrP,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAA,CAAa,KAAK,OAAO,UAAU,OAAO,EAC3CD,EAAAA,IAAC,QAAA,CAAM,QAAQ,WAAW,SAAA,cAAW,EACrCA,EAAAA,IAACqP,GAAAA,cAAA,CAAc,KAAK,OAAO,KAAK,MAAA,CAAO,CAAA,EACzC,EAGIC,EAAkBtH,GACf,IAAI,IAAI,CAAC,YAAa,SAAU,WAAW,CAAC,EAAE,IAAIA,CAAQ,EAG7DuH,GAAsB,MAAM3L,GAAQ,iCACxC,MAAMH,EAAO,MAAMrF,EAAS,kBAAkBwF,CAAI,EAClD,GAAIH,IAAS,KACX,MAAO,CAAE,QAAS,QAAQG,CAAI,iBAAA,EAEhC,MAAM4L,EAAW,CACf,KAAM/L,EAAK,KACX,KAAMA,EAAK,KAAK,YAAA,EAChB,aAAcA,EAAK,QAAQ,YAC3B,YAAaA,EAAK,QAAQ,YAC1B,YAAaA,EAAK,QAAQ,WAC1B,MAAOA,EAAK,QAAQ,MACpB,KAAMA,EAAK,KACX,KAAMA,EAAK,QAAQ,KAAK,YAAA,EACxB,OAAQA,EAAK,OACb,gBAAiBA,EAAK,QAAQ,cAAA,EAGhC,GAAIA,EAAK,OAAS,SAAU,CAE1B,MAAMgM,GAAkBhM,EAAK,QAAQ,gBAE/BiM,EAAkBjM,EAAK,QAAQ,QAAQ,KAC3CkM,GAAKA,EAAE,OAAS,QAAA,EAGlB,GAAIF,GAAiB,CAInB,MAAMG,GADQnM,EAAK,QAAQ,OAAS,IACV,MAAM,iBAAiB,EAC3CoM,EAAoBD,EACtBA,EAAY,CAAC,EAAE,SACfrQ,EAAAkE,EAAK,QAAQ,iBAAb,YAAAlE,EAA6B,aAAc,GAE/C,MAAO,CACL,GAAGiQ,EACH,kBACEM,GAAAC,EAAAtM,EAAK,QAAQ,iBAAb,YAAAsM,EAA6B,YAA7B,YAAAD,EAAwC,cAC1C,aAAaE,GAAAC,GAAAC,EAAAzM,EAAK,QAAQ,iBAAb,YAAAyM,EAA6B,OAA7B,YAAAD,EAAmC,OAAnC,YAAAD,EAAyC,cACtD,oBAAoBG,EAAA1M,EAAK,QAAQ,iBAAb,YAAA0M,EAA6B,kBACjD,oBAAqB1M,EAAK,QAAQ,mBAAmB,QAC5C2M,GAAI,IAAA,EAEb,cAAe,GACf,qBAAsBP,CAAA,CAE1B,KAEE,OAAO,CACL,GAAGL,EACH,kBACEa,GAAAC,EAAA7M,EAAK,QAAQ,iBAAb,YAAA6M,EAA6B,YAA7B,YAAAD,EAAwC,cAC1C,aAAaE,GAAAC,GAAAC,EAAAhN,EAAK,QAAQ,iBAAb,YAAAgN,EAA6B,OAA7B,YAAAD,EAAmC,OAAnC,YAAAD,EAAyC,cACtD,oBAAoBG,EAAAjN,EAAK,QAAQ,iBAAb,YAAAiN,EAA6B,kBACjD,oBAAqBjN,EAAK,QAAQ,mBAAmB,OAC5C2M,EAAI,IAAA,EAEb,eAAeV,GAAA,YAAAA,EAAiB,OAAQ,GACxC,sBAAsBiB,EAAAlN,EAAK,QAAQ,iBAAb,YAAAkN,EAA6B,UAAA,CAGzD,CACA,OAAOnB,CACT,EAEMoB,EAAoB,CAAC/E,EAAMgF,EAASC,IAAe,CAEvD,GAAIjF,EAAK,UAAY,OAAW,CAC9BgF,EAAQ,IAAI,EACZC,EAAW,QAAQlN,CAAI,kBAAkB,EACzC,MACF,CAEK0L,EAAgBzD,EAAK,IAAI,IAC5BgF,EAAQ,IAAI,EACRhF,EAAK,OAAS,QAChB8B,EAAS,UAAU9B,EAAK,IAAI,YAAY,EAE1CiF,EAAW,QAAQlN,CAAI,eAAeiI,EAAK,IAAI,uBAAuB,EAE1E,EAEMkF,EAA2B,CAC/BlF,EACAmF,EACAH,EACAI,EACAC,EACAC,EACAC,EACAC,IACG,CAEY,CACb,eACA,QACA,OACA,cACA,cACA,OACA,OACA,uBACA,gBACA,cACA,mBACA,qBACA,sBACA,SACA,iBAAA,EAEK,QAAQC,GAAS,CACtB,GAAIA,IAAU,OACZN,EACEM,EACAzF,EAAKyF,CAAK,EAAE,IAAI9M,GAAOA,EAAI,IAAI,CAAA,UAExB8M,IAAU,SACnBN,EACEM,EACAzF,EAAKyF,CAAK,EAAE,IAAIC,GAASA,EAAM,QAAQ,CAAA,UAEhCD,IAAU,kBAAmB,CACtC,MAAMjT,EAAQwN,EAAKyF,CAAK,EAAI,KAAK,UAAUzF,EAAKyF,CAAK,EAAG,KAAM,CAAC,EAAI,GACnEN,EAAcM,EAAOjT,EAAO,EAAK,CACnC,MACE2S,EAAcM,EAAOzF,EAAKyF,CAAK,GAAK,GAAI,EAAK,CAEjD,CAAC,EACDT,EAAQhF,CAAI,EAIZoF,EACEjR,EAAAA,IAAC0K,GAAA,CACC,aAAcmB,EAAK,KAAK,IAAIpH,IACnB,CAAE,MAAOA,EAAE,KAAM,MAAOA,EAAE,WAAA,EAClC,CAAA,CAAA,CACH,EAEFyM,EACElR,EAAAA,IAAC8L,GAAA,CACC,aAAcD,EAAK,YACnB,UAAU,cACV,MAAM,cACN,QAAS,EAAA,CAAA,CACX,EAEEA,EAAK,qBACPuF,EACEpR,EAAAA,IAACuL,GAAA,CACC,aAAcM,EAAK,oBAAoB,IAAIuE,IAClC,CAAE,MAAOA,EAAK,MAAOA,CAAA,EAC7B,CAAA,CAAA,CACH,EAIJe,EACEnR,EAAAA,IAACsJ,GAAA,CACC,aACEuC,EAAK,cACD,CAAE,MAAOA,EAAK,cAAe,MAAOA,EAAK,eACzC,IAAA,CAAA,CAER,EAEEA,EAAK,QACPwF,EACErR,EAAAA,IAACgK,GAAA,CACC,aAAc6B,EAAK,OAAO,IAAI0F,IACrB,CAAE,MAAOA,EAAM,SAAU,MAAOA,EAAM,QAAA,EAC9C,CAAA,CAAA,CACH,CAGN,EAMA,OAAIzD,IAAWN,EAAO,MAAQO,IAAe,GAEzC/N,EAAAA,IAAC,MAAA,CAAI,UAAU,MACb,SAAAA,EAAAA,IAACwR,EAAAA,gBAAA,CACC,UAAWvD,EACX,iBAAkBD,CAAA,CAAA,EAEtB,EAKFjO,EAAAA,KAAC,MAAA,CAAI,UAAU,MACb,SAAA,CAAAC,EAAAA,IAACwR,EAAAA,gBAAA,CACC,UAAWvD,EACX,iBAAkBD,CAAA,CAAA,QAEnB,MAAA,CAAI,UAAU,eACb,SAAAhO,MAAC,MAAA,CAAI,UAAU,oBACb,SAAAA,EAAAA,IAACyR,EAAAA,OAAA,CACC,cAAAvD,EACA,SAAUC,EACV,iBAAkB,GAClB,eAAgB,GAChB,SAAU,MAAOzC,EAAQ,CAAE,cAAA4C,EAAe,UAAAzH,KAAgB,CACxD,GAAI,CACF,UAAW6K,KAAWrD,EACpB,MAAMqD,EAAQhG,EAAQ,CAAE,cAAA4C,EAAe,UAAAzH,EAAW,CAEtD,OAAS8F,EAAO,CACd,QAAQ,MAAM,sBAAuBA,CAAK,CAC5C,QAAA,CACE2B,EAAc,EAAK,CACrB,CACF,EAEC,SAAA,SAAgBqD,EAAa,CAC5B,KAAM,CACJ,aAAAC,EACA,OAAA1P,EACA,cAAA8O,EACA,OAAA5C,EACA,QAAAyD,EACA,QAAAC,EACA,MAAAC,CAAA,EACEJ,EACE,CAAClO,EAAMoN,CAAO,EAAI/H,EAAAA,SAAS,CAAA,CAAE,EAC7B,CAACkJ,EAAkBd,CAAmB,EAAIpI,EAAAA,SAAS,IAAI,EACvD,CAACmJ,EAAoBb,CAAqB,EAC9CtI,EAAAA,SAAS,IAAI,EACT,CAACoJ,EAAoBf,CAAqB,EAC9CrI,EAAAA,SAAS,IAAI,EACT,CAACqJ,GAAcd,CAAe,EAAIvI,EAAAA,SAAS,IAAI,EAC/C,CAACsJ,EAAYnB,CAAa,EAAInI,EAAAA,SAAS,IAAI,EAC3C,CAACoC,EAAS4F,EAAU,EAAIhI,EAAAA,SAAS,EAAE,EAEzCG,OAAAA,EAAAA,UAAU,IAAM,EACI,SAAY,CAC5B,GAAI6E,IAAWN,EAAO,KAAM,CAC1B,MAAM3B,EAAO,MAAM0D,GAAoB3L,CAAI,EAC3CgN,EAAkB/E,EAAMgF,EAASC,EAAU,EAC3CC,EACElF,EACAmF,EACAH,EACAI,EACAC,EACAC,EACAC,EACAC,CAAA,CAEJ,CACF,KACY,MAAM,QAAQ,KAAK,CACjC,EAAG,CAACL,CAAa,CAAC,SAEfqB,OAAA,CACE,SAAA,CAAAC,EAAAA,0BAA0BpQ,CAAM,EAChC4L,IAAWN,EAAO,MAAQtC,QACxBD,GAAA,CAAa,QAAAC,CAAA,CAAkB,EAEhCnL,EAAAA,KAAA4O,EAAAA,SAAA,CACE,SAAA,CAAA5O,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACZ,SAAA,CAAA0O,QACAnD,GAAA,CAAA,CAAc,CAAA,EACjB,EAEAvL,EAAAA,KAAC,MAAA,CAAI,UAAU,aACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,WACZ,SAAA,CAAA+N,IAAWN,EAAO,IACjBxN,EAAAA,IAAC6K,GAAA,CACC,iBAAAC,CAAA,CAAA,EAGF4D,EAAmBjL,CAAI,QAExB2H,GAAA,CAAA,CAAiB,CAAA,EACpB,EACC0C,IAAWN,EAAO,IAAM4B,EAAgB,SACxC/D,GAAA,CAAA,CAAiB,CAAA,EACpB,EAEAtL,EAAAA,KAAC,MAAA,CAAI,UAAU,aACZ,SAAA,CAAAiI,IAAa,WAAYvE,GAAA,YAAAA,EAAM,QAAS,SACvCqK,IAAWN,EAAO,KAChB0E,EAEAlS,EAAAA,IAACsJ,GAAA,CAAA,CAAkB,EAEnB,KACHtB,IAAa,UAAYvE,EAAK,OAAS,SACtCzD,EAAAA,IAAC7B,GAAA,CACC,SAAAC,EACA,MACEqF,EAAK,qBACDA,EAAK,qBACL,EAAA,CAAA,EAIRzD,EAAAA,IAACkG,GAAA,CACC,SAAA9H,EACA,MAAOqF,EAAK,MAAQA,EAAK,MAAQ,EAAA,CAAA,GAGnCuE,IAAa,UAAYvE,EAAK,OAAS,iBACtCgF,GAAA,CAAA,CAAqB,CAAA,EAE1B,EAEAzI,EAAAA,IAAC,MAAA,CAAI,UAAU,aACZ,SAAAgI,IAAa,UAAYvE,EAAK,OAAS,SACtCqK,IAAWN,EAAO,KAChBwE,EAEAhS,EAAAA,IAAC8L,GAAA,CACC,aAAc,CAAA,EACd,UAAU,cACV,MAAM,cACN,QAAS,EAAA,CAAA,EAGXgC,IAAWN,EAAO,KACpByE,EAEAjS,EAAAA,IAACuL,KAAyB,EAE9B,QAEC,MAAA,CAAI,UAAU,aACb,SAAAxL,EAAAA,KAAC,MAAA,CAAI,UAAU,WACZ,SAAA,CAAA+N,IAAWN,EAAO,KACjB2E,GAEAnS,EAAAA,IAACgK,GAAA,EAAY,EAEd8D,IAAWN,EAAO,KAAO4E,QAAc1H,GAAA,CAAA,CAAU,CAAA,CAAA,CACpD,CAAA,CACF,EAEC,OAAO,QAAQgD,CAAU,EAAE,IAC1B,CAAC,CAACzM,GAAKsR,CAAkB,IACvBvS,EAAAA,IAAC,MAAA,CAAc,UAAU,aACvB,SAAAA,EAAAA,IAACuS,EAAA,CACC,KAAA9O,EACA,OAAAqK,EACA,sBAAuB,CACrB0E,GACA,CAAE,QAAAC,EAAA,EAAY,CAAA,IACX,CACEpE,EAAe,SAASmE,EAAQ,IAC/BC,GACFpE,EAAe,QAAQmE,EAAQ,EAE/BnE,EAAe,KAAKmE,EAAQ,EAGlC,CAAA,CAAA,GAfMvR,EAiBV,CAAA,EAIJjB,EAAAA,IAAC,MAAA,CAAI,UAAU,6BACb,SAAAA,EAAAA,IAAC6M,GAAA,CACC,MACEpJ,EAAK,gBAAkBA,EAAK,gBAAkB,EAAA,CAAA,EAGpD,EAEAzD,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,SAAU4R,GAAgB,CAACE,EAC3B,UAAW,gBACTF,EAAe,0BAA4B,EAC7C,GAEC,WACC7R,EAAAA,KAAA4O,EAAAA,SAAA,CACE,SAAA,CAAA3O,EAAAA,IAAC0S,EAAAA,YAAA,EAAY,EAAE,WAAA,EAEjB,GAEC5E,IAAWN,EAAO,IAAM,UAAY,UACpCxF,GAAsB,GAAA,CAAA,CAE3B,CAAA,CACF,CAAA,EAEJ,CAEJ,CAAA,CAAA,EAEJ,CAAA,CACF,CAAA,EACF,CAEJ"}