{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "adaptive-actions",
  "title": "Adaptive Actions",
  "description": "A responsive action toolbar that measures its available inline size and moves overflowed items into an accessible dropdown menu, with priority and pinned flags to control what stays visible.",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/adaptive-actions.tsx",
      "type": "registry:ui",
      "content": "'use client'\n\nimport {\n  createContext,\n  forwardRef,\n  useCallback,\n  useContext,\n  useEffect,\n  useId,\n  useLayoutEffect,\n  useMemo,\n  useRef,\n  useState,\n  type HTMLAttributes,\n  type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { cn } from '@/lib/utils'\n\nexport interface ActionItem {\n  /** Stable unique identifier for the action. */\n  id: string\n  /** Accessible label — rendered as visible text or `aria-label` for icon-only. */\n  label: string\n  /** Icon rendered inside the button (decorative, `aria-hidden`). */\n  icon?: ReactNode\n  /** Disables this action. */\n  disabled?: boolean\n  /** Marks action as destructive (applies destructive color tokens). */\n  destructive?: boolean\n  /** Priority determines overflow order. Higher priority items overflow last. Default 0. */\n  priority?: number\n  /** When true, this item never overflows into the menu regardless of space. */\n  pinned?: boolean\n  /** Invoked on activation (click / Enter / Space). */\n  onSelect?: () => void\n}\n\nexport interface AdaptiveActionsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n  /** The actions to render. */\n  actions: ActionItem[]\n  /** Accessible label for the toolbar. Defaults to 'Actions'. */\n  label?: string\n  /** Localized label for the overflow trigger button. Defaults to 'More actions'. */\n  moreLabel?: string\n  /** Render a custom trigger for the overflow menu. Receives the count of hidden items. */\n  renderMoreTrigger?: (count: number) => ReactNode\n  /** Maximum visible items before overflow — independent of inline measurement. Optional. */\n  maxVisible?: number\n}\n\ninterface AdaptiveActionsContextValue {\n  rovingIndex: number\n  setRovingIndex: (i: number) => void\n  itemCount: number\n}\n\nconst AdaptiveActionsContext = createContext<AdaptiveActionsContextValue | null>(null)\n\nfunction useAdaptiveActionsCtx() {\n  const ctx = useContext(AdaptiveActionsContext)\n  if (!ctx) throw new Error('AdaptiveActions compound child used outside AdaptiveActions')\n  return ctx\n}\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ninterface OverflowMenuProps {\n  actions: ActionItem[]\n  triggerId: string\n  contentId: string\n  moreLabel: string\n  renderMoreTrigger?: (count: number) => ReactNode\n  triggerTabIndex: number\n}\n\nfunction OverflowMenu({\n  actions,\n  triggerId,\n  contentId,\n  moreLabel,\n  renderMoreTrigger,\n  triggerTabIndex,\n}: OverflowMenuProps) {\n  const [open, setOpen] = useState(false)\n  const [focusedIndex, setFocusedIndex] = useState(-1)\n  const triggerRef = useRef<HTMLButtonElement>(null)\n  const menuRef = useRef<HTMLDivElement>(null)\n  const reduceMotion = useReducedMotion()\n\n  useEffect(() => {\n    if (!open) return\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        e.preventDefault()\n        setOpen(false)\n        triggerRef.current?.focus()\n      }\n    }\n    document.addEventListener('keydown', handleKeyDown)\n    return () => document.removeEventListener('keydown', handleKeyDown)\n  }, [open])\n\n  useEffect(() => {\n    if (!open) return\n    const handlePointerDown = (e: PointerEvent) => {\n      const target = e.target as HTMLElement\n      if (triggerRef.current?.contains(target) || menuRef.current?.contains(target)) {\n        return\n      }\n      setOpen(false)\n    }\n    document.addEventListener('pointerdown', handlePointerDown)\n    return () => document.removeEventListener('pointerdown', handlePointerDown)\n  }, [open])\n\n  useEffect(() => {\n    if (!open) return\n    const firstEnabled = actions.findIndex((a) => !a.disabled)\n    const idx = firstEnabled >= 0 ? firstEnabled : 0\n    // Use a microtask so setState isn't synchronous in the effect body\n    queueMicrotask(() => {\n      setFocusedIndex(idx)\n    })\n  }, [open, actions])\n\n  useEffect(() => {\n    if (!open || focusedIndex < 0) return\n    const menu = menuRef.current\n    if (!menu) return\n    const items = menu.querySelectorAll<HTMLElement>('[role=\"menuitem\"]')\n    items[focusedIndex]?.focus()\n  }, [open, focusedIndex])\n\n  const handleMenuKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      const enabledIndices = actions.map((a, i) => (!a.disabled ? i : -1)).filter((i) => i >= 0)\n      const currentPos = enabledIndices.indexOf(focusedIndex)\n\n      if (e.key === 'ArrowDown') {\n        e.preventDefault()\n        const next = enabledIndices[(currentPos + 1) % enabledIndices.length]\n        setFocusedIndex(next)\n      } else if (e.key === 'ArrowUp') {\n        e.preventDefault()\n        const prev =\n          enabledIndices[(currentPos - 1 + enabledIndices.length) % enabledIndices.length]\n        setFocusedIndex(prev)\n      } else if (e.key === 'Home') {\n        e.preventDefault()\n        setFocusedIndex(enabledIndices[0])\n      } else if (e.key === 'End') {\n        e.preventDefault()\n        setFocusedIndex(enabledIndices[enabledIndices.length - 1])\n      }\n    },\n    [actions, focusedIndex],\n  )\n\n  const [menuPos, setMenuPos] = useState<{\n    top: number\n    insetInlineEnd: number\n  } | null>(null)\n\n  useEffect(() => {\n    if (!open) return\n    const trigger = triggerRef.current\n    if (!trigger) return\n    const updatePos = () => {\n      const rect = trigger.getBoundingClientRect()\n      const isRTL = trigger.ownerDocument.defaultView?.getComputedStyle(trigger).direction === 'rtl'\n      const viewportWidth = trigger.ownerDocument.documentElement.clientWidth\n      // In LTR: align menu's inline-end to the trigger's inline-end (right edge)\n      // In RTL: align menu's inline-end to the trigger's inline-start (left edge)\n      const insetInlineEnd = isRTL ? viewportWidth - rect.left : viewportWidth - rect.right\n      setMenuPos({\n        top: rect.bottom + 4,\n        insetInlineEnd,\n      })\n    }\n    updatePos()\n    window.addEventListener('scroll', updatePos, { passive: true })\n    window.addEventListener('resize', updatePos, { passive: true })\n    return () => {\n      window.removeEventListener('scroll', updatePos)\n      window.removeEventListener('resize', updatePos)\n    }\n  }, [open])\n\n  return (\n    <>\n      <button\n        ref={triggerRef}\n        id={triggerId}\n        type=\"button\"\n        tabIndex={triggerTabIndex}\n        aria-haspopup=\"menu\"\n        aria-expanded={open}\n        aria-controls={open ? contentId : undefined}\n        aria-label={moreLabel}\n        className={cn(\n          'inline-flex min-h-11 min-w-11 items-center justify-center rounded-lg supports-[corner-shape:squircle]:corner-squircle px-3 text-sm font-medium text-(--color-fg)',\n          'transition-colors duration-(--motion-dur-fast) ease motion-reduce:transition-none',\n          'hover:bg-(--color-surface-2)',\n          'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--color-accent) focus-visible:ring-offset-2 focus-visible:ring-offset-(--color-bg)',\n        )}\n        onClick={() => setOpen((v) => !v)}\n        onKeyDown={(e) => {\n          if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n            e.preventDefault()\n            setOpen(true)\n          }\n        }}\n      >\n        {renderMoreTrigger ? (\n          renderMoreTrigger(actions.length)\n        ) : (\n          <span aria-hidden=\"true\" className=\"flex items-center gap-1\">\n            <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n              <circle cx=\"4\" cy=\"8\" r=\"1.5\" />\n              <circle cx=\"8\" cy=\"8\" r=\"1.5\" />\n              <circle cx=\"12\" cy=\"8\" r=\"1.5\" />\n            </svg>\n          </span>\n        )}\n      </button>\n\n      {open &&\n        typeof document !== 'undefined' &&\n        menuPos &&\n        createPortal(\n          <AnimatePresence>\n            <motion.div\n              ref={menuRef}\n              id={contentId}\n              role=\"menu\"\n              aria-labelledby={triggerId}\n              initial={reduceMotion ? false : { opacity: 0, y: -4 }}\n              animate={{ opacity: 1, y: 0 }}\n              exit={reduceMotion ? undefined : { opacity: 0, y: -4 }}\n              transition={\n                reduceMotion ? { duration: 0 } : { duration: 0.15, ease: [0.22, 1, 0.36, 1] }\n              }\n              style={{\n                position: 'fixed',\n                top: menuPos.top,\n                insetInlineEnd: menuPos.insetInlineEnd,\n                zIndex: 50,\n              }}\n              className=\"min-w-40 rounded-lg supports-[corner-shape:squircle]:corner-squircle border border-(--color-border) bg-(--color-surface) py-1 shadow-lg\"\n              onKeyDown={handleMenuKeyDown}\n            >\n              {actions.map((action, i) => (\n                <button\n                  key={action.id}\n                  type=\"button\"\n                  role=\"menuitem\"\n                  tabIndex={i === focusedIndex ? 0 : -1}\n                  disabled={action.disabled}\n                  aria-disabled={action.disabled || undefined}\n                  className={cn(\n                    'flex min-h-10 w-full items-center gap-2 px-3 py-2 text-start text-sm',\n                    'transition-colors duration-(--motion-dur-fast) ease motion-reduce:transition-none',\n                    action.disabled\n                      ? 'cursor-not-allowed opacity-50'\n                      : action.destructive\n                        ? 'text-(--color-destructive) hover:bg-(--color-destructive)/10 focus:bg-(--color-destructive)/10'\n                        : 'text-(--color-fg) hover:bg-(--color-surface-2) focus:bg-(--color-surface-2)',\n                    'focus:outline-none',\n                  )}\n                  onClick={() => {\n                    if (action.disabled) return\n                    action.onSelect?.()\n                    setOpen(false)\n                    triggerRef.current?.focus()\n                  }}\n                >\n                  {action.icon && (\n                    <span aria-hidden=\"true\" className=\"shrink-0\">\n                      {action.icon}\n                    </span>\n                  )}\n                  <span>{action.label}</span>\n                </button>\n              ))}\n            </motion.div>\n          </AnimatePresence>,\n          document.body,\n        )}\n    </>\n  )\n}\n\ninterface VisibleActionProps {\n  action: ActionItem\n  index: number\n  itemRef: (el: HTMLButtonElement | null) => void\n  measureRef?: (el: HTMLButtonElement | null) => void\n  visible: boolean\n}\n\nfunction VisibleAction({ action, index, itemRef, measureRef, visible }: VisibleActionProps) {\n  const { rovingIndex, setRovingIndex } = useAdaptiveActionsCtx()\n  const reduceMotion = useReducedMotion()\n\n  return (\n    <motion.div\n      key={action.id}\n      data-aa-item\n      layout={false}\n      initial={reduceMotion ? false : { opacity: 0, x: -6 }}\n      animate={\n        visible\n          ? { opacity: 1, x: 0, scale: 1 }\n          : { opacity: 0, x: -6, scale: 0.97, pointerEvents: 'none' as const }\n      }\n      exit={reduceMotion ? undefined : { opacity: 0, x: 6, scale: 0.97 }}\n      transition={reduceMotion ? { duration: 0 } : { duration: 0.18, ease: [0.22, 1, 0.36, 1] }}\n      className={cn(\n        'motion-reduce:transform-none motion-reduce:transition-none',\n        !visible && 'pointer-events-none absolute opacity-0',\n      )}\n      style={!visible ? { position: 'absolute', visibility: 'hidden' } : undefined}\n    >\n      <button\n        ref={(el) => {\n          itemRef(el)\n          measureRef?.(el)\n        }}\n        type=\"button\"\n        tabIndex={index === rovingIndex ? 0 : -1}\n        disabled={action.disabled}\n        aria-disabled={action.disabled || undefined}\n        aria-label={!action.icon ? undefined : action.label}\n        className={cn(\n          'inline-flex min-h-11 min-w-11 items-center justify-center gap-2 rounded-lg supports-[corner-shape:squircle]:corner-squircle px-3 text-sm font-medium',\n          'transition-colors duration-(--motion-dur-fast) ease motion-reduce:transition-none',\n          action.disabled\n            ? 'cursor-not-allowed opacity-50'\n            : action.destructive\n              ? 'text-(--color-destructive) hover:bg-(--color-destructive)/10'\n              : 'text-(--color-fg) hover:bg-(--color-surface-2)',\n          'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--color-accent) focus-visible:ring-offset-2 focus-visible:ring-offset-(--color-bg)',\n        )}\n        onClick={() => {\n          if (action.disabled) return\n          setRovingIndex(index)\n          action.onSelect?.()\n        }}\n        onFocus={() => setRovingIndex(index)}\n        onPointerDown={(e) => {\n          // Prevent focus-visible ring on pointer click\n          e.preventDefault()\n          ;(e.currentTarget as HTMLElement).focus()\n        }}\n      >\n        {action.icon && (\n          <span aria-hidden=\"true\" className=\"shrink-0\">\n            {action.icon}\n          </span>\n        )}\n        <span className={action.icon ? 'sr-only sm:not-sr-only' : undefined}>{action.label}</span>\n      </button>\n    </motion.div>\n  )\n}\n\nexport const AdaptiveActions = forwardRef<HTMLDivElement, AdaptiveActionsProps>(\n  (\n    {\n      actions,\n      label = 'Actions',\n      moreLabel = 'More actions',\n      renderMoreTrigger,\n      maxVisible,\n      className,\n      ...props\n    },\n    ref,\n  ) => {\n    const reactId = useId()\n    const triggerId = `${reactId}-overflow-trigger`\n    const contentId = `${reactId}-overflow-menu`\n\n    const [rovingIndex, setRovingIndex] = useState(0)\n    const [visibleCount, setVisibleCount] = useState<number | null>(null)\n    const containerRef = useRef<HTMLDivElement>(null)\n    const itemWidthsRef = useRef<number[]>([])\n    const moreButtonWidthRef = useRef(48) // estimated; measured on mount\n    const measuredRef = useRef(false)\n    const measureFrameRef = useRef<number | null>(null)\n\n    const sortedActions = useMemo(() => {\n      return [...actions].sort((a, b) => {\n        const ap = a.pinned ? Infinity : (a.priority ?? 0)\n        const bp = b.pinned ? Infinity : (b.priority ?? 0)\n        return bp - ap\n      })\n    }, [actions])\n\n    const measureRowRef = useRef<HTMLDivElement>(null)\n\n    const calculateVisibleCount = useCallback(() => {\n      const container = containerRef.current\n      if (!container || !measuredRef.current) return\n\n      const containerWidth = container.offsetWidth\n      const gap = 4 // gap-1 = 0.25rem = 4px\n      const widths = itemWidthsRef.current\n      const moreWidth = moreButtonWidthRef.current\n\n      if (maxVisible !== undefined) {\n        setVisibleCount(Math.min(maxVisible, sortedActions.length))\n        return\n      }\n\n      let usedWidth = 0\n      let count = 0\n\n      for (let i = 0; i < sortedActions.length; i++) {\n        const itemWidth = widths[i] ?? 44\n        const nextUsed = usedWidth + itemWidth + (count > 0 ? gap : 0)\n\n        const remaining = sortedActions.length - (i + 1)\n        const needsMore = remaining > 0\n        const spaceNeeded = needsMore ? nextUsed + gap + moreWidth : nextUsed\n\n        if (spaceNeeded <= containerWidth) {\n          usedWidth = nextUsed\n          count++\n        } else {\n          // This item doesn't fit. But if it's pinned, we must include it.\n          if (sortedActions[i].pinned) {\n            usedWidth = nextUsed\n            count++\n          } else {\n            break\n          }\n        }\n      }\n\n      const totalWidth = widths.reduce((sum, w, i) => sum + w + (i > 0 ? gap : 0), 0)\n      if (totalWidth <= containerWidth) {\n        count = sortedActions.length\n      }\n\n      setVisibleCount(count)\n    }, [sortedActions, maxVisible])\n\n    useIsomorphicLayoutEffect(() => {\n      const measureRow = measureRowRef.current\n      if (!measureRow) return\n      const buttons = measureRow.querySelectorAll<HTMLElement>('[data-aa-measure]')\n      const widths: number[] = []\n      buttons.forEach((btn) => {\n        widths.push(btn.offsetWidth)\n      })\n      itemWidthsRef.current = widths\n\n      const moreBtn = measureRow.querySelector<HTMLElement>('[data-aa-more-measure]')\n      if (moreBtn) {\n        moreButtonWidthRef.current = moreBtn.offsetWidth\n      }\n      measuredRef.current = true\n      calculateVisibleCount()\n    }, [actions, calculateVisibleCount])\n\n    useEffect(() => {\n      const container = containerRef.current\n      if (!container) return\n      let cancelled = false\n\n      const observer = new ResizeObserver(() => {\n        if (cancelled) return\n        // Debounce with rAF to avoid loops\n        if (measureFrameRef.current !== null) {\n          cancelAnimationFrame(measureFrameRef.current)\n        }\n        measureFrameRef.current = requestAnimationFrame(() => {\n          if (!cancelled) calculateVisibleCount()\n          measureFrameRef.current = null\n        })\n      })\n\n      observer.observe(container)\n      return () => {\n        cancelled = true\n        observer.disconnect()\n        if (measureFrameRef.current !== null) {\n          cancelAnimationFrame(measureFrameRef.current)\n          measureFrameRef.current = null\n        }\n      }\n    }, [calculateVisibleCount])\n\n    const effectiveVisibleCount = visibleCount ?? sortedActions.length\n    const visibleActions = sortedActions.slice(0, effectiveVisibleCount)\n    const overflowActions = sortedActions.slice(effectiveVisibleCount)\n\n    const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n      const toolbar = containerRef.current\n      if (!toolbar) return\n\n      const buttons = Array.from(\n        toolbar.querySelectorAll<HTMLElement>(\n          '[role=\"toolbar\"] > [data-aa-item] button:not([disabled]), [role=\"toolbar\"] > button:not([disabled])',\n        ),\n      )\n      if (!buttons.length) return\n\n      const isRTL = toolbar.ownerDocument.defaultView?.getComputedStyle(toolbar).direction === 'rtl'\n      const count = buttons.length\n      const currentIdx = buttons.indexOf(document.activeElement as HTMLElement)\n      let nextIdx = currentIdx\n\n      if (e.key === 'ArrowRight') {\n        e.preventDefault()\n        nextIdx = isRTL ? (currentIdx <= 0 ? count - 1 : currentIdx - 1) : (currentIdx + 1) % count\n      } else if (e.key === 'ArrowLeft') {\n        e.preventDefault()\n        nextIdx = isRTL ? (currentIdx + 1) % count : currentIdx <= 0 ? count - 1 : currentIdx - 1\n      } else if (e.key === 'Home') {\n        e.preventDefault()\n        nextIdx = 0\n      } else if (e.key === 'End') {\n        e.preventDefault()\n        nextIdx = count - 1\n      }\n\n      if (nextIdx !== currentIdx && nextIdx >= 0 && nextIdx < count) {\n        setRovingIndex(nextIdx)\n        buttons[nextIdx]?.focus()\n      }\n    }, [])\n\n    const itemRefs = useRef<(HTMLButtonElement | null)[]>([])\n    const itemCount = visibleActions.length + (overflowActions.length > 0 ? 1 : 0)\n\n    const ctx = useMemo<AdaptiveActionsContextValue>(\n      () => ({ rovingIndex, setRovingIndex, itemCount }),\n      [rovingIndex, itemCount],\n    )\n\n    return (\n      <AdaptiveActionsContext.Provider value={ctx}>\n        {/* Hidden measurement row — measures all items at full size without visible layout */}\n        <div\n          ref={measureRowRef}\n          aria-hidden=\"true\"\n          style={{\n            position: 'absolute',\n            visibility: 'hidden',\n            height: 0,\n            overflow: 'hidden',\n            pointerEvents: 'none',\n            whiteSpace: 'nowrap',\n          }}\n        >\n          {sortedActions.map((action) => (\n            <button\n              key={action.id}\n              data-aa-measure\n              type=\"button\"\n              tabIndex={-1}\n              className=\"inline-flex min-h-11 min-w-11 items-center gap-2 px-3 text-sm font-medium\"\n            >\n              {action.icon && <span className=\"shrink-0\">{action.icon}</span>}\n              <span>{action.label}</span>\n            </button>\n          ))}\n          <button\n            data-aa-more-measure\n            type=\"button\"\n            tabIndex={-1}\n            className=\"inline-flex min-h-11 min-w-11 items-center justify-center px-3 text-sm font-medium\"\n          >\n            <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n              <circle cx=\"4\" cy=\"8\" r=\"1.5\" />\n              <circle cx=\"8\" cy=\"8\" r=\"1.5\" />\n              <circle cx=\"12\" cy=\"8\" r=\"1.5\" />\n            </svg>\n          </button>\n        </div>\n\n        <div\n          ref={(node) => {\n            ;(containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n            if (typeof ref === 'function') ref(node)\n            else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n          }}\n          role=\"toolbar\"\n          aria-orientation=\"horizontal\"\n          aria-label={label}\n          className={cn('inline-flex w-full items-center gap-1', className)}\n          onKeyDown={handleKeyDown}\n          {...props}\n        >\n          <AnimatePresence mode=\"popLayout\" initial={false}>\n            {visibleActions.map((action, i) => (\n              <VisibleAction\n                key={action.id}\n                action={action}\n                index={i}\n                visible={true}\n                itemRef={(el) => {\n                  itemRefs.current[i] = el\n                }}\n              />\n            ))}\n          </AnimatePresence>\n\n          {overflowActions.length > 0 && (\n            <OverflowMenu\n              actions={overflowActions}\n              triggerId={triggerId}\n              contentId={contentId}\n              moreLabel={moreLabel}\n              renderMoreTrigger={renderMoreTrigger}\n              triggerTabIndex={rovingIndex === visibleActions.length ? 0 : -1}\n            />\n          )}\n        </div>\n      </AdaptiveActionsContext.Provider>\n    )\n  },\n)\nAdaptiveActions.displayName = 'AdaptiveActions'\n\nexport function AdaptiveActionsPreview() {\n  const actions: ActionItem[] = [\n    {\n      id: 'edit',\n      label: 'Edit',\n      priority: 3,\n      icon: (\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        >\n          <path d=\"M11.5 2.5l2 2-8 8H3.5v-2l8-8z\" />\n        </svg>\n      ),\n      onSelect: () => {},\n    },\n    {\n      id: 'duplicate',\n      label: 'Duplicate',\n      priority: 2,\n      icon: (\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        >\n          <rect x=\"5.5\" y=\"5.5\" width=\"7\" height=\"7\" rx=\"1\" />\n          <path d=\"M3.5 10.5v-7a1 1 0 011-1h7\" />\n        </svg>\n      ),\n      onSelect: () => {},\n    },\n    {\n      id: 'share',\n      label: 'Share',\n      priority: 1,\n      icon: (\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        >\n          <circle cx=\"12\" cy=\"4\" r=\"2\" />\n          <circle cx=\"4\" cy=\"8\" r=\"2\" />\n          <circle cx=\"12\" cy=\"12\" r=\"2\" />\n          <path d=\"M5.8 9l4.4 2M10.2 5L5.8 7\" />\n        </svg>\n      ),\n      onSelect: () => {},\n    },\n    {\n      id: 'archive',\n      label: 'Archive',\n      priority: 0,\n      icon: (\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        >\n          <rect x=\"2\" y=\"3\" width=\"12\" height=\"3\" rx=\"1\" />\n          <path d=\"M3 6v7a1 1 0 001 1h8a1 1 0 001-1V6M6.5 9h3\" />\n        </svg>\n      ),\n      onSelect: () => {},\n    },\n    {\n      id: 'delete',\n      label: 'Delete',\n      destructive: true,\n      priority: 0,\n      icon: (\n        <svg\n          width=\"16\"\n          height=\"16\"\n          viewBox=\"0 0 16 16\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        >\n          <path d=\"M3 5h10M5.5 5V3.5a1 1 0 011-1h3a1 1 0 011 1V5M12 5v7.5a1.5 1.5 0 01-1.5 1.5h-5A1.5 1.5 0 014 12.5V5\" />\n        </svg>\n      ),\n      onSelect: () => {},\n    },\n  ]\n\n  return (\n    <div className=\"flex w-full items-center justify-center p-6\">\n      <div className=\"w-full max-w-sm\">\n        <AdaptiveActions actions={actions} label=\"File actions\" />\n      </div>\n    </div>\n  )\n}\n"
    }
  ],
  "type": "registry:ui"
}
