{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "motion-presets",
  "title": "Motion Presets",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "Shared easings, durations, springs and enter variants for Motion, so every animated component moves with the same rhythm.",
  "dependencies": [
    "motion@^12"
  ],
  "files": [
    {
      "path": "registry/ballmac/lib/motion.ts",
      "content": "// Ballmac UI: Motion presets. https://ui.ballmac.com/components/motion-presets\n// One set of easings, durations and springs shared by every animated Ballmac component.\nimport * as React from \"react\"\nimport { useReducedMotion, type Transition, type Variants } from \"motion/react\"\n\n/** Cubic-bezier easings (match --bm-ease-* in the theme). */\nexport const ease = {\n  out: [0.22, 1, 0.36, 1],\n  inOut: [0.65, 0, 0.35, 1],\n  in: [0.55, 0, 1, 0.45],\n} as const\n\n/** Durations in seconds (match --bm-duration-*). */\nexport const duration = {\n  fast: 0.14,\n  base: 0.22,\n  slow: 0.32,\n  reveal: 0.6,\n} as const\n\n/** Springs for spatial movement. */\nexport const spring = {\n  /** UI controls: quick, no visible overshoot. */\n  snappy: { type: \"spring\", stiffness: 420, damping: 34, mass: 0.8 },\n  /** Cards and panels: soft settle. */\n  gentle: { type: \"spring\", stiffness: 180, damping: 24 },\n  /** Playful accents: a little bounce. */\n  bouncy: { type: \"spring\", stiffness: 300, damping: 16 },\n} satisfies Record<string, Transition>\n\n/** Common enter/exit variants. Pair with `initial=\"hidden\" animate=\"visible\"`. */\nexport const variants = {\n  fadeUp: {\n    hidden: { opacity: 0, y: 10, filter: \"blur(4px)\" },\n    visible: { opacity: 1, y: 0, filter: \"blur(0px)\", transition: { duration: duration.reveal, ease: ease.out } },\n  },\n  fade: {\n    hidden: { opacity: 0 },\n    visible: { opacity: 1, transition: { duration: duration.base, ease: ease.out } },\n  },\n  scaleIn: {\n    hidden: { opacity: 0, scale: 0.96 },\n    visible: { opacity: 1, scale: 1, transition: spring.gentle },\n  },\n} satisfies Record<string, Variants>\n\n/** Stagger children by `step` seconds. */\nexport function stagger(step = 0.06, delayChildren = 0): Transition {\n  return { staggerChildren: step, delayChildren }\n}\n\nconst noopSubscribe = () => () => {}\n\n/**\n * Motion's `useReducedMotion`, made safe for server rendering. Motion reads the media query on the first\n * client render, so a component that renders different markup for reduced motion would not match the\n * server HTML. This returns `false` until hydration has finished, then the visitor's real preference.\n */\nexport function useReducedMotionSafe(): boolean {\n  const reduce = useReducedMotion()\n  const hydrated = React.useSyncExternalStore(noopSubscribe, () => true, () => false)\n  return hydrated && !!reduce\n}\n",
      "type": "registry:lib",
      "target": "@lib/ballmac/motion.ts"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "motion",
      "animation",
      "easing",
      "spring"
    ],
    "version": "1.0.0",
    "updated": "2026-09-28",
    "ai": {
      "summary": "Import ease, duration, spring, variants and stagger from @/lib/ballmac/motion instead of hard-coding animation values.",
      "whenToUse": [
        "Writing a new animated component that should match Ballmac UI",
        "Page or section entrance animations"
      ],
      "whenNotToUse": [
        "CSS-only transitions (use the --bm-ease-* and --bm-duration-* variables)"
      ],
      "composesWith": [],
      "a11y": [],
      "customization": [
        "spring.snappy for controls, spring.gentle for panels, spring.bouncy for accents",
        "variants.fadeUp with stagger() for lists"
      ]
    },
    "examples": [],
    "url": "https://ui.ballmac.com/components/motion-presets"
  },
  "categories": [
    "foundation"
  ],
  "type": "registry:lib"
}