{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notification-16",
  "title": "Update notice",
  "description": "A new version to install now or later.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://ui.ndekocode.dev/r/button.json",
    "https://ui.ndekocode.dev/r/icons.json",
    "https://ui.ndekocode.dev/r/status-orb.json",
    "https://ui.ndekocode.dev/r/theme.json",
    "https://ui.ndekocode.dev/r/use-prefers-reduced-motion.json"
  ],
  "files": [
    {
      "path": "registry/ndeko/components/notification/notification-16.tsx",
      "content": "'use client';\n\nimport { AnimatePresence, motion } from 'motion/react';\nimport { useState } from 'react';\n\nimport { usePrefersReducedMotion } from '@/registry/ndeko/hooks/use-prefers-reduced-motion';\nimport { RefreshCwIcon, XIcon } from '@/registry/ndeko/lib/icons';\nimport { Button } from '@/registry/ndeko/ui/button';\nimport { StatusOrb } from '@/registry/ndeko/ui/status-orb';\n\nimport { surfaceCollapseOf } from './_parts/collapse';\n\nexport default function Notification16() {\n  const [isVisible, setIsVisible] = useState(true);\n  const shouldReduceMotion = usePrefersReducedMotion();\n  const leaveVariants = surfaceCollapseOf(shouldReduceMotion);\n\n  function dismiss() {\n    setIsVisible(false);\n  }\n\n  return (\n    <AnimatePresence initial={false}>\n      {isVisible && (\n        <motion.div\n          key='notification'\n          role='status'\n          className='surface-raised flex w-full max-w-100 items-start gap-3 overflow-hidden rounded-2xl p-4'\n          variants={leaveVariants}\n          initial='hidden'\n          animate='shown'\n          exit='hidden'\n        >\n          <StatusOrb\n            tone='brand'\n            glyph={<RefreshCwIcon strokeWidth={2.25} />}\n          />\n          <div className='flex grow flex-col gap-3 pt-1.5'>\n            <div className='flex flex-col gap-1 text-[13px] leading-5'>\n              <p className='font-medium'>Version 2.4 is ready to install</p>\n              <p className='text-muted-foreground'>\n                This update fixes sync on slow networks and makes search faster.\n              </p>\n            </div>\n            <div className='flex gap-2'>\n              <Button size='sm'>Install</Button>\n              <Button size='sm' variant='ghost' onClick={dismiss}>\n                Later\n              </Button>\n            </div>\n          </div>\n          <Button\n            variant='ghost'\n            size='icon-sm'\n            aria-label='Dismiss notification'\n            className='text-muted-foreground -me-1.5 -mt-1.5'\n            onClick={dismiss}\n          >\n            <XIcon />\n          </Button>\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/notification/notification-16.tsx"
    },
    {
      "path": "registry/ndeko/components/notification/_parts/collapse.ts",
      "content": "import type { Transition, Variants } from 'motion/react';\n\nconst EASE_OUT_STRONG: [number, number, number, number] = [0.23, 1, 0.32, 1];\n\n/**\n * The spring AnimatedSize resizes with. It starts from rest, so the fade leads and the freed space\n * closes after it at the pace the surrounding container follows, instead of snapping shut.\n */\nconst SIZE_SPRING: Transition = { type: 'spring', bounce: 0, duration: 0.32 };\n\nconst ARRIVE: Transition = {\n  ...SIZE_SPRING,\n  opacity: { duration: 0.2, ease: EASE_OUT_STRONG },\n};\n\nconst LEAVE: Transition = {\n  ...SIZE_SPRING,\n  opacity: { duration: 0.12, ease: EASE_OUT_STRONG },\n};\n\nconst ARRIVE_FADE: Transition = { duration: 0.2, ease: EASE_OUT_STRONG };\n\nconst LEAVE_FADE: Transition = { duration: 0.12, ease: EASE_OUT_STRONG };\n\n/** A row whose spacing sits inside it: only its height and opacity change. */\nconst ROW_VARIANTS: Variants = {\n  shown: { height: 'auto', opacity: 1, transition: ARRIVE },\n  hidden: { height: 0, opacity: 0, transition: LEAVE },\n};\n\n/** A padded surface dismissed for good: its padding closes with its height. */\nconst SURFACE_VARIANTS: Variants = {\n  shown: { height: 'auto', opacity: 1, transition: ARRIVE },\n  hidden: {\n    height: 0,\n    opacity: 0,\n    paddingTop: 0,\n    paddingBottom: 0,\n    transition: LEAVE,\n  },\n};\n\nconst FADE_VARIANTS: Variants = {\n  shown: { opacity: 1, transition: ARRIVE_FADE },\n  hidden: { opacity: 0, transition: LEAVE_FADE },\n};\n\nexport function rowCollapseOf(shouldReduceMotion: boolean | null) {\n  if (shouldReduceMotion) {\n    return FADE_VARIANTS;\n  }\n  return ROW_VARIANTS;\n}\n\nexport function surfaceCollapseOf(shouldReduceMotion: boolean | null) {\n  if (shouldReduceMotion) {\n    return FADE_VARIANTS;\n  }\n  return SURFACE_VARIANTS;\n}\n",
      "type": "registry:component",
      "target": "components/notification/_parts/collapse.ts"
    }
  ],
  "categories": [
    "components",
    "notification"
  ],
  "type": "registry:component"
}