{"$schema":"https:\/\/ui.particle.academy\/schema\/registry-item.json","name":"kanban","type":"registry:ui","title":"Kanban","description":"Kanban from react-fancy","package":"react-fancy","dependencies":[],"registryDependencies":[],"files":[{"path":"components\/fancy\/kanban\/Kanban.context.ts","content":"import { createContext, useContext } from \"react\";\r\nimport type { KanbanContextValue } from \".\/Kanban.types\";\r\n\r\nexport const KanbanContext = createContext<KanbanContextValue | null>(null);\r\n\r\nexport function useKanban(): KanbanContextValue {\r\n  const ctx = useContext(KanbanContext);\r\n  if (!ctx) {\r\n    throw new Error(\"Kanban compound components must be used within <Kanban>\");\r\n  }\r\n  return ctx;\r\n}\r\n\r\nexport const KanbanColumnContext = createContext<string>(\"\");\r\n\r\nexport function useKanbanColumn(): string {\r\n  return useContext(KanbanColumnContext);\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/Kanban.context.ts"},{"path":"components\/fancy\/kanban\/Kanban.tsx","content":"import { useCallback, useMemo, useRef, useState } from \"react\";\r\nimport { cn } from \"..\/..\/utils\/cn\";\r\nimport { KanbanContext } from \".\/Kanban.context\";\r\nimport { KanbanColumn } from \".\/KanbanColumn\";\r\nimport { KanbanCard } from \".\/KanbanCard\";\r\nimport { KanbanColumnHandle } from \".\/KanbanColumnHandle\";\r\nimport type { KanbanProps } from \".\/Kanban.types\";\r\n\r\n\/**\r\n * Kanban board.\r\n *\r\n * Compound:\r\n *   <Kanban onCardMove={...} onColumnMove={...}>\r\n *     <Kanban.Column id=\"todo\" wipLimit={4}>\r\n *       <Kanban.ColumnHandle>...header...<\/Kanban.ColumnHandle>  \/\/ optional\r\n *       <Kanban.Card id=\"...\">...<\/Kanban.Card>\r\n *     <\/Kanban.Column>\r\n *   <\/Kanban>\r\n *\r\n * Cards drag between columns AND within a column. Drop position is\r\n * computed from mouse Y at hover time and surfaced via the `toIndex`\r\n * argument on `onCardMove`.\r\n *\r\n * Columns drag horizontally to reorder when a `<Kanban.ColumnHandle>`\r\n * is mounted inside them. The root computes the drop index from\r\n * mouse X and surfaces it via `onColumnMove`.\r\n *\/\r\nfunction KanbanRoot({\r\n  children,\r\n  onCardMove,\r\n  onColumnMove,\r\n  className,\r\n}: KanbanProps) {\r\n  const [draggedCard, setDraggedCard] = useState<string | null>(null);\r\n  const [dragSource, setDragSource] = useState<string | null>(null);\r\n  const [draggedColumn, setDraggedColumn] = useState<string | null>(null);\r\n\r\n  const orderRef = useRef<string[]>([]);\r\n  const [columnIds, setColumnIds] = useState<string[]>([]);\r\n\r\n  const registerColumn = useCallback((id: string) => {\r\n    if (!orderRef.current.includes(id)) {\r\n      orderRef.current = [...orderRef.current, id];\r\n      setColumnIds(orderRef.current);\r\n    }\r\n    return () => {\r\n      orderRef.current = orderRef.current.filter((x) => x !== id);\r\n      setColumnIds(orderRef.current);\r\n    };\r\n  }, []);\r\n\r\n  const ctx = useMemo(\r\n    () => ({\r\n      draggedCard,\r\n      setDraggedCard,\r\n      dragSource,\r\n      setDragSource,\r\n      draggedColumn,\r\n      setDraggedColumn,\r\n      onCardMove,\r\n      onColumnMove,\r\n      columnIds,\r\n      registerColumn,\r\n    }),\r\n    [\r\n      draggedCard,\r\n      dragSource,\r\n      draggedColumn,\r\n      onCardMove,\r\n      onColumnMove,\r\n      columnIds,\r\n      registerColumn,\r\n    ],\r\n  );\r\n\r\n  \/\/ \u2500\u2500 Column-level drop handling \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  \/\/ Root listens only when a column is being dragged. Drop index is\r\n  \/\/ computed from mouse X versus each column's horizontal midpoint.\r\n  const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n  const handleDragOver = useCallback(\r\n    (e: React.DragEvent) => {\r\n      if (!draggedColumn) return;\r\n      e.preventDefault();\r\n    },\r\n    [draggedColumn],\r\n  );\r\n\r\n  const handleDrop = useCallback(\r\n    (e: React.DragEvent) => {\r\n      if (!draggedColumn || !containerRef.current) return;\r\n      e.preventDefault();\r\n\r\n      const cols = containerRef.current.querySelectorAll<HTMLElement>(\r\n        '[data-react-fancy-kanban-column]',\r\n      );\r\n      const x = e.clientX;\r\n      let dropIdx = cols.length;\r\n      for (let i = 0; i < cols.length; i++) {\r\n        const rect = cols[i]!.getBoundingClientRect();\r\n        if (x < rect.left + rect.width \/ 2) {\r\n          dropIdx = i;\r\n          break;\r\n        }\r\n      }\r\n\r\n      const sourceIdx = columnIds.indexOf(draggedColumn);\r\n      \/\/ When moving rightward, dropping at index N visually means landing\r\n      \/\/ at N - 1 after the source is removed.\r\n      const finalIdx =\r\n        sourceIdx >= 0 && dropIdx > sourceIdx ? dropIdx - 1 : dropIdx;\r\n\r\n      if (finalIdx !== sourceIdx) {\r\n        onColumnMove?.(draggedColumn, finalIdx);\r\n      }\r\n      setDraggedColumn(null);\r\n    },\r\n    [draggedColumn, columnIds, onColumnMove],\r\n  );\r\n\r\n  return (\r\n    <KanbanContext.Provider value={ctx}>\r\n      <div\r\n        ref={containerRef}\r\n        data-react-fancy-kanban=\"\"\r\n        onDragOver={handleDragOver}\r\n        onDrop={handleDrop}\r\n        role=\"application\"\r\n        aria-roledescription=\"kanban board\"\r\n        className={cn(\"flex gap-4 overflow-x-auto p-4\", className)}\r\n      >\r\n        {children}\r\n      <\/div>\r\n    <\/KanbanContext.Provider>\r\n  );\r\n}\r\n\r\nexport const Kanban = Object.assign(KanbanRoot, {\r\n  Column: KanbanColumn,\r\n  Card: KanbanCard,\r\n  ColumnHandle: KanbanColumnHandle,\r\n});\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/Kanban.tsx"},{"path":"components\/fancy\/kanban\/Kanban.types.ts","content":"import type { ReactNode } from \"react\";\r\n\r\n\/**\r\n * Fired when a card is dropped into a column. `toIndex` is the position\r\n * the card should land at within the destination column (0-based;\r\n * `toIndex === current count` means append).\r\n *\r\n * For a same-column reorder, `fromColumn === toColumn` and `toIndex` is\r\n * the new position.\r\n *\/\r\nexport type KanbanCardMoveHandler = (\r\n  cardId: string,\r\n  fromColumn: string,\r\n  toColumn: string,\r\n  toIndex: number,\r\n) => void;\r\n\r\n\/**\r\n * Fired when a column is dropped at a new position. `toIndex` is the\r\n * new position among registered columns (0-based).\r\n *\/\r\nexport type KanbanColumnMoveHandler = (\r\n  columnId: string,\r\n  toIndex: number,\r\n) => void;\r\n\r\nexport interface KanbanContextValue {\r\n  \/\/ Card drag state\r\n  draggedCard: string | null;\r\n  setDraggedCard: (id: string | null) => void;\r\n  dragSource: string | null;\r\n  setDragSource: (id: string | null) => void;\r\n\r\n  \/\/ Column drag state\r\n  draggedColumn: string | null;\r\n  setDraggedColumn: (id: string | null) => void;\r\n\r\n  \/\/ Callbacks\r\n  onCardMove?: KanbanCardMoveHandler;\r\n  onColumnMove?: KanbanColumnMoveHandler;\r\n\r\n  \/\/ Column registration \u2014 root tracks order for column-reorder math\r\n  columnIds: string[];\r\n  registerColumn: (id: string) => () => void;\r\n}\r\n\r\nexport interface KanbanProps {\r\n  children: ReactNode;\r\n  \/**\r\n   * Called when a card is dropped into a column. Receives the destination\r\n   * index so handlers can support within-column reorder.\r\n   *\/\r\n  onCardMove?: KanbanCardMoveHandler;\r\n  \/**\r\n   * Called when a column is dropped at a new position. Only fires if at\r\n   * least one column inside the board has a `<Kanban.ColumnHandle>` and\r\n   * a column was actually dragged.\r\n   *\/\r\n  onColumnMove?: KanbanColumnMoveHandler;\r\n  className?: string;\r\n}\r\n\r\nexport interface KanbanColumnProps {\r\n  children: ReactNode;\r\n  id: string;\r\n  title?: string;\r\n  className?: string;\r\n  \/**\r\n   * Skip the column's default visuals (background, padding, min-height,\r\n   * fixed width). Drop-target wiring and the drag-over ring stay.\r\n   *\/\r\n  unstyled?: boolean;\r\n  \/**\r\n   * Soft work-in-progress limit. Shown in the column header (when `title`\r\n   * is provided) as `count\/limit`. Turns red over capacity. Drops are\r\n   * still accepted \u2014 enforce hard via the consumer's `onCardMove`.\r\n   *\/\r\n  wipLimit?: number;\r\n  \/**\r\n   * If true, the column renders nothing when it has zero card children.\r\n   * Useful for filter UIs that want clean collapse instead of empty\r\n   * placeholders.\r\n   *\/\r\n  hideWhenEmpty?: boolean;\r\n}\r\n\r\nexport interface KanbanCardProps {\r\n  children: ReactNode;\r\n  id: string;\r\n  className?: string;\r\n  \/**\r\n   * Skip the card's default visuals (border, padding, shadow). Drag\r\n   * handlers and `draggable` stay.\r\n   *\/\r\n  unstyled?: boolean;\r\n}\r\n\r\nexport interface KanbanColumnHandleProps {\r\n  children: ReactNode;\r\n  className?: string;\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/Kanban.types.ts"},{"path":"components\/fancy\/kanban\/KanbanCard.tsx","content":"import { useCallback } from \"react\";\r\nimport { cn } from \"..\/..\/utils\/cn\";\r\nimport { useKanban, useKanbanColumn } from \".\/Kanban.context\";\r\nimport type { KanbanCardProps } from \".\/Kanban.types\";\r\n\r\nconst DEFAULT_CARD_CLASSES =\r\n  \"rounded-lg border border-zinc-200 bg-white p-3 shadow-sm transition-shadow hover:shadow-md dark:border-zinc-700 dark:bg-zinc-900\";\r\n\r\nexport function KanbanCard({ children, id, className, unstyled }: KanbanCardProps) {\r\n  const { setDraggedCard, setDragSource } = useKanban();\r\n  const columnId = useKanbanColumn();\r\n\r\n  const handleDragStart = useCallback(() => {\r\n    setDraggedCard(id);\r\n    setDragSource(columnId);\r\n  }, [id, columnId, setDraggedCard, setDragSource]);\r\n\r\n  const handleDragEnd = useCallback(() => {\r\n    setDraggedCard(null);\r\n    setDragSource(null);\r\n  }, [setDraggedCard, setDragSource]);\r\n\r\n  return (\r\n    <div\r\n      data-react-fancy-kanban-card=\"\"\r\n      draggable\r\n      onDragStart={handleDragStart}\r\n      onDragEnd={handleDragEnd}\r\n      className={cn(\r\n        \/\/ Drag affordance \u2014 kept even when unstyled so users still see grab cursors.\r\n        \"cursor-grab active:cursor-grabbing\",\r\n        !unstyled && DEFAULT_CARD_CLASSES,\r\n        className,\r\n      )}\r\n    >\r\n      {children}\r\n    <\/div>\r\n  );\r\n}\r\n\r\nKanbanCard.displayName = \"KanbanCard\";\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/KanbanCard.tsx"},{"path":"components\/fancy\/kanban\/KanbanColumn.tsx","content":"import { Children, isValidElement, useCallback, useEffect, useRef, useState } from \"react\";\r\nimport { cn } from \"..\/..\/utils\/cn\";\r\nimport { KanbanCard } from \".\/KanbanCard\";\r\nimport { useKanban, KanbanColumnContext } from \".\/Kanban.context\";\r\nimport type { KanbanColumnProps } from \".\/Kanban.types\";\r\n\r\nconst DEFAULT_COLUMN_CLASSES =\r\n  \"min-h-[200px] w-72 rounded-xl bg-zinc-50 p-3 dark:bg-zinc-800\/50\";\r\n\r\n\/**\r\n * Deep-recurse through the children tree counting Kanban.Card descendants\r\n * regardless of wrapping (Fragment, ContextMenu, motion.div, custom HOCs,\r\n * etc.). Used by `hideWhenEmpty` and the WIP-limit count chip.\r\n *\/\r\nfunction countCardChildren(children: React.ReactNode): number {\r\n  let n = 0;\r\n  Children.forEach(children, (child) => {\r\n    if (!isValidElement(child)) return;\r\n    if (child.type === KanbanCard) {\r\n      n += 1;\r\n      return;\r\n    }\r\n    const inner = (child.props as { children?: React.ReactNode }).children;\r\n    if (inner !== undefined) n += countCardChildren(inner);\r\n  });\r\n  return n;\r\n}\r\n\r\n\/**\r\n * Find the document-order index of a Kanban.Card with the given id, deep-\r\n * recursing through wrappers. Used by same-column reorder to compute the\r\n * post-removal insert position.\r\n *\/\r\nfunction findCardIndex(children: React.ReactNode, cardId: string): number {\r\n  let idx = -1;\r\n  let i = 0;\r\n  function walk(nodes: React.ReactNode): void {\r\n    Children.forEach(nodes, (child) => {\r\n      if (idx !== -1) return;\r\n      if (!isValidElement(child)) return;\r\n      if (child.type === KanbanCard) {\r\n        if ((child.props as { id?: string }).id === cardId) idx = i;\r\n        i += 1;\r\n        return;\r\n      }\r\n      const inner = (child.props as { children?: React.ReactNode }).children;\r\n      if (inner !== undefined) walk(inner);\r\n    });\r\n  }\r\n  walk(children);\r\n  return idx;\r\n}\r\n\r\nexport function KanbanColumn({\r\n  children,\r\n  id,\r\n  title,\r\n  className,\r\n  unstyled,\r\n  wipLimit,\r\n  hideWhenEmpty,\r\n}: KanbanColumnProps) {\r\n  const { onCardMove, draggedCard, dragSource, registerColumn } = useKanban();\r\n  const [dragOver, setDragOver] = useState(false);\r\n  const [dropIndex, setDropIndex] = useState<number | null>(null);\r\n  const [dropY, setDropY] = useState<number | null>(null);\r\n  const cardsRef = useRef<HTMLDivElement>(null);\r\n\r\n  useEffect(() => registerColumn(id), [id, registerColumn]);\r\n\r\n  \/**\r\n   * Compute drop position from mouse Y. Walks the *DOM* (not the React\r\n   * tree) and queries `[data-react-fancy-kanban-card]` so wrappers\r\n   * (ContextMenu, custom Card surfaces, motion.div) don't break the\r\n   * indicator placement.\r\n   *\/\r\n  const updateDrop = useCallback((clientY: number) => {\r\n    const container = cardsRef.current;\r\n    if (!container) {\r\n      setDropIndex(null);\r\n      setDropY(null);\r\n      return;\r\n    }\r\n\r\n    \/\/ Limit to cards belonging to THIS column \u2014 important if a card\r\n    \/\/ happens to nest a sub-board (rare, but cheap to defend).\r\n    const all = Array.from(\r\n      container.querySelectorAll<HTMLElement>(\r\n        \"[data-react-fancy-kanban-card]\",\r\n      ),\r\n    );\r\n    const cards = all.filter(\r\n      (el) =>\r\n        el.closest(\"[data-react-fancy-kanban-column]\") ===\r\n        cardsRef.current?.closest(\"[data-react-fancy-kanban-column]\"),\r\n    );\r\n\r\n    const containerRect = container.getBoundingClientRect();\r\n\r\n    if (cards.length === 0) {\r\n      setDropIndex(0);\r\n      setDropY(0);\r\n      return;\r\n    }\r\n\r\n    let idx = cards.length;\r\n    let yRel = 0;\r\n    for (let i = 0; i < cards.length; i++) {\r\n      const rect = cards[i]!.getBoundingClientRect();\r\n      if (clientY < rect.top + rect.height \/ 2) {\r\n        idx = i;\r\n        yRel = rect.top - containerRect.top;\r\n        break;\r\n      }\r\n    }\r\n    if (idx === cards.length) {\r\n      const last = cards[cards.length - 1]!.getBoundingClientRect();\r\n      yRel = last.bottom - containerRect.top;\r\n    }\r\n\r\n    setDropIndex(idx);\r\n    setDropY(yRel);\r\n  }, []);\r\n\r\n  const handleDragOver = useCallback(\r\n    (e: React.DragEvent) => {\r\n      \/\/ Only react to card drags. Column drags are handled by the root.\r\n      if (!draggedCard) return;\r\n      e.preventDefault();\r\n      e.stopPropagation();\r\n      setDragOver(true);\r\n      updateDrop(e.clientY);\r\n    },\r\n    [draggedCard, updateDrop],\r\n  );\r\n\r\n  const handleDragLeave = useCallback((e: React.DragEvent) => {\r\n    if (e.currentTarget.contains(e.relatedTarget as Node | null)) return;\r\n    setDragOver(false);\r\n    setDropIndex(null);\r\n    setDropY(null);\r\n  }, []);\r\n\r\n  const handleDrop = useCallback(\r\n    (e: React.DragEvent) => {\r\n      if (!draggedCard) return;\r\n      e.preventDefault();\r\n      e.stopPropagation();\r\n      const target = dropIndex ?? 0;\r\n\r\n      if (dragSource) {\r\n        let finalIdx = target;\r\n        if (dragSource === id) {\r\n          const srcIdx = findCardIndex(children, draggedCard);\r\n          if (srcIdx !== -1 && target > srcIdx) finalIdx = target - 1;\r\n          if (srcIdx === finalIdx) {\r\n            \/\/ No-op\r\n            setDragOver(false);\r\n            setDropIndex(null);\r\n            setDropY(null);\r\n            return;\r\n          }\r\n        }\r\n        onCardMove?.(draggedCard, dragSource, id, finalIdx);\r\n      }\r\n\r\n      setDragOver(false);\r\n      setDropIndex(null);\r\n      setDropY(null);\r\n    },\r\n    [draggedCard, dragSource, dropIndex, id, onCardMove, children],\r\n  );\r\n\r\n  const cardCount = countCardChildren(children);\r\n  if (hideWhenEmpty && cardCount === 0 && !draggedCard) return null;\r\n\r\n  const showIndicator =\r\n    draggedCard !== null &&\r\n    dropIndex !== null &&\r\n    dropY !== null &&\r\n    dragOver;\r\n\r\n  const overWip = wipLimit !== undefined && cardCount > wipLimit;\r\n\r\n  return (\r\n    <KanbanColumnContext.Provider value={id}>\r\n      <div\r\n        data-react-fancy-kanban-column=\"\"\r\n        data-column-id={id}\r\n        role=\"group\"\r\n        aria-label={title}\r\n        onDrop={handleDrop}\r\n        onDragOver={handleDragOver}\r\n        onDragLeave={handleDragLeave}\r\n        className={cn(\r\n          \"flex flex-col\",\r\n          !unstyled && DEFAULT_COLUMN_CLASSES,\r\n          dragOver && \"ring-2 ring-blue-400 ring-inset\",\r\n          className,\r\n        )}\r\n      >\r\n        {title && (\r\n          <h3 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-zinc-600 dark:text-zinc-400\">\r\n            <span className=\"flex-1\">{title}<\/span>\r\n            <span\r\n              className={cn(\r\n                \"rounded-full px-1.5 py-0.5 text-[10px] font-semibold\",\r\n                overWip\r\n                  ? \"bg-red-100 text-red-700 dark:bg-red-900\/40 dark:text-red-300\"\r\n                  : \"bg-zinc-200 text-zinc-700 dark:bg-zinc-700 dark:text-zinc-300\",\r\n              )}\r\n            >\r\n              {cardCount}\r\n              {wipLimit !== undefined ? `\/${wipLimit}` : \"\"}\r\n            <\/span>\r\n          <\/h3>\r\n        )}\r\n\r\n        {\/* Cards container \u2014 `relative` so the drop indicator overlay\r\n            can position itself in the container's coordinate space.\r\n            Children are rendered untouched so any wrapper hierarchy\r\n            (ContextMenu, motion.div, etc.) keeps working. *\/}\r\n        <div ref={cardsRef} className=\"relative flex flex-1 flex-col gap-2\">\r\n          {children}\r\n\r\n          {showIndicator && (\r\n            <div\r\n              data-react-fancy-kanban-drop-indicator=\"\"\r\n              style={{ top: dropY }}\r\n              className=\"pointer-events-none absolute left-0 right-0 h-0.5 -translate-y-1\/2 rounded-full bg-blue-500\/80 shadow-[0_0_0_3px_rgba(59,130,246,0.15)]\"\r\n            \/>\r\n          )}\r\n        <\/div>\r\n      <\/div>\r\n    <\/KanbanColumnContext.Provider>\r\n  );\r\n}\r\n\r\nKanbanColumn.displayName = \"KanbanColumn\";\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/KanbanColumn.tsx"},{"path":"components\/fancy\/kanban\/KanbanColumnHandle.tsx","content":"import { useCallback } from \"react\";\r\nimport { cn } from \"..\/..\/utils\/cn\";\r\nimport { useKanban, useKanbanColumn } from \".\/Kanban.context\";\r\nimport type { KanbanColumnHandleProps } from \".\/Kanban.types\";\r\n\r\n\/**\r\n * Drag handle for column reordering.\r\n *\r\n * Mount inside a `Kanban.Column` to make that column draggable. The\r\n * column's parent `Kanban` listens for the drop and surfaces the new\r\n * position via `onColumnMove`. Without a handle, columns are static.\r\n *\r\n * Typically wrapped around the column header so users grab the title\r\n * to reorder; can also be a small grip icon.\r\n *\/\r\nexport function KanbanColumnHandle({\r\n  children,\r\n  className,\r\n}: KanbanColumnHandleProps) {\r\n  const { setDraggedColumn } = useKanban();\r\n  const columnId = useKanbanColumn();\r\n\r\n  const handleDragStart = useCallback(\r\n    (e: React.DragEvent) => {\r\n      \/\/ Set a dataTransfer payload so the browser permits the drag \u2014 some\r\n      \/\/ browsers refuse if dataTransfer is empty.\r\n      e.dataTransfer.effectAllowed = \"move\";\r\n      e.dataTransfer.setData(\"text\/plain\", columnId);\r\n      e.stopPropagation();\r\n      setDraggedColumn(columnId);\r\n    },\r\n    [columnId, setDraggedColumn],\r\n  );\r\n\r\n  const handleDragEnd = useCallback(() => {\r\n    setDraggedColumn(null);\r\n  }, [setDraggedColumn]);\r\n\r\n  return (\r\n    <div\r\n      draggable\r\n      onDragStart={handleDragStart}\r\n      onDragEnd={handleDragEnd}\r\n      data-react-fancy-kanban-column-handle=\"\"\r\n      className={cn(\r\n        \"cursor-grab active:cursor-grabbing select-none\",\r\n        className,\r\n      )}\r\n    >\r\n      {children}\r\n    <\/div>\r\n  );\r\n}\r\n\r\nKanbanColumnHandle.displayName = \"KanbanColumnHandle\";\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/KanbanColumnHandle.tsx"},{"path":"components\/fancy\/kanban\/index.ts","content":"export { Kanban } from \".\/Kanban\";\r\nexport { useKanban } from \".\/Kanban.context\";\r\nexport type {\r\n  KanbanProps,\r\n  KanbanColumnProps,\r\n  KanbanCardProps,\r\n  KanbanColumnHandleProps,\r\n  KanbanContextValue,\r\n  KanbanCardMoveHandler,\r\n  KanbanColumnMoveHandler,\r\n} from \".\/Kanban.types\";\r\n","type":"registry:ui","target":"components\/fancy\/kanban\/index.ts"}]}