{"version":3,"file":"index-B8BCP1aG.cjs","sources":["../src/app/components/AddNodeDropdown.jsx","../src/app/pages/NamespacePage/CompactSelect.jsx","../src/app/icons/ChevronIcon.jsx","../src/app/pages/NamespacePage/namespaceShortcuts.js","../src/app/pages/NamespacePage/FolderTree.jsx","../src/app/pages/NamespacePage/NewSubNamespace.jsx","../src/app/pages/NamespacePage/NamespaceNav.jsx","../src/app/pages/NamespacePage/nodeTypes.js","../src/app/pages/NamespacePage/index.jsx"],"sourcesContent":["import { useContext } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCurrentUser } from '../providers/UserProvider';\nimport DJClientContext from '../providers/djclient';\n\nconst PERSONAL_NS_PREFIX =\n  process.env.REACT_APP_PERSONAL_NAMESPACE_PREFIX || 'users';\n\nfunction resolvePersonalNamespace(namespace, username) {\n  if (namespace && namespace !== 'default') return namespace;\n  if (!username) return 'default';\n  const handle = username\n    .split('@')[0]\n    .toLowerCase()\n    .replace(/[^a-z0-9_]/g, '_');\n  return `${PERSONAL_NS_PREFIX}.${handle}`;\n}\n\nexport default function AddNodeDropdown({ namespace }) {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const { currentUser } = useCurrentUser();\n  const navigate = useNavigate();\n  const ns = resolvePersonalNamespace(namespace, currentUser?.username);\n  const isPersonalFallback =\n    (!namespace || namespace === 'default') && currentUser?.username;\n\n  const goTo = path => async e => {\n    e.preventDefault();\n    if (isPersonalFallback) {\n      // Create the personal namespace if it doesn't exist yet (idempotent on the server)\n      try {\n        await djClient.addNamespace(ns);\n      } catch (err) {\n        console.error('Failed to ensure namespace exists:', err);\n      }\n    }\n    navigate(path);\n  };\n\n  return (\n    <span\n      className=\"menu-link\"\n      style={{\n        display: 'inline-flex',\n        alignItems: 'center',\n        margin: 0,\n        width: '130px',\n      }}\n    >\n      <span className=\"menu-title\">\n        <div className=\"dropdown\">\n          <span className=\"add_node\">+ Add Node</span>\n          <div className=\"dropdown-content add-node-dropdown-content\">\n            <a href={`/create/source`}>\n              <div className=\"node_type__source node_type_creation_heading\">\n                Register Table\n              </div>\n            </a>\n            <a\n              href={`/create/transform/${ns}`}\n              onClick={goTo(`/create/transform/${ns}`)}\n            >\n              <div className=\"node_type__transform node_type_creation_heading\">\n                Transform\n              </div>\n            </a>\n            <a\n              href={`/create/metric/${ns}`}\n              onClick={goTo(`/create/metric/${ns}`)}\n            >\n              <div className=\"node_type__metric node_type_creation_heading\">\n                Metric\n              </div>\n            </a>\n            <a\n              href={`/create/dimension/${ns}`}\n              onClick={goTo(`/create/dimension/${ns}`)}\n            >\n              <div className=\"node_type__dimension node_type_creation_heading\">\n                Dimension\n              </div>\n            </a>\n            <a href={`/create/tag`}>\n              <div className=\"entity__tag node_type_creation_heading\">Tag</div>\n            </a>\n            <a href={`/create/cube/${ns}`} onClick={goTo(`/create/cube/${ns}`)}>\n              <div className=\"node_type__cube node_type_creation_heading\">\n                Cube\n              </div>\n            </a>\n          </div>\n        </div>\n      </span>\n    </span>\n  );\n}\n","import Select, { components } from 'react-select';\n\n// react-select renders a DOM node per option with no virtualization, so a large\n// list (e.g. all users) makes the menu sluggish to open/scroll. Cap how many\n// options are rendered at once; react-select still filters the full list as the\n// user types, so any option remains reachable by searching.\nconst MAX_RENDERED_OPTIONS = 100;\n\nconst WindowedMenuList = props => {\n  const { children } = props;\n  if (Array.isArray(children) && children.length > MAX_RENDERED_OPTIONS) {\n    return (\n      <components.MenuList {...props}>\n        {children.slice(0, MAX_RENDERED_OPTIONS)}\n        <div\n          style={{\n            padding: '6px 12px',\n            fontSize: '11px',\n            color: '#888',\n          }}\n        >\n          Showing first {MAX_RENDERED_OPTIONS} of {children.length}. Type to\n          narrow…\n        </div>\n      </components.MenuList>\n    );\n  }\n  return <components.MenuList {...props}>{children}</components.MenuList>;\n};\n\n// Compact select with label above - saves horizontal space\nexport default function CompactSelect({\n  label,\n  name,\n  options,\n  value,\n  onChange,\n  isMulti = false,\n  isClearable = true,\n  placeholder = 'Select...',\n  minWidth = '100px',\n  flex = 1,\n  isLoading = false,\n  testId = null,\n  formatOptionLabel = undefined,\n  onMenuOpen = undefined,\n}) {\n  // For single select, find the matching option\n  // For multi select, filter to matching options\n  const selectedValue = isMulti\n    ? value?.length\n      ? options.filter(o => value.includes(o.value))\n      : []\n    : value\n    ? options.find(o => o.value === value)\n    : null;\n\n  return (\n    <div\n      style={{\n        display: 'flex',\n        flexDirection: 'column',\n        gap: '2px',\n        flex,\n        minWidth,\n      }}\n      data-testid={testId}\n    >\n      <label\n        style={{\n          fontSize: '10px',\n          fontWeight: '600',\n          color: '#666',\n          textTransform: 'uppercase',\n          letterSpacing: '0.5px',\n        }}\n      >\n        {label}\n      </label>\n      <Select\n        name={name}\n        isClearable={isClearable}\n        isMulti={isMulti}\n        isLoading={isLoading}\n        placeholder={placeholder}\n        onChange={onChange}\n        onMenuOpen={onMenuOpen}\n        value={selectedValue}\n        formatOptionLabel={formatOptionLabel}\n        components={{ MenuList: WindowedMenuList }}\n        styles={{\n          control: base => ({\n            ...base,\n            minHeight: '32px',\n            height: isMulti ? 'auto' : '32px',\n            fontSize: '12px',\n            backgroundColor: 'white',\n          }),\n          valueContainer: base => ({\n            ...base,\n            padding: '0 6px',\n          }),\n          input: base => ({\n            ...base,\n            margin: 0,\n            padding: 0,\n          }),\n          indicatorSeparator: () => ({\n            display: 'none',\n          }),\n          dropdownIndicator: base => ({\n            ...base,\n            padding: '4px',\n          }),\n          clearIndicator: base => ({\n            ...base,\n            padding: '4px',\n          }),\n          option: base => ({\n            ...base,\n            fontSize: '12px',\n            padding: '6px 10px',\n          }),\n          multiValue: base => ({\n            ...base,\n            fontSize: '11px',\n          }),\n        }}\n        options={options}\n      />\n    </div>\n  );\n}\n","import React from 'react';\n\n// A clean chevron that points right when collapsed and rotates down when open.\n// Shared by the rail folder tree and the rail's collapsible group headings so\n// expand/collapse looks the same everywhere. Color comes from `currentColor`.\nexport default function ChevronIcon({ open = false, size = 12 }) {\n  return (\n    <svg\n      width={size}\n      height={size}\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"3\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      style={{\n        transform: open ? 'rotate(90deg)' : 'none',\n        transition: 'transform 0.12s ease',\n      }}\n    >\n      <polyline points=\"9 6 15 12 9 18\" />\n    </svg>\n  );\n}\n","// Per-device pinned namespaces, backed by localStorage (no backend).\nconst PINNED_KEY = 'dj.ns.pinned';\n\nfunction read(key) {\n  try {\n    const v = JSON.parse(localStorage.getItem(key));\n    return Array.isArray(v) ? v.filter(x => typeof x === 'string') : [];\n  } catch {\n    return [];\n  }\n}\n\nfunction write(key, list) {\n  try {\n    localStorage.setItem(key, JSON.stringify(list));\n  } catch {\n    /* ignore quota / unavailable storage */\n  }\n}\n\nexport function getPinned() {\n  return read(PINNED_KEY);\n}\n\nexport function togglePinned(ns) {\n  const cur = read(PINNED_KEY);\n  const next = cur.includes(ns) ? cur.filter(x => x !== ns) : [...cur, ns];\n  write(PINNED_KEY, next);\n  return next;\n}\n\nexport { PINNED_KEY };\n","import React, { useState } from 'react';\nimport ChevronIcon from '../../icons/ChevronIcon';\n\n// Recursive folder tree for the namespace rail. `nodes` are hierarchy nodes\n// ({ namespace, path, children }) — the descendants of the current namespace.\n// Clicking the chevron expands/collapses that level in place (no navigation);\n// clicking the name navigates into it (onSelect(path)). Collapsed beyond the\n// top level so a deep tree only grows on demand.\nfunction FolderTreeRows({ nodes, depth, expanded, onToggle, onSelect }) {\n  return nodes.map(node => {\n    const hasChildren = node.children?.length > 0;\n    const isOpen = expanded.has(node.path);\n    return (\n      <React.Fragment key={node.path}>\n        <div\n          className=\"dj-ns-nav-item\"\n          role=\"button\"\n          tabIndex={0}\n          title={node.path}\n          style={{ paddingLeft: `${depth * 14}px` }}\n          onClick={() => onSelect(node.path)}\n          onKeyDown={e => {\n            if (e.key === 'Enter') onSelect(node.path);\n          }}\n        >\n          {hasChildren ? (\n            <button\n              type=\"button\"\n              aria-label={isOpen ? 'Collapse' : 'Expand'}\n              aria-expanded={isOpen}\n              onClick={e => {\n                e.stopPropagation();\n                onToggle(node.path);\n              }}\n              style={{\n                width: '18px',\n                minWidth: '18px',\n                flexShrink: 0,\n                padding: 0,\n                margin: 0,\n                border: 'none',\n                background: 'none',\n                cursor: 'pointer',\n                color: '#64748b',\n                display: 'inline-flex',\n                alignItems: 'center',\n                justifyContent: 'center',\n              }}\n            >\n              <ChevronIcon open={isOpen} />\n            </button>\n          ) : (\n            <span style={{ width: '18px', minWidth: '18px', flexShrink: 0 }} />\n          )}\n          <span className=\"dj-ns-nav-name\">{node.namespace}</span>\n        </div>\n        {hasChildren && isOpen ? (\n          <FolderTreeRows\n            nodes={node.children}\n            depth={depth + 1}\n            expanded={expanded}\n            onToggle={onToggle}\n            onSelect={onSelect}\n          />\n        ) : null}\n      </React.Fragment>\n    );\n  });\n}\n\n// Rail folder tree rooted at the current namespace's children. Remount it\n// (via a `key` on the current path) to reset expansion when the root changes.\nexport default function FolderTree({ folders, onSelect }) {\n  const [expanded, setExpanded] = useState(() => new Set());\n  if (!folders || folders.length === 0) return null;\n  const onToggle = path =>\n    setExpanded(prev => {\n      const next = new Set(prev);\n      if (next.has(path)) {\n        next.delete(path);\n      } else {\n        next.add(path);\n      }\n      return next;\n    });\n  return (\n    <div className=\"dj-ns-folder-nav\">\n      <div className=\"dj-ns-tree-heading\">Folders</div>\n      <FolderTreeRows\n        nodes={folders}\n        depth={0}\n        expanded={expanded}\n        onToggle={onToggle}\n        onSelect={onSelect}\n      />\n    </div>\n  );\n}\n","import React, { useState } from 'react';\n\n// Inline \"new folder\" affordance for the rail folder tree: a subtle button that\n// expands into a text field for the leaf name. Enter creates `<parent>.<name>`\n// (via onCreate), Esc / empty-blur cancels. Only rendered for non-git-backed\n// namespaces (namespaces under git control are managed via git, not the UI).\nexport default function NewSubNamespace({ parent, onCreate }) {\n  const [adding, setAdding] = useState(false);\n  const [name, setName] = useState('');\n  const [error, setError] = useState(null);\n\n  // Sanitize to a single namespace segment for the create call.\n  const segment = name.trim().replace(/[^a-zA-Z0-9_]/g, '_');\n\n  const reset = () => {\n    setAdding(false);\n    setName('');\n    setError(null);\n  };\n\n  const submit = async () => {\n    if (!segment) {\n      reset();\n      return;\n    }\n    const res = await onCreate(`${parent}.${segment}`);\n    if (res?._error) {\n      setError(res.message || 'Failed to create namespace');\n    } else {\n      reset();\n    }\n  };\n\n  if (!adding) {\n    // Match the folder rows (dj-ns-nav-item): same 15px size/padding, with the\n    // ＋ sitting in the same column the folder chevrons occupy. Muted color marks\n    // it as a secondary \"add\" affordance.\n    return (\n      <button\n        type=\"button\"\n        className=\"dj-ns-nav-item\"\n        onClick={() => setAdding(true)}\n        style={{ paddingLeft: 0, color: '#64748b' }}\n      >\n        <span\n          style={{\n            width: '18px',\n            minWidth: '18px',\n            flexShrink: 0,\n            display: 'inline-flex',\n            alignItems: 'center',\n            justifyContent: 'center',\n            fontSize: '16px',\n            lineHeight: 1,\n          }}\n        >\n          ＋\n        </span>\n        <span className=\"dj-ns-nav-name\">New folder</span>\n      </button>\n    );\n  }\n\n  return (\n    <div style={{ marginTop: '4px', paddingLeft: '18px', paddingRight: '8px' }}>\n      <input\n        autoFocus\n        type=\"text\"\n        value={name}\n        onChange={e => setName(e.target.value)}\n        onKeyDown={e => {\n          if (e.key === 'Enter') submit();\n          else if (e.key === 'Escape') reset();\n        }}\n        onBlur={() => {\n          if (!name.trim()) reset();\n        }}\n        placeholder=\"Folder name\"\n        aria-label=\"New sub-namespace name\"\n        style={{\n          width: '100%',\n          boxSizing: 'border-box',\n          padding: '6px 8px',\n          fontSize: '15px',\n          border: '1px solid #cbd5e1',\n          borderRadius: '6px',\n          outline: 'none',\n        }}\n      />\n      {error ? (\n        <div style={{ marginTop: '4px', fontSize: '12px', color: '#b91c1c' }}>\n          {error}\n        </div>\n      ) : null}\n    </div>\n  );\n}\n","import React, { useState } from 'react';\nimport ChevronIcon from '../../icons/ChevronIcon';\nimport {\n  buildNamespaceOptions,\n  searchNamespaces,\n  immediateChildren,\n} from './namespaceOptions';\nimport { getPinned, togglePinned } from './namespaceShortcuts';\nimport FolderTree from './FolderTree';\nimport NewSubNamespace from './NewSubNamespace';\n\n// Git context for a selected namespace, derived from the raw namespace list.\nfunction gitContext(gitByNs, ns) {\n  const g = gitByNs[ns];\n  if (!g) return null;\n  if (g.__typename === 'GitRootConfig') {\n    return {\n      root: ns,\n      defaultBranch: g.defaultBranch,\n      activeBranch: g.defaultBranch,\n      isRoot: true,\n    };\n  }\n  if (g.__typename === 'GitBranchConfig') {\n    return {\n      root: g.parentNamespace,\n      defaultBranch: g.root?.defaultBranch,\n      activeBranch: g.branch,\n      isRoot: false,\n    };\n  }\n  return null;\n}\n\nexport default function NamespaceNav({\n  namespaces,\n  hierarchy,\n  currentNamespace,\n  gitRoots,\n  onSelect,\n  canCreateNamespace = false,\n  onCreateNamespace,\n}) {\n  const [collapsed, setCollapsed] = useState({ 'Top-level': true });\n  const [pinned, setPinned] = useState(() => getPinned());\n  // Filter only exists in the no-namespace (\"All namespaces\") view, where there's\n  // no current scope to confuse it with. Once a namespace is selected, jumping\n  // elsewhere is done via the header's namespace switcher.\n  const [filter, setFilter] = useState('');\n\n  const isFiltering = filter.trim() !== '';\n  const matches = isFiltering ? searchNamespaces(namespaces || [], filter) : [];\n  const showList = !currentNamespace;\n  const groups = showList ? buildNamespaceOptions(namespaces || []) : [];\n\n  const gitByNs = {};\n  for (const ns of namespaces || []) {\n    gitByNs[ns.namespace] = ns.git;\n  }\n  const pinnedSet = new Set(pinned);\n\n  const isOpen = label => !collapsed[label];\n  const toggleGroup = label =>\n    setCollapsed(c => ({ ...c, [label]: !c[label] }));\n\n  const onPin = (e, ns) => {\n    e.stopPropagation();\n    setPinned(togglePinned(ns));\n  };\n\n  const renderRow = (ns, keyPrefix) => (\n    <div\n      key={`${keyPrefix}-${ns}`}\n      className=\"dj-ns-nav-item\"\n      role=\"button\"\n      tabIndex={0}\n      title={ns}\n      onClick={() => onSelect(ns)}\n      onKeyDown={e => {\n        if (e.key === 'Enter') onSelect(ns);\n      }}\n    >\n      <span className=\"dj-ns-nav-name\">{ns}</span>\n      <button\n        type=\"button\"\n        className={`dj-ns-star${pinnedSet.has(ns) ? ' pinned' : ''}`}\n        aria-label={`${pinnedSet.has(ns) ? 'Unpin' : 'Pin'} ${ns}`}\n        aria-pressed={pinnedSet.has(ns)}\n        onClick={e => onPin(e, ns)}\n      >\n        {pinnedSet.has(ns) ? '★' : '☆'}\n      </button>\n    </div>\n  );\n\n  // One uniform collapsible section used for Pinned and the git groups.\n  const renderGroup = (label, names, keyPrefix) => {\n    const open = isOpen(label);\n    return (\n      <div key={keyPrefix}>\n        <button\n          type=\"button\"\n          className=\"dj-ns-group-heading\"\n          aria-expanded={open}\n          onClick={() => toggleGroup(label)}\n        >\n          <span className=\"dj-ns-chevron\">\n            <ChevronIcon open={open} />\n          </span>\n          <span className=\"dj-ns-group-label\">{label}</span>\n          <span className=\"dj-ns-group-count\">{names.length}</span>\n        </button>\n        {open ? names.map(ns => renderRow(ns, keyPrefix)) : null}\n      </div>\n    );\n  };\n\n  // Selected (subtree) state — ctx is still needed for subtreePath (git-root folders).\n  const ctx = currentNamespace ? gitContext(gitByNs, currentNamespace) : null;\n  const subtreePath =\n    ctx?.isRoot && ctx.defaultBranch\n      ? `${ctx.root}.${ctx.defaultBranch}`\n      : currentNamespace;\n\n  return (\n    <div>\n      {showList ? (\n        <>\n          <div className=\"dj-ns-filter\">\n            <input\n              type=\"text\"\n              className=\"dj-ns-filter-input\"\n              value={filter}\n              onChange={e => setFilter(e.target.value)}\n              placeholder=\"Filter namespaces…\"\n              aria-label=\"Filter namespaces\"\n            />\n            {isFiltering ? (\n              <button\n                type=\"button\"\n                className=\"dj-ns-filter-clear\"\n                aria-label=\"Clear filter\"\n                title=\"Clear filter\"\n                onClick={() => setFilter('')}\n              >\n                ✕\n              </button>\n            ) : null}\n          </div>\n          {isFiltering ? (\n            matches.length === 0 ? (\n              <div\n                style={{ padding: '6px', color: '#64748b', fontSize: '12px' }}\n              >\n                No namespaces match \"{filter.trim()}\".\n              </div>\n            ) : (\n              renderGroup('Matches', matches, 'matches')\n            )\n          ) : (\n            <>\n              {pinned.length > 0 ? renderGroup('Pinned', pinned, 'pin') : null}\n              {groups.map(group =>\n                renderGroup(\n                  group.label,\n                  group.options.map(o => o.value),\n                  `grp-${group.label}`,\n                ),\n              )}\n            </>\n          )}\n        </>\n      ) : (\n        // Folder navigation: the current namespace's sub-namespace tree. Chevron\n        // expands a level in place; clicking a name drills in. Going up is handled\n        // by the header breadcrumb; switching namespace by the filter box\n        // (no-namespace view) or the header switcher. Keyed by the current path so\n        // expansion resets when the tree re-roots.\n        <>\n          <FolderTree\n            key={subtreePath}\n            folders={immediateChildren(hierarchy || [], subtreePath)}\n            onSelect={onSelect}\n          />\n          {canCreateNamespace ? (\n            <NewSubNamespace\n              parent={subtreePath}\n              onCreate={onCreateNamespace}\n            />\n          ) : null}\n        </>\n      )}\n    </div>\n  );\n}\n","// Canonical node-type ordering + badge colors for the NamespacePage views.\n// Single source of truth shared by the namespace landing preview (index.jsx) and the\n// rail's per-namespace type summary (NamespaceTypeSummary.jsx) so the order and colors\n// can't drift between them.\n\nexport const NODE_TYPE_ORDER = [\n  'metric',\n  'cube',\n  'dimension',\n  'transform',\n  'source',\n];\n\nexport const NODE_TYPE_COLORS = {\n  metric: { bg: '#fad7dd', color: '#a2283e' },\n  cube: { bg: '#dbafff', color: '#580076' },\n  dimension: { bg: '#ffefd0', color: '#a96621' },\n  transform: { bg: '#ccefff', color: '#0063b4' },\n  source: { bg: '#ccf7e5', color: '#00b368' },\n};\n","import { useParams, useSearchParams, useNavigate } from 'react-router-dom';\nimport {\n  useContext,\n  useEffect,\n  useState,\n  useCallback,\n  useRef,\n  useMemo,\n} from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { useCurrentUser } from '../../providers/UserProvider';\nimport AddNodeDropdown from '../../components/AddNodeDropdown';\nimport NodeListActions from '../../components/NodeListActions';\nimport NamespaceHeader from '../../components/NamespaceHeader';\nimport SplitFilter from '../../components/SplitFilter';\nimport Tooltip from '../../components/Tooltip';\nimport {\n  secondaryButtonStyle,\n  onSecondaryHover,\n  onSecondaryOut,\n} from '../../components/buttonStyles';\nimport LoadingIcon from '../../icons/LoadingIcon';\nimport CompactSelect from './CompactSelect';\nimport NamespaceNav from './NamespaceNav';\nimport { isHiddenNamespace } from './namespaceOptions';\nimport { NODE_TYPE_ORDER, NODE_TYPE_COLORS } from './nodeTypes';\nimport { getDJUrl } from '../../services/DJService';\n\nimport 'styles/node-list.css';\nimport 'styles/sorted-table.css';\n\nconst AVATAR_COLORS = [\n  ['#dbeafe', '#1e40af'],\n  ['#dcfce7', '#166534'],\n  ['#fef3c7', '#92400e'],\n  ['#fce7f3', '#9d174d'],\n  ['#ede9fe', '#5b21b6'],\n  ['#ffedd5', '#9a3412'],\n  ['#fee2e2', '#991b1b'],\n  ['#d1fae5', '#065f46'],\n];\n\nfunction avatarColorIndex(username) {\n  let hash = 0;\n  for (let i = 0; i < username.length; i++) {\n    hash = (hash * 31 + username.charCodeAt(i)) >>> 0;\n  }\n  return hash % AVATAR_COLORS.length;\n}\n\nconst FIELD_CONFIG = {\n  name: { label: 'Name' },\n  displayName: { label: 'Display name' },\n  type: { label: 'Type' },\n  status: {\n    label: 'Validation',\n    tooltip: 'Whether this node validates successfully.',\n  },\n  mode: {\n    label: 'Publish state',\n    tooltip: 'Whether this node is published or still a draft.',\n  },\n  owners: { label: 'Owners' },\n  updatedAt: { label: 'Updated' },\n};\n\nconst CELL_STYLE = {\n  padding: '8px 16px',\n};\n\nconst MIDDLE_CELL_STYLE = {\n  ...CELL_STYLE,\n  verticalAlign: 'middle',\n};\n\nconst NODE_TYPE_DESCRIPTIONS = {\n  CUBE: 'A curated set of metrics and dimensions for querying together.',\n  DIMENSION: 'Descriptive attributes used to group, filter, and join metrics.',\n  METRIC: 'A reusable business calculation or measure.',\n  SOURCE: 'A physical table registered in DJ as a source node.',\n  TRANSFORM: 'A SQL-defined node derived from sources or other DJ nodes.',\n};\n\nfunction splitNodeName(nodeName) {\n  const lastDot = nodeName.lastIndexOf('.');\n  if (lastDot === -1) {\n    return { leafName: nodeName, namespacePath: '' };\n  }\n  return {\n    leafName: nodeName.slice(lastDot + 1),\n    namespacePath: nodeName.slice(0, lastDot),\n  };\n}\n\nfunction nodeState(current) {\n  const isPublished = current.mode === 'PUBLISHED';\n  const isValid = current.status === 'VALID';\n  return {\n    isPublished,\n    isValid,\n    publishLabel: isPublished ? 'Published' : 'Draft',\n    validationLabel: isValid ? 'Valid' : 'Needs fixes',\n    publishTooltip: isPublished\n      ? 'This version is published and expected to be usable by downstream nodes.'\n      : 'This version is a draft and may still be incomplete.',\n    validationTooltip: isValid\n      ? 'This node validates successfully.'\n      : 'This node has validation errors. Open it to see what needs to be fixed.',\n    needsAttention: !isPublished || !isValid,\n    borderColor: isValid && isPublished ? '#28a745' : '#d39e00',\n    backgroundColor: isValid && isPublished ? '#eaf7ee' : '#fff7df',\n    color: isValid && isPublished ? '#1f7a3a' : '#8a5b00',\n  };\n}\n\nfunction exactDateTime(value) {\n  return new Date(value).toLocaleString('en-us', {\n    year: 'numeric',\n    month: 'short',\n    day: 'numeric',\n    hour: 'numeric',\n    minute: '2-digit',\n  });\n}\n\nfunction relativeDate(value) {\n  const updatedAt = new Date(value);\n  const diffMs = Date.now() - updatedAt.getTime();\n  const absMs = Math.abs(diffMs);\n  const units = [\n    ['year', 365 * 24 * 60 * 60 * 1000],\n    ['month', 30 * 24 * 60 * 60 * 1000],\n    ['week', 7 * 24 * 60 * 60 * 1000],\n    ['day', 24 * 60 * 60 * 1000],\n    ['hour', 60 * 60 * 1000],\n    ['minute', 60 * 1000],\n  ];\n\n  for (const [unit, ms] of units) {\n    if (absMs >= ms) {\n      const valueForUnit = Math.round(absMs / ms);\n      return `${valueForUnit} ${unit}${valueForUnit === 1 ? '' : 's'} ${\n        diffMs >= 0 ? 'ago' : 'from now'\n      }`;\n    }\n  }\n  return 'just now';\n}\n\nexport function NamespacePage() {\n  const ASC = 'ascending';\n  const DESC = 'descending';\n\n  const fields = [\n    'name',\n    'displayName',\n    'type',\n    'status',\n    'mode',\n    'owners',\n    'updatedAt',\n  ];\n\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const { currentUser } = useCurrentUser();\n  var { namespace } = useParams();\n  const navigate = useNavigate();\n  const [searchParams, setSearchParams] = useSearchParams();\n\n  // Data for select options. These populate filter dropdowns only, so they're\n  // fetched lazily on first dropdown open instead of on page load — except when a\n  // users/tags filter is already active from the URL, where we need the options to\n  // render the selected label.\n  const [users, setUsers] = useState([]);\n  const [tags, setTags] = useState([]);\n  const [usersLoading, setUsersLoading] = useState(false);\n  const [tagsLoading, setTagsLoading] = useState(false);\n  const usersRequested = useRef(false);\n  const tagsRequested = useRef(false);\n\n  const ensureUsers = useCallback(async () => {\n    if (usersRequested.current) return;\n    usersRequested.current = true;\n    setUsersLoading(true);\n    try {\n      const data = await djClient.users();\n      setUsers(data || []);\n    } finally {\n      setUsersLoading(false);\n    }\n  }, [djClient]);\n\n  const ensureTags = useCallback(async () => {\n    if (tagsRequested.current) return;\n    tagsRequested.current = true;\n    setTagsLoading(true);\n    try {\n      const data = await djClient.listTags();\n      setTags(data || []);\n    } finally {\n      setTagsLoading(false);\n    }\n  }, [djClient]);\n\n  // Eagerly fetch only what an already-applied filter needs to render its label.\n  useEffect(() => {\n    if (searchParams.get('editedBy') || searchParams.get('ownedBy')) {\n      ensureUsers().catch(console.error);\n    }\n    if (searchParams.get('tags')) {\n      ensureTags().catch(console.error);\n    }\n  }, [searchParams, ensureUsers, ensureTags]);\n\n  // Parse all filters from URL\n  const getFiltersFromUrl = useCallback(\n    () => ({\n      node_type: searchParams.get('type') || '',\n      tags: searchParams.get('tags') ? searchParams.get('tags').split(',') : [],\n      edited_by: searchParams.get('editedBy') || '',\n      mode: searchParams.get('mode') || '',\n      ownedBy: searchParams.get('ownedBy') || '',\n      statuses: searchParams.get('statuses') || '',\n      missingDescription: searchParams.get('missingDescription') === 'true',\n      hasMaterialization: searchParams.get('hasMaterialization') === 'true',\n      orphanedDimension: searchParams.get('orphanedDimension') === 'true',\n    }),\n    [searchParams],\n  );\n\n  const [filters, setFilters] = useState(getFiltersFromUrl);\n  const [moreFiltersOpen, setMoreFiltersOpen] = useState(false);\n\n  // Sync filters state when the URL changes. `filters` is already seeded from the\n  // URL via useState, so we skip the initial run — otherwise it would replace\n  // filters with an equal-but-new object and trigger a redundant node refetch.\n  const didSyncFilters = useRef(false);\n  useEffect(() => {\n    if (!didSyncFilters.current) {\n      didSyncFilters.current = true;\n      return;\n    }\n    setFilters(getFiltersFromUrl());\n  }, [searchParams, getFiltersFromUrl]);\n\n  // Update URL when filters change\n  const updateFilters = useCallback(\n    newFilters => {\n      const params = new URLSearchParams();\n\n      if (newFilters.node_type) params.set('type', newFilters.node_type);\n      if (newFilters.tags?.length)\n        params.set('tags', newFilters.tags.join(','));\n      if (newFilters.edited_by) params.set('editedBy', newFilters.edited_by);\n      if (newFilters.mode) params.set('mode', newFilters.mode);\n      if (newFilters.ownedBy) params.set('ownedBy', newFilters.ownedBy);\n      if (newFilters.statuses) params.set('statuses', newFilters.statuses);\n      if (newFilters.missingDescription)\n        params.set('missingDescription', 'true');\n      if (newFilters.hasMaterialization)\n        params.set('hasMaterialization', 'true');\n      if (newFilters.orphanedDimension) params.set('orphanedDimension', 'true');\n\n      setSearchParams(params);\n    },\n    [setSearchParams],\n  );\n\n  const clearAllFilters = () => {\n    setSearchParams(new URLSearchParams());\n  };\n\n  // Check if any filters are active\n  const hasActiveFilters =\n    filters.node_type ||\n    filters.tags?.length ||\n    filters.edited_by ||\n    filters.mode ||\n    filters.ownedBy ||\n    filters.statuses ||\n    filters.missingDescription ||\n    filters.hasMaterialization ||\n    filters.orphanedDimension;\n\n  // Quick presets\n  const presets = [\n    {\n      id: 'my-nodes',\n      label: 'My Nodes',\n      filters: { ownedBy: currentUser?.username },\n    },\n    {\n      id: 'needs-attention',\n      label: 'Needs Attention',\n      filters: { ownedBy: currentUser?.username, statuses: 'INVALID' },\n    },\n    {\n      id: 'drafts',\n      label: 'Drafts',\n      filters: { ownedBy: currentUser?.username, mode: 'draft' },\n    },\n  ];\n\n  const applyPreset = preset => {\n    const newFilters = {\n      node_type: '',\n      tags: [],\n      edited_by: '',\n      mode: preset.filters.mode || '',\n      ownedBy: preset.filters.ownedBy || '',\n      statuses: preset.filters.statuses || '',\n      missingDescription: preset.filters.missingDescription || false,\n      hasMaterialization: preset.filters.hasMaterialization || false,\n      orphanedDimension: preset.filters.orphanedDimension || false,\n    };\n    updateFilters(newFilters);\n  };\n\n  // Check if a preset is active\n  const isPresetActive = preset => {\n    const pf = preset.filters;\n    return (\n      (pf.ownedBy || '') === (filters.ownedBy || '') &&\n      (pf.statuses || '') === (filters.statuses || '') &&\n      (pf.mode || '') === (filters.mode || '') &&\n      !filters.node_type &&\n      !filters.tags?.length &&\n      !filters.edited_by &&\n      !filters.missingDescription &&\n      !filters.hasMaterialization &&\n      !filters.orphanedDimension\n    );\n  };\n\n  const [state, setState] = useState({\n    namespace: namespace ? namespace : '',\n    nodes: [],\n  });\n  const [retrieved, setRetrieved] = useState(false);\n\n  const [namespaceHierarchy, setNamespaceHierarchy] = useState([]);\n  const [rawNamespaces, setRawNamespaces] = useState([]);\n  const [gitRoots, setGitRoots] = useState(new Set());\n  // Use undefined to indicate \"not yet loaded\", null means \"loaded but no config\"\n  const [gitConfig, setGitConfig] = useState(undefined);\n\n  const [sortConfig, setSortConfig] = useState({\n    key: 'updatedAt',\n    direction: DESC,\n  });\n\n  const [before, setBefore] = useState(null);\n  const [after, setAfter] = useState(null);\n  const [prevCursor, setPrevCursor] = useState(true);\n  const [nextCursor, setNextCursor] = useState(true);\n\n  const [hasNextPage, setHasNextPage] = useState(true);\n  const [hasPrevPage, setHasPrevPage] = useState(true);\n\n  const [nodeSearch, setNodeSearch] = useState('');\n  const [debouncedSearch, setDebouncedSearch] = useState('');\n  useEffect(() => {\n    const t = setTimeout(() => setDebouncedSearch(nodeSearch.trim()), 300);\n    return () => clearTimeout(t);\n  }, [nodeSearch]);\n  // Changing the search term restarts paging from the first page; a cursor from\n  // a previous page would otherwise be sent with the new query.\n  useEffect(() => {\n    setBefore(null);\n    setAfter(null);\n  }, [debouncedSearch]);\n\n  const [typeCounts, setTypeCounts] = useState(null);\n  // undefined until NamespaceHeader reports the read-only verdict, so Add Node stays hidden until known\n  const [headerReadOnly, setHeaderReadOnly] = useState(undefined);\n\n  // Only show edit/add controls once git config has loaded and namespace is not git-only\n  const gitConfigLoaded = gitConfig !== undefined;\n  // Descendants inherit github_repo_path via cascade, so compare against\n  // git_root_namespace to know if this namespace IS the git root.\n  const isGitRoot =\n    gitConfigLoaded &&\n    !!gitConfig?.github_repo_path &&\n    gitConfig?.git_root_namespace === namespace;\n  // Node-edit controls follow the single read-only verdict from NamespaceHeader\n  // (`headerReadOnly`), which correctly treats the default branch, 1:1/root git\n  // namespaces, git_only, and git-deployed non-feature content as read-only\n  // while leaving feature branches (and plain namespaces) editable. It's\n  // `undefined` until the header reports, so controls stay hidden until the\n  // verdict is known (no flash). Deriving a second, shape-based verdict here is\n  // what let the default branch (shape 'branch') wrongly show edit controls.\n  const showEditControls = headerReadOnly === false;\n  // Sub-namespaces can be created from the rail only for plain (non-git-backed)\n  // namespaces; git-backed ones are managed via git, not the UI. The git config\n  // endpoint returns an object with null fields (not null) for non-git\n  // namespaces, so check the actual git markers — a repo (root or cascaded\n  // descendant) or a branch namespace.\n  const isGitBacked = !!(\n    gitConfig?.github_repo_path || gitConfig?.branch_namespace\n  );\n  const canCreateNamespace = gitConfigLoaded && !isGitBacked;\n  const createSubNamespace = async fullNamespace => {\n    const response = await djClient.addNamespace(fullNamespace);\n    if (response.status === 200 || response.status === 201) {\n      // The cached namespace list is now stale — refetch it on next mount.\n      djClient.invalidateNamespacesCache?.();\n      navigate(`/namespaces/${fullNamespace}`);\n      return {};\n    }\n    return {\n      _error: true,\n      message: response.json?.message || 'Failed to create namespace',\n    };\n  };\n  // Distinguish a *child-spawning* git root (owns the repo, has no branch of its\n  // own — its nodes live on `<root>.<default_branch>`) from a *flat* git-backed\n  // namespace (has its own `git_branch`, e.g. tracks `main` directly, with no\n  // `<ns>.<branch>` children). Only the former is browsed via / redirected to its\n  // default branch; a flat namespace is its own branch and must stay put.\n  const isChildSpawningRoot = isGitRoot && !gitConfig?.git_branch;\n\n  // A child-spawning root has no nodes of its own — they live on its default\n  // branch — so the node table browses `<root>.<default_branch>`. A flat\n  // namespace browses itself.\n  const tableNamespace =\n    isChildSpawningRoot && gitConfig?.default_branch\n      ? `${namespace}.${gitConfig.default_branch}`\n      : namespace;\n\n  // A child-spawning root isn't a browsable branch — redirect to its default\n  // branch so the URL is the branch (giving the breadcrumb its branch switcher)\n  // and everything is scoped consistently. A flat git-backed namespace is NOT\n  // redirected: it *is* the branch, and `<ns>.<default_branch>` doesn't exist.\n  useEffect(() => {\n    if (isChildSpawningRoot && gitConfig?.default_branch) {\n      navigate(`/namespaces/${namespace}.${gitConfig.default_branch}`, {\n        replace: true,\n      });\n    }\n  }, [isChildSpawningRoot, gitConfig, namespace, navigate]);\n\n  // Per-type node counts (recursive) for the current namespace, shown inline in\n  // the TYPE filter options (e.g. \"Metric (342)\").\n  useEffect(() => {\n    // Wait until git config resolves so tableNamespace is final — otherwise a\n    // git root fetches its provisional namespace, then refetches after redirect.\n    if (!gitConfigLoaded) return;\n    if (isGitRoot && gitConfig?.default_branch) return;\n    let cancelled = false;\n    if (!tableNamespace) {\n      setTypeCounts(null);\n      return;\n    }\n    djClient\n      .nodeTypeCounts(tableNamespace, NODE_TYPE_ORDER)\n      .then(byType => {\n        if (!cancelled) setTypeCounts(byType);\n      })\n      .catch(() => {\n        if (!cancelled) setTypeCounts(null);\n      });\n    return () => {\n      cancelled = true;\n    };\n  }, [djClient, tableNamespace, gitConfigLoaded, isGitRoot, gitConfig]);\n\n  const requestSort = key => {\n    let direction = ASC;\n    if (sortConfig.key === key && sortConfig.direction === ASC) {\n      direction = DESC;\n    }\n    if (sortConfig.key !== key || sortConfig.direction !== direction) {\n      setSortConfig({ key, direction });\n    }\n  };\n\n  const getClassNamesFor = name => {\n    if (sortConfig.key === name) {\n      return sortConfig.direction;\n    }\n    return undefined;\n  };\n\n  const createNamespaceHierarchy = namespaceList => {\n    const hierarchy = [];\n    // Map lookups (path -> node's children map) keep insertion O(n · depth); we sort\n    // each level once at the end rather than on every insert (which was O(n² log n)).\n    const rootMap = new Map();\n    const childMaps = new Map();\n\n    for (const item of namespaceList) {\n      const segments = item.namespace.split('.');\n      let currentLevel = hierarchy;\n      let levelMap = rootMap;\n      let path = '';\n      for (const ns of segments) {\n        path += ns;\n        let node = levelMap.get(ns);\n        if (!node) {\n          node = { namespace: ns, children: [], path };\n          currentLevel.push(node);\n          levelMap.set(ns, node);\n          childMaps.set(path, new Map());\n        }\n        currentLevel = node.children;\n        levelMap = childMaps.get(path);\n        path += '.';\n      }\n    }\n\n    const sortLevel = level => {\n      level.sort((a, b) => a.namespace.localeCompare(b.namespace));\n      level.forEach(node => sortLevel(node.children));\n    };\n    sortLevel(hierarchy);\n    return hierarchy;\n  };\n\n  useEffect(() => {\n    const fetchData = async () => {\n      const all = await djClient.listNamespacesWithGit();\n      // Hide system/internal scratch namespaces from all browse navigation\n      // (rail list, header switcher, folders).\n      const namespaces = all.filter(ns => !isHiddenNamespace(ns.namespace));\n      setRawNamespaces(namespaces);\n      const hierarchy = createNamespaceHierarchy(namespaces);\n      setNamespaceHierarchy(hierarchy);\n\n      const roots = new Set(\n        namespaces\n          .filter(ns => ns.git?.__typename === 'GitRootConfig')\n          .map(ns => ns.namespace),\n      );\n      setGitRoots(roots);\n    };\n    fetchData().catch(console.error);\n  }, [djClient]);\n\n  useEffect(() => {\n    // Wait until git config resolves so tableNamespace is final — otherwise a\n    // git root fetches its provisional namespace, then refetches after redirect.\n    if (!gitConfigLoaded) return;\n    if (isGitRoot && gitConfig?.default_branch) return;\n    const fetchData = async () => {\n      setRetrieved(false);\n\n      // Build extended filters for API\n      const extendedFilters = {\n        ownedBy: filters.ownedBy || null,\n        statuses: filters.statuses ? [filters.statuses] : null,\n        missingDescription: filters.missingDescription,\n        hasMaterialization: filters.hasMaterialization,\n        orphanedDimension: filters.orphanedDimension,\n        // The table shows every node under this namespace (all descendants),\n        // matching the rail's per-type counts. The rail's Folders drill DOWN to\n        // re-scope; search narrows within the current scope.\n        search: debouncedSearch || null,\n      };\n\n      const nodes = await djClient.listNodesForLanding(\n        tableNamespace,\n        filters.node_type ? [filters.node_type.toUpperCase()] : [],\n        filters.tags,\n        filters.edited_by,\n        before,\n        after,\n        50,\n        sortConfig,\n        filters.mode ? filters.mode.toUpperCase() : null,\n        extendedFilters,\n      );\n\n      setState({\n        namespace: namespace,\n        nodes: nodes.data\n          ? nodes.data.findNodesPaginated.edges.map(n => n.node)\n          : [],\n      });\n      if (nodes.data) {\n        setPrevCursor(\n          nodes.data ? nodes.data.findNodesPaginated.pageInfo.startCursor : '',\n        );\n        setNextCursor(\n          nodes.data ? nodes.data.findNodesPaginated.pageInfo.endCursor : '',\n        );\n        setHasPrevPage(\n          nodes.data\n            ? nodes.data.findNodesPaginated.pageInfo.hasPrevPage\n            : false,\n        );\n        setHasNextPage(\n          nodes.data\n            ? nodes.data.findNodesPaginated.pageInfo.hasNextPage\n            : false,\n        );\n      }\n      setRetrieved(true);\n    };\n    fetchData().catch(console.error);\n  }, [\n    djClient,\n    filters,\n    before,\n    after,\n    sortConfig.key,\n    sortConfig.direction,\n    tableNamespace,\n    namespace,\n    debouncedSearch,\n    gitConfigLoaded,\n    isGitRoot,\n    gitConfig,\n  ]);\n\n  const loadNext = () => {\n    if (nextCursor) {\n      setAfter(nextCursor);\n      setBefore(null);\n    }\n  };\n  const loadPrev = () => {\n    if (prevCursor) {\n      setAfter(null);\n      setBefore(prevCursor);\n    }\n  };\n\n  // Select options. TYPE options carry the recursive per-type node count for the\n  // current namespace (e.g. \"Metric (342)\") — this replaces the old rail counts.\n  const TYPE_LABELS = {\n    metric: 'Metric',\n    cube: 'Cube',\n    dimension: 'Dimension',\n    transform: 'Transform',\n    source: 'Source',\n  };\n  const typeOptions = NODE_TYPE_ORDER.map(type => ({\n    value: type,\n    label: TYPE_LABELS[type],\n    count: typeCounts?.[type] ?? null,\n  }));\n\n  // Renders a TYPE option as \"<name> <colored count pill>\" (pill colors match the\n  // node-type badges). Right-aligns the pill in the menu; inline in the control.\n  const formatTypeOption = (option, meta) => {\n    const pill =\n      option.count != null ? (\n        <span\n          style={{\n            backgroundColor: NODE_TYPE_COLORS[option.value]?.bg ?? '#f1f5f9',\n            color: NODE_TYPE_COLORS[option.value]?.color ?? '#475569',\n            borderRadius: '8px',\n            padding: '1px 8px',\n            fontSize: '11px',\n            fontWeight: 600,\n            fontVariantNumeric: 'tabular-nums',\n          }}\n        >\n          {option.count}\n        </span>\n      ) : null;\n    return (\n      <span\n        style={{\n          display: 'flex',\n          alignItems: 'center',\n          gap: '8px',\n          justifyContent:\n            meta?.context === 'menu' ? 'space-between' : 'flex-start',\n          width: meta?.context === 'menu' ? '100%' : 'auto',\n        }}\n      >\n        <span>{option.label}</span>\n        {pill}\n      </span>\n    );\n  };\n\n  const modeOptions = [\n    { value: 'published', label: 'Published' },\n    { value: 'draft', label: 'Draft' },\n  ];\n\n  const statusOptions = [\n    { value: 'VALID', label: 'Valid' },\n    { value: 'INVALID', label: 'Needs fixes' },\n  ];\n\n  const userOptions = useMemo(\n    () => users.map(u => ({ value: u.username, label: u.username })),\n    [users],\n  );\n  const tagOptions = useMemo(\n    () => tags.map(t => ({ value: t.name, label: t.display_name })),\n    [tags],\n  );\n\n  const nodesList = retrieved ? (\n    state.nodes.length > 0 ? (\n      state.nodes.map(node => {\n        const { leafName, namespacePath } = splitNodeName(node.name);\n        const stateInfo = nodeState(node.current);\n        const owners = node.owners || [];\n        return (\n          <tr\n            key={node.name}\n            style={{\n              backgroundColor: stateInfo.needsAttention ? '#fffbeb' : undefined,\n            }}\n          >\n            <td\n              style={{\n                ...CELL_STYLE,\n                maxWidth: '300px',\n                overflow: 'hidden',\n                whiteSpace: 'nowrap',\n                textOverflow: 'ellipsis',\n              }}\n            >\n              <div>\n                <a\n                  href={'/nodes/' + node.name}\n                  className=\"link-table\"\n                  title={node.name}\n                  style={{ fontWeight: 600, color: '#334155' }}\n                >\n                  {leafName}\n                </a>\n                <span\n                  className=\"rounded-pill badge bg-secondary-soft\"\n                  style={{ marginLeft: '0.5rem' }}\n                >\n                  {node.currentVersion}\n                </span>\n              </div>\n              {namespacePath ? (\n                <div\n                  title={namespacePath}\n                  style={{\n                    color: '#64748b',\n                    fontSize: '12px',\n                    marginTop: '2px',\n                    overflow: 'hidden',\n                    textOverflow: 'ellipsis',\n                  }}\n                >\n                  {namespacePath}\n                </div>\n              ) : null}\n            </td>\n            <td\n              style={{\n                ...MIDDLE_CELL_STYLE,\n                maxWidth: '250px',\n                overflow: 'hidden',\n                whiteSpace: 'nowrap',\n                textOverflow: 'ellipsis',\n                color: '#64748b',\n              }}\n            >\n              <a\n                href={'/nodes/' + node.name}\n                className=\"link-table\"\n                style={{ color: '#475569', fontWeight: 400 }}\n              >\n                {node.type !== 'source' ? node.current.displayName : ''}\n              </a>\n            </td>\n            <td style={MIDDLE_CELL_STYLE}>\n              <Tooltip content={NODE_TYPE_DESCRIPTIONS[node.type]}>\n                <span\n                  className={\n                    'node_type__' + node.type.toLowerCase() + ' badge node_type'\n                  }\n                >\n                  {node.type}\n                </span>\n              </Tooltip>\n            </td>\n            <td style={MIDDLE_CELL_STYLE}>\n              <Tooltip content={stateInfo.validationTooltip}>\n                <span\n                  style={{\n                    display: 'inline-flex',\n                    alignItems: 'center',\n                    borderRadius: '999px',\n                    border: `1px solid ${\n                      stateInfo.isValid ? '#28a745' : '#d39e00'\n                    }`,\n                    backgroundColor: stateInfo.isValid ? '#eaf7ee' : '#fff7df',\n                    color: stateInfo.isValid ? '#1f7a3a' : '#8a5b00',\n                    fontWeight: '600',\n                    fontSize: '12px',\n                    lineHeight: 1.2,\n                    padding: '6px 10px',\n                    whiteSpace: 'nowrap',\n                  }}\n                >\n                  {stateInfo.validationLabel}\n                </span>\n              </Tooltip>\n            </td>\n            <td style={MIDDLE_CELL_STYLE}>\n              <Tooltip content={stateInfo.publishTooltip}>\n                <span\n                  style={{\n                    display: 'inline-flex',\n                    alignItems: 'center',\n                    borderRadius: '999px',\n                    border: `1px solid ${\n                      stateInfo.isPublished ? '#28a745' : '#d39e00'\n                    }`,\n                    backgroundColor: stateInfo.isPublished\n                      ? '#eaf7ee'\n                      : '#fff7df',\n                    color: stateInfo.isPublished ? '#1f7a3a' : '#8a5b00',\n                    fontWeight: '600',\n                    fontSize: '12px',\n                    lineHeight: 1.2,\n                    padding: '6px 10px',\n                    whiteSpace: 'nowrap',\n                  }}\n                >\n                  {stateInfo.publishLabel}\n                </span>\n              </Tooltip>\n            </td>\n            <td style={MIDDLE_CELL_STYLE}>\n              {owners.length > 0 && (\n                <div style={{ display: 'flex', gap: '2px' }}>\n                  {owners.slice(0, 3).map(owner => {\n                    const initials = owner.username\n                      .split('@')[0]\n                      .slice(0, 2)\n                      .toUpperCase();\n                    const [bg, fg] =\n                      AVATAR_COLORS[avatarColorIndex(owner.username)];\n                    return (\n                      <span\n                        key={owner.username}\n                        title={owner.username}\n                        style={{\n                          display: 'inline-flex',\n                          alignItems: 'center',\n                          justifyContent: 'center',\n                          width: '24px',\n                          height: '24px',\n                          borderRadius: '50%',\n                          backgroundColor: bg,\n                          color: fg,\n                          fontSize: '9px',\n                          fontWeight: '600',\n                          flexShrink: 0,\n                        }}\n                      >\n                        {initials}\n                      </span>\n                    );\n                  })}\n                </div>\n              )}\n            </td>\n            <td style={MIDDLE_CELL_STYLE}>\n              <Tooltip content={exactDateTime(node.current.updatedAt)}>\n                <span className=\"status\">\n                  {relativeDate(node.current.updatedAt)}\n                </span>\n              </Tooltip>\n            </td>\n            {showEditControls && (\n              <td style={MIDDLE_CELL_STYLE}>\n                <NodeListActions nodeName={node?.name} />\n              </td>\n            )}\n          </tr>\n        );\n      })\n    ) : (\n      <tr>\n        <td colSpan={fields.length + (showEditControls ? 1 : 0)}>\n          <span\n            style={{\n              display: 'block',\n              marginTop: '2rem',\n              marginLeft: '2rem',\n              fontSize: '16px',\n            }}\n          >\n            {hasActiveFilters ? (\n              <>\n                No nodes match the current filters.\n                <a\n                  href=\"#\"\n                  onClick={e => {\n                    e.preventDefault();\n                    clearAllFilters();\n                  }}\n                  style={{ marginLeft: '0.5rem' }}\n                >\n                  Clear filters\n                </a>\n              </>\n            ) : (\n              'No nodes in this namespace yet.'\n            )}\n          </span>\n        </td>\n      </tr>\n    )\n  ) : (\n    <tr>\n      <td>\n        <span style={{ display: 'block', marginTop: '2rem' }}>\n          <LoadingIcon />\n        </span>\n      </td>\n    </tr>\n  );\n\n  // Count active filters tucked behind \"More filters\".\n  const moreFiltersCount = [\n    !!filters.edited_by,\n    filters.missingDescription,\n    filters.hasMaterialization,\n    filters.orphanedDimension,\n  ].filter(Boolean).length;\n\n  return (\n    <div className=\"mid\">\n      <div className=\"card\">\n        <div className=\"card-header\">\n          <div\n            style={{\n              display: 'flex',\n              justifyContent: 'space-between',\n              alignItems: 'center',\n              marginBottom: '1rem',\n            }}\n          >\n            <h2 style={{ margin: 0 }}>Browse</h2>\n          </div>\n\n          {/* Unified Filter Bar — always shown; a git root browses its default branch */}\n          {gitConfigLoaded && (\n            <div\n              style={{\n                marginBottom: '1rem',\n                padding: '1rem',\n                backgroundColor: '#f8fafc',\n                borderRadius: '8px',\n              }}\n            >\n              {/* Top row: Quick presets + Clear all */}\n              <div\n                style={{\n                  display: 'flex',\n                  alignItems: 'center',\n                  gap: '12px',\n                  marginBottom: '12px',\n                }}\n              >\n                <div\n                  style={{ display: 'flex', alignItems: 'center', gap: '6px' }}\n                >\n                  <span\n                    style={{\n                      fontSize: '11px',\n                      fontWeight: '600',\n                      textTransform: 'uppercase',\n                      letterSpacing: '0.5px',\n                      color: '#64748b',\n                    }}\n                  >\n                    Quick\n                  </span>\n                  {presets.map(preset => (\n                    <button\n                      key={preset.id}\n                      onClick={() => applyPreset(preset)}\n                      style={{\n                        padding: '4px 10px',\n                        fontSize: '11px',\n                        border: '1px solid',\n                        borderColor: isPresetActive(preset)\n                          ? '#1976d2'\n                          : '#ddd',\n                        borderRadius: '12px',\n                        backgroundColor: isPresetActive(preset)\n                          ? '#e3f2fd'\n                          : 'white',\n                        color: isPresetActive(preset) ? '#1976d2' : '#666',\n                        cursor: 'pointer',\n                        fontWeight: isPresetActive(preset) ? '600' : '400',\n                      }}\n                    >\n                      {preset.label}\n                    </button>\n                  ))}\n                  {hasActiveFilters && (\n                    <button\n                      onClick={clearAllFilters}\n                      style={{\n                        padding: '4px 10px',\n                        fontSize: '11px',\n                        border: 'none',\n                        backgroundColor: 'transparent',\n                        color: '#dc3545',\n                        cursor: 'pointer',\n                      }}\n                    >\n                      Clear all ×\n                    </button>\n                  )}\n                </div>\n              </div>\n\n              {/* Bottom row: Dropdowns */}\n              <div\n                style={{\n                  display: 'flex',\n                  alignItems: 'flex-end',\n                  gap: '12px',\n                }}\n              >\n                <CompactSelect\n                  label=\"Type\"\n                  name=\"type\"\n                  options={typeOptions}\n                  value={filters.node_type}\n                  onChange={e =>\n                    updateFilters({ ...filters, node_type: e?.value || '' })\n                  }\n                  formatOptionLabel={formatTypeOption}\n                  flex={1}\n                  minWidth=\"80px\"\n                  testId=\"select-node-type\"\n                />\n                <CompactSelect\n                  label=\"Owner\"\n                  name=\"owner\"\n                  options={userOptions}\n                  value={filters.ownedBy}\n                  onChange={e =>\n                    updateFilters({ ...filters, ownedBy: e?.value || '' })\n                  }\n                  isLoading={usersLoading}\n                  onMenuOpen={ensureUsers}\n                  flex={1}\n                  minWidth=\"80px\"\n                />\n                <CompactSelect\n                  label=\"Tags\"\n                  name=\"tags\"\n                  options={tagOptions}\n                  value={filters.tags}\n                  onChange={e =>\n                    updateFilters({\n                      ...filters,\n                      tags: e ? e.map(t => t.value) : [],\n                    })\n                  }\n                  isMulti\n                  isLoading={tagsLoading}\n                  onMenuOpen={ensureTags}\n                  flex={1.2}\n                  minWidth=\"100px\"\n                  testId=\"select-tag\"\n                />\n                <SplitFilter\n                  label=\"Publish state\"\n                  options={modeOptions}\n                  value={filters.mode}\n                  onChange={value => updateFilters({ ...filters, mode: value })}\n                />\n                <SplitFilter\n                  label=\"Validation\"\n                  options={statusOptions}\n                  value={filters.statuses}\n                  onChange={value =>\n                    updateFilters({ ...filters, statuses: value })\n                  }\n                />\n\n                {/* More Filters */}\n                <div\n                  style={{ position: 'relative', flex: 0, minWidth: 'auto' }}\n                >\n                  <div\n                    style={{\n                      display: 'flex',\n                      flexDirection: 'column',\n                      gap: '2px',\n                    }}\n                  >\n                    <label\n                      style={{\n                        fontSize: '10px',\n                        fontWeight: '600',\n                        color: '#666',\n                        textTransform: 'uppercase',\n                        letterSpacing: '0.5px',\n                      }}\n                    >\n                      More filters\n                    </label>\n                    <button\n                      onClick={() => setMoreFiltersOpen(!moreFiltersOpen)}\n                      style={{\n                        height: '32px',\n                        minHeight: '32px',\n                        padding: '0 12px',\n                        fontSize: '12px',\n                        border: '1px solid #ccc',\n                        borderRadius: '4px',\n                        backgroundColor:\n                          moreFiltersCount > 0 ? '#e3f2fd' : 'white',\n                        color: '#666',\n                        cursor: 'pointer',\n                        display: 'flex',\n                        alignItems: 'center',\n                        gap: '4px',\n                        whiteSpace: 'nowrap',\n                      }}\n                    >\n                      {moreFiltersCount > 0\n                        ? `${moreFiltersCount} active`\n                        : 'Filters'}\n                      <span style={{ fontSize: '8px' }}>\n                        {moreFiltersOpen ? '▲' : '▼'}\n                      </span>\n                    </button>\n                  </div>\n\n                  {moreFiltersOpen && (\n                    <div\n                      style={{\n                        position: 'absolute',\n                        top: '100%',\n                        right: 0,\n                        marginTop: '4px',\n                        padding: '12px',\n                        backgroundColor: 'white',\n                        border: '1px solid #ddd',\n                        borderRadius: '8px',\n                        boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n                        zIndex: 1000,\n                        minWidth: '320px',\n                      }}\n                    >\n                      <div\n                        style={{\n                          display: 'grid',\n                          gap: '12px',\n                          marginBottom: '12px',\n                        }}\n                      >\n                        <CompactSelect\n                          label=\"Edited By\"\n                          name=\"editedBy\"\n                          options={userOptions}\n                          value={filters.edited_by}\n                          onChange={e =>\n                            updateFilters({\n                              ...filters,\n                              edited_by: e?.value || '',\n                            })\n                          }\n                          isLoading={usersLoading}\n                          onMenuOpen={ensureUsers}\n                          flex=\"none\"\n                          minWidth=\"100%\"\n                          testId=\"select-user\"\n                        />\n                      </div>\n                      <div\n                        style={{\n                          borderTop: '1px solid #e2e8f0',\n                          paddingTop: '12px',\n                        }}\n                      >\n                        <label\n                          style={{\n                            display: 'flex',\n                            alignItems: 'center',\n                            gap: '8px',\n                            fontSize: '12px',\n                            color: '#444',\n                            marginBottom: '8px',\n                            cursor: 'pointer',\n                          }}\n                        >\n                          <input\n                            type=\"checkbox\"\n                            checked={filters.missingDescription}\n                            onChange={e =>\n                              updateFilters({\n                                ...filters,\n                                missingDescription: e.target.checked,\n                              })\n                            }\n                          />\n                          Missing Description\n                        </label>\n                        <label\n                          style={{\n                            display: 'flex',\n                            alignItems: 'center',\n                            gap: '8px',\n                            fontSize: '12px',\n                            color: '#444',\n                            marginBottom: '8px',\n                            cursor: 'pointer',\n                          }}\n                        >\n                          <input\n                            type=\"checkbox\"\n                            checked={filters.orphanedDimension}\n                            onChange={e =>\n                              updateFilters({\n                                ...filters,\n                                orphanedDimension: e.target.checked,\n                              })\n                            }\n                          />\n                          Orphaned Dimensions\n                        </label>\n                        <label\n                          style={{\n                            display: 'flex',\n                            alignItems: 'center',\n                            gap: '8px',\n                            fontSize: '12px',\n                            color: '#444',\n                            cursor: 'pointer',\n                          }}\n                        >\n                          <input\n                            type=\"checkbox\"\n                            checked={filters.hasMaterialization}\n                            onChange={e =>\n                              updateFilters({\n                                ...filters,\n                                hasMaterialization: e.target.checked,\n                              })\n                            }\n                          />\n                          Has Materialization\n                        </label>\n                      </div>\n                    </div>\n                  )}\n                </div>\n              </div>\n            </div>\n          )}\n\n          <NamespaceHeader\n            namespace={namespace}\n            onGitConfigLoaded={setGitConfig}\n            onReadOnlyChange={setHeaderReadOnly}\n            namespaceOptions={rawNamespaces}\n            currentNamespace={namespace}\n          >\n            {namespace && (\n              <Tooltip\n                content={`Download every node in \"${namespace}\" as a YAML project (.zip) you can version in git and re-deploy with the DJ client.`}\n              >\n                <button\n                  type=\"button\"\n                  onClick={async () => {\n                    const response = await fetch(\n                      `${getDJUrl()}/namespaces/${namespace}/export/yaml`,\n                      { method: 'POST', credentials: 'include' },\n                    );\n                    if (!response.ok) {\n                      return;\n                    }\n                    const blob = await response.blob();\n                    const url = URL.createObjectURL(blob);\n                    const link = document.createElement('a');\n                    const safeName = namespace.replace(/\\./g, '_');\n                    link.href = url;\n                    link.download = `${safeName}_export.zip`;\n                    document.body.appendChild(link);\n                    link.click();\n                    document.body.removeChild(link);\n                    URL.revokeObjectURL(url);\n                  }}\n                  style={secondaryButtonStyle}\n                  onMouseOver={onSecondaryHover}\n                  onMouseOut={onSecondaryOut}\n                  aria-label=\"Export namespace to YAML\"\n                >\n                  <svg\n                    width=\"14\"\n                    height=\"14\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    strokeWidth=\"2\"\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                  >\n                    <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n                    <polyline points=\"7 10 12 15 17 10\"></polyline>\n                    <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"></line>\n                  </svg>\n                  Export YAML\n                </button>\n              </Tooltip>\n            )}\n            {showEditControls && <AddNodeDropdown namespace={namespace} />}\n          </NamespaceHeader>\n\n          <div className=\"table-responsive\">\n            {/* The rail is always present for layout consistency, even on a leaf\n                namespace with no sub-namespaces (where its Folders list is empty). */}\n            <div\n              className=\"sidebar\"\n              style={{\n                borderRight: '1px solid #e2e8f0',\n                paddingRight: '1rem',\n              }}\n            >\n              <NamespaceNav\n                namespaces={rawNamespaces}\n                hierarchy={namespaceHierarchy}\n                currentNamespace={namespace}\n                gitRoots={gitRoots}\n                onSelect={value =>\n                  navigate(value ? `/namespaces/${value}` : '/')\n                }\n                canCreateNamespace={canCreateNamespace}\n                onCreateNamespace={createSubNamespace}\n              />\n            </div>\n            <div\n              style={{\n                flex: 1,\n                minWidth: 0,\n                marginLeft: '1.5rem',\n              }}\n            >\n              {gitConfigLoaded && (\n                <input\n                  type=\"text\"\n                  className=\"dj-node-search\"\n                  value={nodeSearch}\n                  onChange={e => setNodeSearch(e.target.value)}\n                  placeholder=\"Search nodes in this namespace…\"\n                  aria-label=\"Search nodes in this namespace\"\n                />\n              )}\n\n              {/* NODES: nodes that live directly in this namespace */}\n              {!gitConfigLoaded ? null : (\n                <table className=\"card-table table\" style={{ marginBottom: 0 }}>\n                  <thead>\n                    <tr>\n                      {fields.map(field => {\n                        const fieldConfig = FIELD_CONFIG[field] || {};\n                        const sortable = fieldConfig.sortable !== false;\n                        const thStyle = {\n                          fontFamily:\n                            \"'Inter', -apple-system, BlinkMacSystemFont, sans-serif\",\n                          fontSize: '11px',\n                          fontWeight: '600',\n                          textTransform: 'uppercase',\n                          letterSpacing: '0.5px',\n                          color: '#64748b',\n                          padding: '12px 16px',\n                          borderBottom: '1px solid #e2e8f0',\n                          backgroundColor: 'transparent',\n                        };\n                        return (\n                          <th key={field} style={thStyle}>\n                            <Tooltip\n                              content={fieldConfig.tooltip}\n                              placement=\"top\"\n                            >\n                              {sortable ? (\n                                <button\n                                  type=\"button\"\n                                  onClick={() => requestSort(field)}\n                                  className={\n                                    'sortable ' + getClassNamesFor(field)\n                                  }\n                                  style={{\n                                    fontSize: 'inherit',\n                                    fontWeight: 'inherit',\n                                    letterSpacing: 'inherit',\n                                    textTransform: 'inherit',\n                                    fontFamily: 'inherit',\n                                  }}\n                                >\n                                  {fieldConfig.label ||\n                                    field.replace(/([a-z](?=[A-Z]))/g, '$1 ')}\n                                </button>\n                              ) : (\n                                <span>\n                                  {fieldConfig.label ||\n                                    field.replace(/([a-z](?=[A-Z]))/g, '$1 ')}\n                                </span>\n                              )}\n                            </Tooltip>\n                          </th>\n                        );\n                      })}\n                      {showEditControls && (\n                        <th\n                          style={{\n                            fontFamily:\n                              \"'Inter', -apple-system, BlinkMacSystemFont, sans-serif\",\n                            fontSize: '11px',\n                            fontWeight: '600',\n                            textTransform: 'uppercase',\n                            letterSpacing: '0.5px',\n                            color: '#64748b',\n                            padding: '12px 16px',\n                            borderBottom: '1px solid #e2e8f0',\n                            backgroundColor: 'transparent',\n                          }}\n                        >\n                          Actions\n                        </th>\n                      )}\n                    </tr>\n                  </thead>\n                  <tbody className=\"nodes-table-body\">{nodesList}</tbody>\n                  <tfoot>\n                    <tr>\n                      <td>\n                        {retrieved && hasPrevPage ? (\n                          <a\n                            onClick={loadPrev}\n                            className=\"previous round pagination\"\n                          >\n                            ← Previous\n                          </a>\n                        ) : (\n                          ''\n                        )}\n                        {retrieved && hasNextPage ? (\n                          <a\n                            onClick={loadNext}\n                            className=\"next round pagination\"\n                          >\n                            Next →\n                          </a>\n                        ) : (\n                          ''\n                        )}\n                      </td>\n                    </tr>\n                  </tfoot>\n                </table>\n              )}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"],"names":["PERSONAL_NS_PREFIX","resolvePersonalNamespace","namespace","username","handle","AddNodeDropdown","djClient","useContext","DJClientContext","currentUser","useCurrentUser","navigate","useNavigate","ns","isPersonalFallback","goTo","path","e","err","jsx","jsxs","MAX_RENDERED_OPTIONS","WindowedMenuList","props","children","components","CompactSelect","label","name","options","value","onChange","isMulti","isClearable","placeholder","minWidth","flex","isLoading","testId","formatOptionLabel","onMenuOpen","selectedValue","o","Select","base","ChevronIcon","open","size","PINNED_KEY","read","key","v","x","write","list","getPinned","togglePinned","cur","next","FolderTreeRows","nodes","depth","expanded","onToggle","onSelect","node","hasChildren","_a","isOpen","React","FolderTree","folders","setExpanded","useState","prev","NewSubNamespace","parent","onCreate","adding","setAdding","setName","error","setError","segment","reset","submit","res","gitContext","gitByNs","g","NamespaceNav","namespaces","hierarchy","currentNamespace","gitRoots","canCreateNamespace","onCreateNamespace","collapsed","setCollapsed","pinned","setPinned","filter","setFilter","isFiltering","matches","searchNamespaces","showList","groups","buildNamespaceOptions","pinnedSet","toggleGroup","c","onPin","renderRow","keyPrefix","renderGroup","names","ctx","subtreePath","Fragment","group","immediateChildren","NODE_TYPE_ORDER","NODE_TYPE_COLORS","AVATAR_COLORS","avatarColorIndex","hash","i","FIELD_CONFIG","CELL_STYLE","MIDDLE_CELL_STYLE","NODE_TYPE_DESCRIPTIONS","splitNodeName","nodeName","lastDot","nodeState","current","isPublished","isValid","exactDateTime","relativeDate","updatedAt","diffMs","absMs","units","unit","ms","valueForUnit","NamespacePage","ASC","DESC","fields","useParams","searchParams","setSearchParams","useSearchParams","users","setUsers","tags","setTags","usersLoading","setUsersLoading","tagsLoading","setTagsLoading","usersRequested","useRef","tagsRequested","ensureUsers","useCallback","data","ensureTags","useEffect","getFiltersFromUrl","filters","setFilters","moreFiltersOpen","setMoreFiltersOpen","didSyncFilters","updateFilters","newFilters","params","clearAllFilters","hasActiveFilters","presets","applyPreset","preset","isPresetActive","pf","state","setState","retrieved","setRetrieved","namespaceHierarchy","setNamespaceHierarchy","rawNamespaces","setRawNamespaces","setGitRoots","gitConfig","setGitConfig","sortConfig","setSortConfig","before","setBefore","after","setAfter","prevCursor","setPrevCursor","nextCursor","setNextCursor","hasNextPage","setHasNextPage","hasPrevPage","setHasPrevPage","nodeSearch","setNodeSearch","debouncedSearch","setDebouncedSearch","typeCounts","setTypeCounts","headerReadOnly","setHeaderReadOnly","gitConfigLoaded","isGitRoot","showEditControls","isGitBacked","createSubNamespace","fullNamespace","response","_b","isChildSpawningRoot","tableNamespace","cancelled","byType","requestSort","direction","getClassNamesFor","createNamespaceHierarchy","namespaceList","rootMap","childMaps","item","segments","currentLevel","levelMap","sortLevel","level","a","b","isHiddenNamespace","roots","extendedFilters","n","loadNext","loadPrev","TYPE_LABELS","typeOptions","type","formatTypeOption","option","meta","pill","modeOptions","statusOptions","userOptions","useMemo","u","tagOptions","nodesList","leafName","namespacePath","stateInfo","owners","Tooltip","owner","initials","bg","fg","NodeListActions","LoadingIcon","moreFiltersCount","t","SplitFilter","NamespaceHeader","getDJUrl","blob","url","link","safeName","secondaryButtonStyle","onSecondaryHover","onSecondaryOut","field","fieldConfig","sortable","thStyle"],"mappings":"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"}