{"version":3,"file":"KanbanItem.mjs","names":[],"sources":["../../../../package/common/kanbanBoard/KanbanItem.tsx"],"sourcesContent":["import type { SyntheticEvent } from 'react';\nimport { useCallback, useLayoutEffect, useRef } from 'react';\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport cx from 'classnames';\n\nimport type { KanbanItemProps } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\n\n// Hoisted so these are referentially stable across renders — an inline object literal here would\n// give `useSortable` a new `disabled` value every render (every card re-renders on every\n// `dragOver` while a drag is in progress, via the board's `placement`), which can spin dnd-kit's own\n// registration effect into a render loop that eventually trips React's \"Maximum update depth\n// exceeded\" guard. Same fix as the sensor options in `KanbanBoard.tsx` and `data`/`disabled` in\n// `KanbanColumn.tsx`. Only two shapes are ever needed, so both are hoisted rather than memoized.\nconst ITEM_DISABLED_DRAG_AND_DROP = { draggable: true, droppable: true };\nconst ITEM_DISABLED_DRAG_ONLY = { draggable: true, droppable: false };\n\nfunction KanbanItem({ id, label, dragHandle, disabled, preventAsDropTarget, children }: KanbanItemProps) {\n  const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n    id,\n    // The boolean shorthand only disables dragging *out* of the card — dnd-kit hard-codes\n    // `droppable: false` for it either way (\"backwards compatibility\"). That's actually what we\n    // want for a card pinned individually (`getItemDisabled`): it can't be dragged, but other\n    // cards should still be able to land before/after it normally. Only a frozen *column*\n    // (`preventAsDropTarget`) also disables droppable, so nothing can be dropped into it at all.\n    disabled: disabled ? (preventAsDropTarget ? ITEM_DISABLED_DRAG_AND_DROP : ITEM_DISABLED_DRAG_ONLY) : undefined,\n  });\n\n  // Without an activator, dnd-kit starts a drag for a Space or Enter bubbling up from anything\n  // inside the card, and cancels it: a button in the card could not be pressed, nor a space typed.\n  const nodeRef = useRef<HTMLDivElement | null>(null);\n  const setRefs = useCallback(\n    (node: HTMLDivElement | null) => {\n      nodeRef.current = node;\n      setNodeRef(node);\n      if (!dragHandle) setActivatorNodeRef(node);\n    },\n    [setNodeRef, setActivatorNodeRef, dragHandle],\n  );\n\n  // With `dragHandle`, the handle is the keyboard handle too, and the card a plain container: as a\n  // button, the card wrapped its own controls, which a screen reader then reads as text. The\n  // handle is the consumer's element, so it gets the drag semantics here rather than as props.\n  // No dependencies: the consumer can re-render the handle at any time.\n  useLayoutEffect(() => {\n    if (!dragHandle) return;\n    const handle = nodeRef.current?.querySelector<HTMLElement>('[data-drag-handle]') ?? null;\n    setActivatorNodeRef(handle);\n    if (!handle) return;\n    if (handle.tabIndex < 0) handle.tabIndex = 0;\n    if (handle.tagName !== 'BUTTON' && !handle.hasAttribute('role')) handle.setAttribute('role', 'button');\n    const namedByUs = handle.hasAttribute('data-kanban-label');\n    if (label && (namedByUs || !(handle.hasAttribute('aria-label') || handle.hasAttribute('aria-labelledby')))) {\n      handle.setAttribute('aria-label', label);\n      handle.setAttribute('data-kanban-label', '');\n    }\n    handle.setAttribute('data-kanban-card', '');\n    for (const [name, value] of Object.entries(attributes)) {\n      if (name === 'role' || name === 'tabIndex') continue;\n      if (value === undefined) handle.removeAttribute(name);\n      else handle.setAttribute(name, String(value));\n    }\n  });\n\n  // dnd-kit's listeners are a new object every render, so wrapping them per render costs nothing.\n  const handleListeners =\n    dragHandle && listeners\n      ? Object.fromEntries(\n          Object.entries(listeners).map(([name, listener]) => [\n            name,\n            (event: SyntheticEvent) => {\n              if ((event.target as HTMLElement).closest('[data-drag-handle]')) listener(event);\n            },\n          ]),\n        )\n      : listeners;\n\n  return (\n    <div\n      ref={setRefs}\n      data-kanban-card={dragHandle ? undefined : ''}\n      style={{ transform: CSS.Transform.toString(transform), transition }}\n      className={cx(\n        styles.item,\n        dragHandle && styles.itemHandled,\n        isDragging && styles.itemDragging,\n        disabled && styles.itemDisabled,\n      )}\n      {...(dragHandle ? undefined : attributes)}\n      {...handleListeners}\n    >\n      {children}\n    </div>\n  );\n}\n\nexport default KanbanItem;\n"],"mappings":"qRAeA,IAAM,EAA8B,CAAE,UAAW,GAAM,UAAW,EAAK,EACjE,EAA0B,CAAE,UAAW,GAAM,UAAW,EAAM,EAEpE,SAAS,EAAW,CAAE,KAAI,QAAO,aAAY,WAAU,sBAAqB,YAA6B,CACvG,GAAM,CAAE,aAAY,YAAW,aAAY,sBAAqB,YAAW,aAAY,cAAe,EAAY,CAChH,KAMA,SAAU,EAAY,EAAsB,EAA8B,EAA2B,IAAA,EACvG,CAAC,EAIK,EAAU,EAA8B,IAAI,EAC5C,EAAU,EACb,GAAgC,CAC/B,EAAQ,QAAU,EAClB,EAAW,CAAI,EACV,GAAY,EAAoB,CAAI,CAC3C,EACA,CAAC,EAAY,EAAqB,CAAU,CAC9C,EAMA,MAAsB,CACpB,GAAI,CAAC,EAAY,OACjB,IAAM,EAAS,EAAQ,SAAS,cAA2B,oBAAoB,GAAK,KAEpF,GADA,EAAoB,CAAM,EACtB,CAAC,EAAQ,OACT,EAAO,SAAW,IAAG,EAAO,SAAW,GACvC,EAAO,UAAY,UAAY,CAAC,EAAO,aAAa,MAAM,GAAG,EAAO,aAAa,OAAQ,QAAQ,EACrG,IAAM,EAAY,EAAO,aAAa,mBAAmB,EACrD,IAAU,GAAa,EAAE,EAAO,aAAa,YAAY,GAAK,EAAO,aAAa,iBAAiB,MACrG,EAAO,aAAa,aAAc,CAAK,EACvC,EAAO,aAAa,oBAAqB,EAAE,GAE7C,EAAO,aAAa,mBAAoB,EAAE,EAC1C,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,CAAU,EAC/C,IAAS,QAAU,IAAS,aAC5B,IAAU,IAAA,GAAW,EAAO,gBAAgB,CAAI,EAC/C,EAAO,aAAa,EAAM,OAAO,CAAK,CAAC,EAEhD,CAAC,EAGD,IAAM,EACJ,GAAc,EACV,OAAO,YACL,OAAO,QAAQ,CAAS,CAAC,CAAC,KAAK,CAAC,EAAM,KAAc,CAClD,EACC,GAA0B,CACpB,EAAM,OAAuB,QAAQ,oBAAoB,GAAG,EAAS,CAAK,CACjF,CACF,CAAC,CACH,EACA,EAEN,OACE,EAAC,MAAD,CACE,IAAK,EACL,mBAAkB,EAAa,IAAA,GAAY,GAC3C,MAAO,CAAE,UAAW,EAAI,UAAU,SAAS,CAAS,EAAG,YAAW,EAClE,UAAW,EACT,EAAO,KACP,GAAc,EAAO,YACrB,GAAc,EAAO,aACrB,GAAY,EAAO,YACrB,EACA,GAAK,EAAa,IAAA,GAAY,EAC9B,GAAI,EAEH,UACE,CAAA,CAET"}