@datatechsolutions/ui 3.6.1 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astrlabe/graph-node.js +8 -5
- package/dist/astrlabe/graph-node.mjs +4 -1
- package/dist/astrlabe/index.js +115 -114
- package/dist/astrlabe/index.mjs +7 -6
- package/dist/astrlabe/workflow-canvas.js +7 -6
- package/dist/astrlabe/workflow-canvas.mjs +6 -5
- package/dist/{chunk-3Z66NXEB.mjs → chunk-2OPBUVTQ.mjs} +3 -3
- package/dist/{chunk-3Z66NXEB.mjs.map → chunk-2OPBUVTQ.mjs.map} +1 -1
- package/dist/{chunk-4JDJRGAB.mjs → chunk-34XRH2FX.mjs} +5 -4
- package/dist/chunk-34XRH2FX.mjs.map +1 -0
- package/dist/{chunk-KEWRLEYV.js → chunk-3JZGRXSG.js} +4 -4
- package/dist/{chunk-KEWRLEYV.js.map → chunk-3JZGRXSG.js.map} +1 -1
- package/dist/{chunk-JQYDJ75Q.mjs → chunk-3VYD7QL2.mjs} +3 -3
- package/dist/{chunk-JQYDJ75Q.mjs.map → chunk-3VYD7QL2.mjs.map} +1 -1
- package/dist/{chunk-MRRFDIUQ.mjs → chunk-4JRMXHPU.mjs} +5 -4
- package/dist/chunk-4JRMXHPU.mjs.map +1 -0
- package/dist/{chunk-4OFG6POC.mjs → chunk-5LCWQKGQ.mjs} +207 -1128
- package/dist/chunk-5LCWQKGQ.mjs.map +1 -0
- package/dist/{chunk-W5YCZOXO.js → chunk-7YK4WXHO.js} +79 -78
- package/dist/chunk-7YK4WXHO.js.map +1 -0
- package/dist/{chunk-YOJIPZ72.js → chunk-BBLBSDPN.js} +9 -9
- package/dist/{chunk-YOJIPZ72.js.map → chunk-BBLBSDPN.js.map} +1 -1
- package/dist/chunk-BHOT22QL.js +998 -0
- package/dist/chunk-BHOT22QL.js.map +1 -0
- package/dist/{chunk-MQNXKBFP.mjs → chunk-C4AJWDFB.mjs} +7 -6
- package/dist/chunk-C4AJWDFB.mjs.map +1 -0
- package/dist/{chunk-UOABOFKO.mjs → chunk-CBFK4W4C.mjs} +3 -3
- package/dist/{chunk-UOABOFKO.mjs.map → chunk-CBFK4W4C.mjs.map} +1 -1
- package/dist/{chunk-P5F257N3.js → chunk-CVZXZK2X.js} +35 -34
- package/dist/chunk-CVZXZK2X.js.map +1 -0
- package/dist/{chunk-IHHGT3LP.mjs → chunk-CYAAL3BY.mjs} +6 -5
- package/dist/chunk-CYAAL3BY.mjs.map +1 -0
- package/dist/{chunk-LVK7VXW7.js → chunk-DMPBNWJB.js} +37 -36
- package/dist/chunk-DMPBNWJB.js.map +1 -0
- package/dist/{chunk-ESLKQJQS.mjs → chunk-DXLATMGD.mjs} +6 -5
- package/dist/chunk-DXLATMGD.mjs.map +1 -0
- package/dist/{chunk-P4YYEM4B.js → chunk-EZQ2D47U.js} +7 -10
- package/dist/chunk-EZQ2D47U.js.map +1 -0
- package/dist/{chunk-6ZMTJSQF.js → chunk-FUHNEP3Y.js} +164 -163
- package/dist/chunk-FUHNEP3Y.js.map +1 -0
- package/dist/{chunk-YTE6WCBX.js → chunk-JHN2OUWG.js} +64 -63
- package/dist/chunk-JHN2OUWG.js.map +1 -0
- package/dist/{chunk-AMYQSPQC.js → chunk-JLECJI7S.js} +18 -17
- package/dist/chunk-JLECJI7S.js.map +1 -0
- package/dist/{chunk-DRORQGN2.js → chunk-KMNWPC64.js} +40 -39
- package/dist/chunk-KMNWPC64.js.map +1 -0
- package/dist/{chunk-VUAGVZJM.mjs → chunk-NJ6HH4QP.mjs} +6 -5
- package/dist/chunk-NJ6HH4QP.mjs.map +1 -0
- package/dist/{chunk-OZNTQROP.mjs → chunk-PLTLRL2V.mjs} +7 -10
- package/dist/chunk-PLTLRL2V.mjs.map +1 -0
- package/dist/{chunk-5ZAZ2C7A.mjs → chunk-PMMP76MV.mjs} +7 -6
- package/dist/chunk-PMMP76MV.mjs.map +1 -0
- package/dist/{chunk-NJZIE4EH.js → chunk-QF6WL7XU.js} +6 -5
- package/dist/chunk-QF6WL7XU.js.map +1 -0
- package/dist/{chunk-QRNFTG6A.js → chunk-QGLGQXJE.js} +4 -4
- package/dist/{chunk-QRNFTG6A.js.map → chunk-QGLGQXJE.js.map} +1 -1
- package/dist/{chunk-GCYYGSHU.js → chunk-R4EKPXX3.js} +564 -1525
- package/dist/chunk-R4EKPXX3.js.map +1 -0
- package/dist/{chunk-SQZGQOKU.js → chunk-RWYG7QHP.js} +119 -132
- package/dist/chunk-RWYG7QHP.js.map +1 -0
- package/dist/{chunk-WBEZATIB.js → chunk-RZ3NDH5S.js} +13 -13
- package/dist/{chunk-WBEZATIB.js.map → chunk-RZ3NDH5S.js.map} +1 -1
- package/dist/{chunk-HGWVJ3VB.mjs → chunk-SJVKID3E.mjs} +4 -3
- package/dist/chunk-SJVKID3E.mjs.map +1 -0
- package/dist/{chunk-7LILNZMR.mjs → chunk-TJEZL72T.mjs} +4 -3
- package/dist/chunk-TJEZL72T.mjs.map +1 -0
- package/dist/{chunk-MUOTTGCX.js → chunk-UDYEUTJC.js} +31 -30
- package/dist/chunk-UDYEUTJC.js.map +1 -0
- package/dist/{chunk-UGJZ3M4Q.js → chunk-VDLMWOQM.js} +55 -54
- package/dist/chunk-VDLMWOQM.js.map +1 -0
- package/dist/{chunk-KDFBN2L2.mjs → chunk-VZIUQE7B.mjs} +24 -37
- package/dist/chunk-VZIUQE7B.mjs.map +1 -0
- package/dist/chunk-WR55H7DH.mjs +934 -0
- package/dist/chunk-WR55H7DH.mjs.map +1 -0
- package/dist/{chunk-ZYVDDSAC.mjs → chunk-YRXDETBK.mjs} +6 -6
- package/dist/{chunk-ZYVDDSAC.mjs.map → chunk-YRXDETBK.mjs.map} +1 -1
- package/dist/{chunk-VDLAZR7S.mjs → chunk-ZYRL3WER.mjs} +5 -4
- package/dist/chunk-ZYRL3WER.mjs.map +1 -0
- package/dist/index.js +826 -825
- package/dist/index.mjs +4 -3
- package/dist/platform/admin/index.js +13 -12
- package/dist/platform/admin/index.mjs +7 -6
- package/dist/platform/agents-workspace.js +10 -9
- package/dist/platform/agents-workspace.mjs +9 -8
- package/dist/platform/app-shell.js +6 -5
- package/dist/platform/app-shell.mjs +5 -4
- package/dist/platform/auth/index.js +30 -29
- package/dist/platform/auth/index.mjs +7 -6
- package/dist/platform/billing/index.js +6 -5
- package/dist/platform/billing/index.mjs +5 -4
- package/dist/platform/impersonation/index.js +6 -5
- package/dist/platform/impersonation/index.mjs +5 -4
- package/dist/platform/index.js +87 -93
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.mjs +23 -29
- package/dist/platform/index.mjs.map +1 -1
- package/dist/platform/pages/index.js +210 -209
- package/dist/platform/pages/index.js.map +1 -1
- package/dist/platform/pages/index.mjs +11 -10
- package/dist/platform/pages/index.mjs.map +1 -1
- package/dist/platform/settings/index.js +10 -9
- package/dist/platform/settings/index.mjs +9 -8
- package/dist/platform/workflow-canvas-shell.js +8 -7
- package/dist/platform/workflow-canvas-shell.mjs +7 -6
- package/package.json +1 -1
- package/dist/chunk-4JDJRGAB.mjs.map +0 -1
- package/dist/chunk-4OFG6POC.mjs.map +0 -1
- package/dist/chunk-5ZAZ2C7A.mjs.map +0 -1
- package/dist/chunk-6ZMTJSQF.js.map +0 -1
- package/dist/chunk-7LILNZMR.mjs.map +0 -1
- package/dist/chunk-AMYQSPQC.js.map +0 -1
- package/dist/chunk-DRORQGN2.js.map +0 -1
- package/dist/chunk-ESLKQJQS.mjs.map +0 -1
- package/dist/chunk-GCYYGSHU.js.map +0 -1
- package/dist/chunk-HGWVJ3VB.mjs.map +0 -1
- package/dist/chunk-IHHGT3LP.mjs.map +0 -1
- package/dist/chunk-KDFBN2L2.mjs.map +0 -1
- package/dist/chunk-LVK7VXW7.js.map +0 -1
- package/dist/chunk-MQNXKBFP.mjs.map +0 -1
- package/dist/chunk-MRRFDIUQ.mjs.map +0 -1
- package/dist/chunk-MUOTTGCX.js.map +0 -1
- package/dist/chunk-NJZIE4EH.js.map +0 -1
- package/dist/chunk-OZNTQROP.mjs.map +0 -1
- package/dist/chunk-P4YYEM4B.js.map +0 -1
- package/dist/chunk-P5F257N3.js.map +0 -1
- package/dist/chunk-SQZGQOKU.js.map +0 -1
- package/dist/chunk-UGJZ3M4Q.js.map +0 -1
- package/dist/chunk-VDLAZR7S.mjs.map +0 -1
- package/dist/chunk-VUAGVZJM.mjs.map +0 -1
- package/dist/chunk-W5YCZOXO.js.map +0 -1
- package/dist/chunk-YTE6WCBX.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/motion-tokens.ts","../src/lib/animations.ts","../src/components/link.tsx","../src/components/button-styles.ts","../src/components/button.tsx","../src/components/badge.tsx"],"names":["Link","iosColors","forwardRef","Button","jsx","HeadlessButton","clsx","jsxs","BadgeButton","Headless2"],"mappings":"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","file":"chunk-WR55H7DH.mjs","sourcesContent":["/**\n * Motion tokens — the canonical source for animation timing in the\n * design system. Every component that animates anything reads from\n * here: there are no hard-coded durations or spring stiffness/damping\n * pairs anywhere else in the package.\n *\n * The tokens come in three layers:\n * 1. `duration` (ms) — for CSS transitions + framer-motion `duration`\n * 2. `ease` (cubic-bezier arrays) — for keyframe easing\n * 3. `spring` (typed framer-motion Transition objects) — for spring physics\n *\n * Naming is intent-based, not numeric:\n * - duration: xs / sm / md / lg (micro-feedback → page enter)\n * - ease: standard / emphasized / decelerate / accelerate / ios\n * - spring: snap / smooth / bounce / gentle / sheet\n *\n * These mirror the CSS custom properties in `liquid-glass.css`\n * (`--duration-*`, `--ease-*`), so CSS consumers and JS consumers\n * stay in lockstep. The CSS layer also responds to\n * `prefers-reduced-motion`, collapsing durations to 0ms; the JS\n * helpers in `animations.ts` do the equivalent for spring tokens.\n *\n * If a component needs a duration the scale doesn't have, add a new\n * token here first — don't inline.\n */\n\nimport type { Transition } from 'framer-motion'\n\n// ════════════════════════════════════════════════════════════════════\n// Duration scale (milliseconds)\n// ════════════════════════════════════════════════════════════════════\n\nexport const duration = {\n /** 90ms — micro feedback: toggle thumb, hover tint, focus ring */\n xs: 90,\n /** 150ms — button press, popover open, chip toggle */\n sm: 150,\n /** 240ms — card hover, drawer slide, tab switch */\n md: 240,\n /** 360ms — page transitions, modal enter/exit */\n lg: 360,\n} as const\n\nexport type DurationToken = keyof typeof duration\n\n/** Same scale, expressed in seconds — for framer-motion's `duration` prop. */\nexport const durationSeconds = {\n xs: duration.xs / 1000,\n sm: duration.sm / 1000,\n md: duration.md / 1000,\n lg: duration.lg / 1000,\n} as const\n\n// ════════════════════════════════════════════════════════════════════\n// Easing curves (cubic-bezier arrays for framer-motion / CSS strings)\n// ════════════════════════════════════════════════════════════════════\n\nexport const ease = {\n /** Default product curve — symmetric, balanced */\n standard: [0.4, 0, 0.2, 1] as const,\n /** Entering elements — slow start, fast finish */\n emphasized: [0.2, 0, 0, 1] as const,\n /** Arrivals — fast in, slow settle */\n decelerate: [0, 0, 0.2, 1] as const,\n /** Departures — fast out, sharp end */\n accelerate: [0.4, 0, 1, 1] as const,\n /** iOS HIG-canonical curve — slightly slower decay than `standard` */\n ios: [0.25, 0.46, 0.45, 0.94] as const,\n} as const\n\nexport type EaseToken = keyof typeof ease\n\n/** CSS string form (`cubic-bezier(...)`). */\nexport const easeCss: Record<EaseToken, string> = {\n standard: `cubic-bezier(${ease.standard.join(', ')})`,\n emphasized: `cubic-bezier(${ease.emphasized.join(', ')})`,\n decelerate: `cubic-bezier(${ease.decelerate.join(', ')})`,\n accelerate: `cubic-bezier(${ease.accelerate.join(', ')})`,\n ios: `cubic-bezier(${ease.ios.join(', ')})`,\n}\n\n// ════════════════════════════════════════════════════════════════════\n// Spring presets (framer-motion Transition objects)\n// ════════════════════════════════════════════════════════════════════\n\nexport const spring = {\n /** Snap — fast, no overshoot. Buttons, micro-interactions. */\n snap: { type: 'spring', stiffness: 500, damping: 38 } as Transition,\n /** Smooth — balanced, no overshoot. Default for cards/transitions. */\n smooth: { type: 'spring', stiffness: 300, damping: 30 } as Transition,\n /** Bounce — playful overshoot. Icons, success confirmations. */\n bounce: { type: 'spring', stiffness: 400, damping: 22 } as Transition,\n /** Gentle — soft and slow. Modals, large surface entry. */\n gentle: { type: 'spring', stiffness: 200, damping: 22 } as Transition,\n /** Sheet — iOS sheet presentation (with mass). Drawers. */\n sheet: { type: 'spring', stiffness: 350, damping: 30, mass: 0.8 } as Transition,\n} as const\n\nexport type SpringToken = keyof typeof spring\n\n// ════════════════════════════════════════════════════════════════════\n// JSON-shape export\n// ════════════════════════════════════════════════════════════════════\n\n/** Full token tree as a single JSON-shape object — for design tool\n * syncs, doc tables, and Tailwind plugin consumption. */\nexport const motionTokens = {\n duration,\n durationSeconds,\n ease,\n easeCss,\n spring,\n} as const\n\nexport type MotionTokens = typeof motionTokens\n","/**\n * iOS-style animation presets for Framer Motion\n * Based on Apple Human Interface Guidelines\n * Includes reduced motion support for accessibility\n *\n * NOTE: New code should consume tokens from `./motion-tokens` directly\n * (`spring.snap`, `duration.md`, `ease.standard`). The exports in this\n * file are kept for back-compatibility — they re-export and adapt the\n * canonical token shape so existing call sites don't break.\n */\n\nimport type { Transition, Variants } from 'framer-motion'\nimport { spring as springTokens, duration as durationTokens, ease as easeTokens } from './motion-tokens'\n\n// Re-export canonical tokens so callers can do\n// `import { spring, duration } from '@datatechsolutions/ui'` directly.\nexport { duration, durationSeconds, ease, easeCss, spring, motionTokens } from './motion-tokens'\nexport type { DurationToken, EaseToken, SpringToken, MotionTokens } from './motion-tokens'\n\n// ============================================================================\n// Reduced Motion Detection\n// ============================================================================\n\n/**\n * Check if user prefers reduced motion\n * Use this to conditionally disable animations\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\n/**\n * Get a transition that respects reduced motion preference\n */\nexport function getTransition(transition: Transition): Transition {\n if (prefersReducedMotion()) {\n return { duration: 0 }\n }\n return transition\n}\n\n/**\n * Get variants that respect reduced motion preference\n */\nexport function getVariants(variants: Variants): Variants {\n if (prefersReducedMotion()) {\n // Return variants with instant transitions\n const reducedVariants: Variants = {}\n for (const key in variants) {\n reducedVariants[key] = {\n ...variants[key],\n transition: { duration: 0 },\n }\n }\n return reducedVariants\n }\n return variants\n}\n\n// ============================================================================\n// Spring Presets\n// ============================================================================\n\n/**\n * Legacy spring presets — kept for back-compat with existing call sites.\n * Maps onto the canonical `spring.*` tokens from motion-tokens.ts.\n * New code should import from `motion-tokens` directly.\n */\nexport const springPresets = {\n default: springTokens.smooth,\n bouncy: springTokens.bounce,\n stiff: springTokens.snap,\n gentle: springTokens.gentle,\n sheet: springTokens.sheet,\n /** Quick spring - very fast, good for micro-interactions */\n quick: { type: 'spring', stiffness: 600, damping: 40 } as Transition,\n}\n\n/** Spring presets with reduced motion fallback (instant) */\nexport const springPresetsReduced = {\n default: prefersReducedMotion() ? { duration: 0 } : springPresets.default,\n bouncy: prefersReducedMotion() ? { duration: 0 } : springPresets.bouncy,\n stiff: prefersReducedMotion() ? { duration: 0 } : springPresets.stiff,\n gentle: prefersReducedMotion() ? { duration: 0 } : springPresets.gentle,\n sheet: prefersReducedMotion() ? { duration: 0 } : springPresets.sheet,\n quick: prefersReducedMotion() ? { duration: 0 } : springPresets.quick,\n}\n\n// ============================================================================\n// Button Animations\n// ============================================================================\n\nexport const buttonPress: Variants = {\n idle: { scale: 1 },\n pressed: { scale: 0.97 },\n hover: { scale: 1.02 },\n}\n\nexport const buttonTap = {\n scale: 0.97,\n transition: springPresets.stiff,\n}\n\n/** Reduced motion version - no scale animation */\nexport const buttonPressReduced: Variants = {\n idle: { opacity: 1 },\n pressed: { opacity: 0.7 },\n hover: { opacity: 0.9 },\n}\n\n// ============================================================================\n// Card Animations\n// ============================================================================\n\nexport const cardHover: Variants = {\n idle: {\n y: 0,\n boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)'\n },\n hover: {\n y: -4,\n boxShadow: '0 20px 25px -5px rgb(0 0 0 / 0.1)'\n },\n}\n\nexport const cardPress: Variants = {\n idle: { scale: 1 },\n pressed: { scale: 0.98 },\n}\n\n/** Reduced motion version - opacity only */\nexport const cardHoverReduced: Variants = {\n idle: { opacity: 1 },\n hover: { opacity: 0.95 },\n}\n\n// ============================================================================\n// Modal/Sheet Animations\n// ============================================================================\n\nexport const slideUp: Variants = {\n hidden: { y: '100%', opacity: 0 },\n visible: { y: 0, opacity: 1 },\n exit: { y: '100%', opacity: 0 },\n}\n\nexport const slideRight: Variants = {\n hidden: { x: '100%', opacity: 0 },\n visible: { x: 0, opacity: 1 },\n exit: { x: '100%', opacity: 0 },\n}\n\nexport const slideDown: Variants = {\n hidden: { y: '-100%', opacity: 0 },\n visible: { y: 0, opacity: 1 },\n exit: { y: '-100%', opacity: 0 },\n}\n\nexport const fadeScale: Variants = {\n hidden: { opacity: 0, scale: 0.95 },\n visible: { opacity: 1, scale: 1 },\n exit: { opacity: 0, scale: 0.95 },\n}\n\n/** Reduced motion - fade only, no movement */\nexport const fadeOnly: Variants = {\n hidden: { opacity: 0 },\n visible: { opacity: 1 },\n exit: { opacity: 0 },\n}\n\n// ============================================================================\n// Notification Animations\n// ============================================================================\n\nexport const notificationBanner: Variants = {\n hidden: { y: -100, opacity: 0, scale: 0.9 },\n visible: {\n y: 0,\n opacity: 1,\n scale: 1,\n transition: springPresets.bouncy,\n },\n exit: {\n y: -100,\n opacity: 0,\n scale: 0.9,\n transition: { duration: 0.2 },\n },\n}\n\n/** Reduced motion version */\nexport const notificationBannerReduced: Variants = {\n hidden: { opacity: 0 },\n visible: { opacity: 1, transition: { duration: 0.15 } },\n exit: { opacity: 0, transition: { duration: 0.1 } },\n}\n\n// ============================================================================\n// List Item Animations\n// ============================================================================\n\nexport const listItem: Variants = {\n hidden: { opacity: 0, x: -20 },\n visible: (i: number) => ({\n opacity: 1,\n x: 0,\n transition: {\n delay: i * 0.05,\n ...springPresets.default,\n },\n }),\n}\n\nexport const staggerContainer: Variants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: 0.05,\n },\n },\n}\n\n/** Reduced motion - no stagger, just fade */\nexport const listItemReduced: Variants = {\n hidden: { opacity: 0 },\n visible: { opacity: 1, transition: { duration: 0.15 } },\n}\n\n// ============================================================================\n// Swipe Actions\n// ============================================================================\n\nexport const swipeActionThreshold = 80 // pixels\n\nexport const swipeConstraints = {\n left: -120,\n right: 0,\n}\n\n// ============================================================================\n// Page Control (Pagination Dots)\n// ============================================================================\n\nexport const pageControlDot: Variants = {\n inactive: { width: 8, backgroundColor: 'rgb(156 163 175)' },\n active: { width: 24, backgroundColor: 'rgb(59 130 246)' },\n}\n\n// ============================================================================\n// iOS System Colors\n// ============================================================================\n\nexport const iosColors = {\n // Primary colors\n blue: '#007AFF',\n green: '#34C759',\n red: '#FF3B30',\n orange: '#FF9500',\n yellow: '#FFCC00',\n purple: '#AF52DE',\n pink: '#FF2D55',\n teal: '#5AC8FA',\n indigo: '#5856D6',\n mint: '#00C7BE',\n cyan: '#32ADE6',\n brown: '#A2845E',\n\n // Grays\n gray: '#8E8E93',\n gray2: '#AEAEB2',\n gray3: '#C7C7CC',\n gray4: '#D1D1D6',\n gray5: '#E5E5EA',\n gray6: '#F2F2F7',\n\n // Dark mode variants\n dark: {\n blue: '#0A84FF',\n green: '#30D158',\n red: '#FF453A',\n orange: '#FF9F0A',\n yellow: '#FFD60A',\n purple: '#BF5AF2',\n pink: '#FF375F',\n teal: '#64D2FF',\n indigo: '#5E5CE6',\n mint: '#66D4CF',\n cyan: '#5AC8FA',\n brown: '#AC8E68',\n },\n}\n\n// ============================================================================\n// Duration Presets\n// ============================================================================\n\n/**\n * Legacy duration presets (seconds — for framer-motion). Mapped onto\n * the canonical `duration.*` tokens (ms) divided by 1000.\n */\nexport const durations = {\n instant: 0,\n fast: durationTokens.sm / 1000,\n normal: durationTokens.md / 1000,\n slow: durationTokens.lg / 1000,\n verySlow: 0.5,\n}\n\n/** Duration presets with reduced motion fallback */\nexport const durationsReduced = {\n instant: 0,\n fast: prefersReducedMotion() ? 0 : 0.15,\n normal: prefersReducedMotion() ? 0 : 0.25,\n slow: prefersReducedMotion() ? 0 : 0.35,\n verySlow: prefersReducedMotion() ? 0 : 0.5,\n}\n\n// ============================================================================\n// Easing Presets\n// ============================================================================\n\n/**\n * Legacy easing presets — kept for back-compat. New code uses `ease.*`\n * from motion-tokens. `default` here is preserved as a historical curve;\n * the canonical equivalent is `ease.standard`.\n */\nexport const easings = {\n default: [0.25, 0.1, 0.25, 1],\n out: easeTokens.decelerate,\n in: easeTokens.accelerate,\n inOut: easeTokens.standard,\n ios: easeTokens.ios,\n}\n\n// ============================================================================\n// Utility: Create motion-safe animation props\n// ============================================================================\n\n/**\n * Creates animation props that respect reduced motion preference\n */\nexport function createMotionProps<T extends object>(\n animatedProps: T,\n reducedProps: Partial<T> = {}\n): T {\n if (prefersReducedMotion()) {\n return { ...animatedProps, ...reducedProps, transition: { duration: 0 } }\n }\n return animatedProps\n}\n","import * as Headless from '@headlessui/react'\nimport React, { forwardRef } from 'react'\nimport { useLink } from '@ui/lib/router-context'\n\nexport type LinkProps = {\n href: string\n children?: React.ReactNode\n} & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>\n\nexport const Link = forwardRef(function Link(\n props: LinkProps,\n ref: React.ForwardedRef<HTMLAnchorElement>\n) {\n const RouterLink = useLink()\n return (\n <Headless.DataInteractive>\n <RouterLink {...props} ref={ref as React.Ref<HTMLAnchorElement>} />\n </Headless.DataInteractive>\n )\n})\n","/**\n * Button Styles Module\n * ====================\n *\n * Centralized style definitions for all button variants.\n * Extracted from button.tsx for better maintainability.\n */\n\n// iOS System Colors for buttons\nexport const iosColors = {\n // Glassy iOS blue — neutral glass at rest, fills blue on hover\n 'ios-glass-blue': [\n 'liquid-button-primary text-slate-900 [--btn-bg:transparent] [--btn-border:transparent] [--btn-hover-overlay:transparent]',\n 'dark:text-white dark:[--btn-bg:transparent] dark:[--btn-border:transparent]',\n '[--btn-icon:var(--color-slate-600)] dark:[--btn-icon:var(--color-white)]/70',\n ],\n // Glassy iOS red — neutral glass at rest, fills red on hover\n 'ios-glass-red': [\n 'liquid-button liquid-button-red text-slate-900 [--btn-bg:transparent] [--btn-border:transparent] [--btn-hover-overlay:transparent]',\n 'dark:text-white dark:[--btn-bg:transparent] dark:[--btn-border:transparent]',\n '[--btn-icon:var(--color-slate-600)] dark:[--btn-icon:var(--color-white)]/70',\n ],\n // Glassy iOS green — neutral glass at rest, fills green on hover\n 'ios-glass-green': [\n 'liquid-button liquid-button-green text-slate-900 [--btn-bg:transparent] [--btn-border:transparent] [--btn-hover-overlay:transparent]',\n 'dark:text-white dark:[--btn-bg:transparent] dark:[--btn-border:transparent]',\n '[--btn-icon:var(--color-slate-600)] dark:[--btn-icon:var(--color-white)]/70',\n ],\n // Primary iOS blue\n 'ios-blue': [\n 'text-white [--btn-bg:#007AFF] [--btn-border:#0066DD] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#0A84FF] dark:[--btn-border:#007AFF]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n // Destructive iOS red\n 'ios-red': [\n 'text-white [--btn-bg:#FF3B30] [--btn-border:#E6352B] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#FF453A] dark:[--btn-border:#FF3B30]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n // iOS green (success/confirm)\n 'ios-green': [\n 'text-white [--btn-bg:#34C759] [--btn-border:#2DB350] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#30D158] dark:[--btn-border:#34C759]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n // iOS orange (warning)\n 'ios-orange': [\n 'text-white [--btn-bg:#FF9500] [--btn-border:#E68600] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#FF9F0A] dark:[--btn-border:#FF9500]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n // iOS purple\n 'ios-purple': [\n 'text-white [--btn-bg:#AF52DE] [--btn-border:#9B48C7] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#BF5AF2] dark:[--btn-border:#AF52DE]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n // iOS teal\n 'ios-teal': [\n 'text-white [--btn-bg:#5AC8FA] [--btn-border:#4AB8E8] [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-bg:#64D2FF] dark:[--btn-border:#5AC8FA]',\n '[--btn-icon:var(--color-white)]/80',\n ],\n}\n\n// Size presets\nexport const sizeStyles = {\n xs: 'px-2 py-1 text-xs rounded-md',\n sm: 'px-3 py-1.5 text-sm rounded-lg',\n md: '', // Default size from base styles\n lg: 'px-5 py-3 text-base rounded-xl',\n xl: 'px-6 py-4 text-lg rounded-xl',\n}\n\n// Pill shape modifier\nexport const pillStyles = 'rounded-full'\n\nexport const styles = {\n base: [\n // Base\n 'relative isolate inline-flex items-center justify-center gap-x-2 rounded-lg border text-base/6 font-semibold',\n // Sizing\n 'px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/6',\n // Focus\n 'focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500',\n // Disabled\n 'data-disabled:opacity-50',\n // Icon\n '*:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:my-0.5 *:data-[slot=icon]:size-5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:self-center *:data-[slot=icon]:text-(--btn-icon) sm:*:data-[slot=icon]:my-1 sm:*:data-[slot=icon]:size-4 forced-colors:[--btn-icon:ButtonText] forced-colors:data-hover:[--btn-icon:ButtonText]',\n ],\n solid: [\n // Optical border, implemented as the button background to avoid corner artifacts\n 'border-transparent bg-(--btn-border)',\n // Dark mode: border is rendered on `after` so background is set to button background\n 'dark:bg-(--btn-bg)',\n // Button background, implemented as foreground layer to stack on top of pseudo-border layer\n 'before:absolute before:inset-0 before:-z-10 before:rounded-[calc(var(--radius-lg)-1px)] before:bg-(--btn-bg)',\n // Drop shadow, applied to the inset `before` layer so it blends with the border\n 'before:shadow-xs',\n // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo\n 'dark:before:hidden',\n // Dark mode: Subtle white outline is applied using a border\n 'dark:border-white/5',\n // Shim/overlay, inset to match button foreground and used for hover state + highlight shadow\n 'after:absolute after:inset-0 after:-z-10 after:rounded-[calc(var(--radius-lg)-1px)]',\n // Inner highlight shadow\n 'after:shadow-[inset_0_1px_--theme(--color-white/15%)]',\n // White overlay on hover\n 'data-active:after:bg-(--btn-hover-overlay) data-hover:after:bg-(--btn-hover-overlay)',\n // Dark mode: `after` layer expands to cover entire button\n 'dark:after:-inset-px dark:after:rounded-lg',\n // Disabled\n 'data-disabled:before:shadow-none data-disabled:after:shadow-none',\n ],\n outline: [\n // Liquid glass secondary button\n 'liquid-button text-slate-900 !border-white/55',\n // Dark mode\n 'dark:text-white dark:!border-white/18',\n // Icon\n '[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]',\n ],\n plain: [\n // Base\n 'border-transparent text-zinc-950 data-active:bg-zinc-950/5 data-hover:bg-zinc-950/5',\n // Dark mode\n 'dark:text-white dark:data-active:bg-white/10 dark:data-hover:bg-white/10',\n // Icon\n '[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]',\n ],\n gradient: [\n // Same crystal-illuminated mechanic as ios-glass-blue/red/green:\n // neutral glass at rest, fills with translucent indigo→purple\n // gradient on hover. The actual rest/hover styling — including\n // the text-color flip from slate-900 → white — lives in the\n // `.liquid-button-gradient` CSS class in liquid-glass.css so the\n // whole transition is keyed off `:hover` (works without JS).\n 'liquid-button-gradient border-transparent',\n // Disabled\n 'data-disabled:opacity-50 data-disabled:saturate-50',\n // Icon tint flips with text via inherit (currentColor)\n '[--btn-icon:currentColor]',\n ],\n colors: {\n 'dark/zinc': [\n 'text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:text-white dark:[--btn-bg:var(--color-zinc-600)] dark:[--btn-hover-overlay:var(--color-white)]/5',\n '[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]',\n ],\n light: [\n 'text-zinc-950 [--btn-bg:white] [--btn-border:var(--color-zinc-950)]/10 [--btn-hover-overlay:var(--color-zinc-950)]/2.5 data-active:[--btn-border:var(--color-zinc-950)]/15 data-hover:[--btn-border:var(--color-zinc-950)]/15',\n 'dark:text-white dark:[--btn-hover-overlay:var(--color-white)]/5 dark:[--btn-bg:var(--color-zinc-800)]',\n '[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]',\n ],\n 'dark/white': [\n 'text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:text-zinc-950 dark:[--btn-bg:white] dark:[--btn-hover-overlay:var(--color-zinc-950)]/5',\n '[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]',\n ],\n dark: [\n 'text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10',\n 'dark:[--btn-hover-overlay:var(--color-white)]/5 dark:[--btn-bg:var(--color-zinc-800)]',\n '[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]',\n ],\n white: [\n 'text-zinc-950 [--btn-bg:white] [--btn-border:var(--color-zinc-950)]/10 [--btn-hover-overlay:var(--color-zinc-950)]/2.5 data-active:[--btn-border:var(--color-zinc-950)]/15 data-hover:[--btn-border:var(--color-zinc-950)]/15',\n 'dark:[--btn-hover-overlay:var(--color-zinc-950)]/5',\n '[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-500)] data-hover:[--btn-icon:var(--color-zinc-500)]',\n ],\n zinc: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-zinc-600)] [--btn-border:var(--color-zinc-700)]/90',\n 'dark:[--btn-hover-overlay:var(--color-white)]/5',\n '[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]',\n ],\n indigo: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-indigo-500)] [--btn-border:var(--color-indigo-600)]/90',\n '[--btn-icon:var(--color-indigo-300)] data-active:[--btn-icon:var(--color-indigo-200)] data-hover:[--btn-icon:var(--color-indigo-200)]',\n ],\n cyan: [\n 'text-cyan-950 [--btn-bg:var(--color-cyan-300)] [--btn-border:var(--color-cyan-400)]/80 [--btn-hover-overlay:var(--color-white)]/25',\n '[--btn-icon:var(--color-cyan-500)]',\n ],\n red: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-red-600)] [--btn-border:var(--color-red-700)]/90',\n '[--btn-icon:var(--color-red-300)] data-active:[--btn-icon:var(--color-red-200)] data-hover:[--btn-icon:var(--color-red-200)]',\n ],\n orange: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-orange-500)] [--btn-border:var(--color-orange-600)]/90',\n '[--btn-icon:var(--color-orange-300)] data-active:[--btn-icon:var(--color-orange-200)] data-hover:[--btn-icon:var(--color-orange-200)]',\n ],\n amber: [\n 'text-amber-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-amber-400)] [--btn-border:var(--color-amber-500)]/80',\n '[--btn-icon:var(--color-amber-600)]',\n ],\n yellow: [\n 'text-yellow-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-yellow-300)] [--btn-border:var(--color-yellow-400)]/80',\n '[--btn-icon:var(--color-yellow-600)] data-active:[--btn-icon:var(--color-yellow-700)] data-hover:[--btn-icon:var(--color-yellow-700)]',\n ],\n lime: [\n 'text-lime-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-lime-300)] [--btn-border:var(--color-lime-400)]/80',\n '[--btn-icon:var(--color-lime-600)] data-active:[--btn-icon:var(--color-lime-700)] data-hover:[--btn-icon:var(--color-lime-700)]',\n ],\n green: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-green-600)] [--btn-border:var(--color-green-700)]/90',\n '[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80',\n ],\n emerald: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-emerald-600)] [--btn-border:var(--color-emerald-700)]/90',\n '[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80',\n ],\n teal: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-teal-600)] [--btn-border:var(--color-teal-700)]/90',\n '[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80',\n ],\n sky: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-sky-500)] [--btn-border:var(--color-sky-600)]/80',\n '[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80',\n ],\n blue: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-blue-600)] [--btn-border:var(--color-blue-700)]/90',\n '[--btn-icon:var(--color-blue-400)] data-active:[--btn-icon:var(--color-blue-300)] data-hover:[--btn-icon:var(--color-blue-300)]',\n ],\n violet: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-violet-500)] [--btn-border:var(--color-violet-600)]/90',\n '[--btn-icon:var(--color-violet-300)] data-active:[--btn-icon:var(--color-violet-200)] data-hover:[--btn-icon:var(--color-violet-200)]',\n ],\n purple: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-purple-500)] [--btn-border:var(--color-purple-600)]/90',\n '[--btn-icon:var(--color-purple-300)] data-active:[--btn-icon:var(--color-purple-200)] data-hover:[--btn-icon:var(--color-purple-200)]',\n ],\n fuchsia: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-fuchsia-500)] [--btn-border:var(--color-fuchsia-600)]/90',\n '[--btn-icon:var(--color-fuchsia-300)] data-active:[--btn-icon:var(--color-fuchsia-200)] data-hover:[--btn-icon:var(--color-fuchsia-200)]',\n ],\n pink: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-pink-500)] [--btn-border:var(--color-pink-600)]/90',\n '[--btn-icon:var(--color-pink-300)] data-active:[--btn-icon:var(--color-pink-200)] data-hover:[--btn-icon:var(--color-pink-200)]',\n ],\n rose: [\n 'text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-rose-500)] [--btn-border:var(--color-rose-600)]/90',\n '[--btn-icon:var(--color-rose-300)] data-active:[--btn-icon:var(--color-rose-200)] data-hover:[--btn-icon:var(--color-rose-200)]',\n ],\n },\n}\n\n// FAB-specific styles\nexport const fabSizes = {\n sm: 'h-12 w-12',\n md: 'h-14 w-14',\n lg: 'h-16 w-16',\n}\n\nexport const fabIconSizes = {\n sm: 'h-5 w-5',\n md: 'h-6 w-6',\n lg: 'h-7 w-7',\n}\n\nexport const fabPositions = {\n 'bottom-right': 'fixed bottom-6 right-6',\n 'bottom-left': 'fixed bottom-6 left-6',\n 'bottom-center': 'fixed bottom-6 left-1/2 -translate-x-1/2',\n}\n\n// FAB colors as crystal-illuminated glass — translucent tint over the\n// surface, inner highlight on the top edge, tinted drop shadow.\n// Hover bumps opacity + glow. Matches the rest of the button family.\nexport const fabColors = {\n 'ios-blue':\n 'text-white bg-[#007AFF]/85 dark:bg-[#0A84FF]/80 backdrop-blur-xl ' +\n 'border border-white/30 dark:border-white/15 ' +\n 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.5),0_12px_32px_-8px_rgba(0,122,255,0.5)] ' +\n 'hover:bg-[#007AFF] dark:hover:bg-[#0A84FF] ' +\n 'hover:shadow-[inset_0_1px_2px_rgba(255,255,255,0.55),0_16px_40px_-8px_rgba(0,122,255,0.65),0_0_24px_-4px_rgba(0,122,255,0.4)]',\n 'ios-green':\n 'text-white bg-[#34C759]/85 dark:bg-[#30D158]/80 backdrop-blur-xl ' +\n 'border border-white/30 dark:border-white/15 ' +\n 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.5),0_12px_32px_-8px_rgba(52,199,89,0.5)] ' +\n 'hover:bg-[#34C759] dark:hover:bg-[#30D158] ' +\n 'hover:shadow-[inset_0_1px_2px_rgba(255,255,255,0.55),0_16px_40px_-8px_rgba(52,199,89,0.65),0_0_24px_-4px_rgba(52,199,89,0.4)]',\n 'ios-red':\n 'text-white bg-[#FF3B30]/85 dark:bg-[#FF453A]/80 backdrop-blur-xl ' +\n 'border border-white/30 dark:border-white/15 ' +\n 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.5),0_12px_32px_-8px_rgba(255,59,48,0.5)] ' +\n 'hover:bg-[#FF3B30] dark:hover:bg-[#FF453A] ' +\n 'hover:shadow-[inset_0_1px_2px_rgba(255,255,255,0.55),0_16px_40px_-8px_rgba(255,59,48,0.65),0_0_24px_-4px_rgba(255,59,48,0.4)]',\n 'ios-purple':\n 'text-white bg-[#AF52DE]/85 dark:bg-[#BF5AF2]/80 backdrop-blur-xl ' +\n 'border border-white/30 dark:border-white/15 ' +\n 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.5),0_12px_32px_-8px_rgba(175,82,222,0.5)] ' +\n 'hover:bg-[#AF52DE] dark:hover:bg-[#BF5AF2] ' +\n 'hover:shadow-[inset_0_1px_2px_rgba(255,255,255,0.55),0_16px_40px_-8px_rgba(175,82,222,0.65),0_0_24px_-4px_rgba(175,82,222,0.4)]',\n 'ios-orange':\n 'text-white bg-[#FF9500]/85 dark:bg-[#FF9F0A]/80 backdrop-blur-xl ' +\n 'border border-white/30 dark:border-white/15 ' +\n 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.5),0_12px_32px_-8px_rgba(255,149,0,0.5)] ' +\n 'hover:bg-[#FF9500] dark:hover:bg-[#FF9F0A] ' +\n 'hover:shadow-[inset_0_1px_2px_rgba(255,255,255,0.55),0_16px_40px_-8px_rgba(255,149,0,0.65),0_0_24px_-4px_rgba(255,149,0,0.4)]',\n}\n\n// IconButton-specific styles\nexport const iconButtonSizes = {\n sm: 'h-8 w-8',\n md: 'h-10 w-10',\n lg: 'h-12 w-12',\n}\n\nexport const iconSizes = {\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-6 w-6',\n}\n\n// Type exports\nexport type ColorType = keyof typeof styles.colors | keyof typeof iosColors\nexport type SizeType = keyof typeof sizeStyles\nexport type FABColorType = keyof typeof fabColors\nexport type FABPositionType = keyof typeof fabPositions\nexport type FABSizeType = keyof typeof fabSizes\nexport type IconButtonSizeType = keyof typeof iconButtonSizes\n","import { Button as HeadlessButton, type ButtonProps as HeadlessButtonProps } from '@headlessui/react'\nimport clsx from 'clsx'\nimport React, { forwardRef } from 'react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { Link } from '@ui/components/link'\nimport { triggerHaptic } from '@ui/hooks/use-haptic'\nimport { springPresets, getTransition } from '@ui/lib/animations'\nimport {\n iosColors,\n sizeStyles,\n pillStyles,\n styles,\n fabSizes,\n fabIconSizes,\n fabPositions,\n fabColors,\n iconButtonSizes,\n iconSizes,\n type ColorType,\n type SizeType,\n type FABColorType,\n type FABPositionType,\n type FABSizeType,\n type IconButtonSizeType,\n} from '@ui/components/button-styles'\n\ntype ButtonProps = (\n | { color?: ColorType; outline?: never; plain?: never; gradient?: never }\n | { color?: never; outline: true; plain?: never; gradient?: never }\n | { color?: never; outline?: never; plain: true; gradient?: never }\n | { color?: never; outline?: never; plain?: never; gradient: true }\n) & {\n className?: string\n children: React.ReactNode\n /** Make button pill-shaped (fully rounded) */\n pill?: boolean\n /** Button size */\n size?: SizeType\n /** Show loading spinner */\n loading?: boolean\n /** Loading text (optional) */\n loadingText?: string\n /** Full width button */\n fullWidth?: boolean\n /** Destructive action (uses iOS red) */\n destructive?: boolean\n} & (\n | ({ href?: never } & Omit<HeadlessButtonProps, 'as' | 'className'>)\n | ({ href: string } & Omit<React.ComponentPropsWithoutRef<typeof Link>, 'className'>)\n )\n\nexport const Button = forwardRef(function Button(\n {\n color,\n outline,\n plain,\n gradient,\n className,\n children,\n pill,\n size = 'md',\n loading,\n loadingText,\n fullWidth,\n destructive,\n disabled,\n ...props\n }: ButtonProps & { disabled?: boolean },\n ref: React.ForwardedRef<HTMLElement>\n) {\n // Determine final color - destructive overrides color\n const finalColor = destructive ? 'ios-red' : color\n\n // Check if using iOS color\n const isIosColor = finalColor && finalColor in iosColors\n const colorStyles = isIosColor\n ? iosColors[finalColor as keyof typeof iosColors]\n : styles.colors[finalColor as keyof typeof styles.colors] ?? styles.colors['dark/zinc']\n\n let classes = clsx(\n className,\n styles.base,\n gradient ? styles.gradient : outline ? styles.outline : plain ? styles.plain : clsx(styles.solid, colorStyles),\n pill && pillStyles,\n size !== 'md' && sizeStyles[size],\n fullWidth && 'w-full',\n loading && 'pointer-events-none'\n )\n\n const handleTapStart = () => {\n if (!loading && !disabled) {\n triggerHaptic(destructive ? 'medium' : 'light')\n }\n }\n\n const isDisabled = disabled || loading\n\n const buttonContent = (\n <>\n <AnimatePresence mode=\"wait\">\n {loading && (\n <motion.span\n initial={{ opacity: 0, width: 0 }}\n animate={{ opacity: 1, width: 'auto' }}\n exit={{ opacity: 0, width: 0 }}\n transition={getTransition(springPresets.stiff)}\n className=\"inline-flex items-center\"\n >\n <LoadingSpinner className=\"mr-2\" />\n </motion.span>\n )}\n </AnimatePresence>\n <span className={clsx('inline-flex items-center gap-x-2', loading && 'opacity-70')}>\n {loading && loadingText ? loadingText : children}\n </span>\n </>\n )\n\n const linkProps = props as Omit<React.ComponentPropsWithoutRef<typeof Link>, 'className'>\n const buttonProps = props as Omit<HeadlessButtonProps, 'className'>\n\n const isLink = typeof props.href === 'string'\n\n return isLink ? (\n <motion.div\n whileTap={!isDisabled ? { scale: 0.97 } : undefined}\n transition={getTransition(springPresets.stiff)}\n onTapStart={handleTapStart}\n className={clsx('inline-flex', fullWidth && 'w-full')}\n >\n <Link\n {...linkProps}\n className={classes}\n ref={ref as React.ForwardedRef<HTMLAnchorElement>}\n >\n <TouchTarget>{buttonContent}</TouchTarget>\n </Link>\n </motion.div>\n ) : (\n <motion.div\n whileTap={!isDisabled ? { scale: 0.97 } : undefined}\n transition={getTransition(springPresets.stiff)}\n onTapStart={handleTapStart}\n className={clsx('inline-flex', fullWidth && 'w-full')}\n >\n <HeadlessButton\n {...buttonProps}\n disabled={isDisabled}\n className={clsx(classes, 'cursor-default')}\n ref={ref}\n >\n <TouchTarget>{buttonContent}</TouchTarget>\n </HeadlessButton>\n </motion.div>\n )\n})\n\n/**\n * Expand the hit area to at least 44×44px on touch devices\n */\nexport function TouchTarget({ children }: { children: React.ReactNode }) {\n return (\n <>\n <span\n className=\"absolute top-1/2 left-1/2 size-[max(100%,2.75rem)] -translate-x-1/2 -translate-y-1/2 pointer-fine:hidden\"\n aria-hidden=\"true\"\n />\n {children}\n </>\n )\n}\n\n/**\n * Loading spinner for button loading state\n */\nfunction LoadingSpinner({ className }: { className?: string }) {\n return (\n <svg\n className={clsx('h-4 w-4 animate-spin motion-reduce:animate-none', className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n )\n}\n\n/**\n * Floating Action Button (FAB) - iOS style\n * Fixed position button typically in bottom-right corner\n */\ntype FABProps = {\n /** Icon to display */\n icon: React.ReactNode\n /** Optional label (shows on hover/focus) */\n label?: string\n /** Button color */\n color?: FABColorType\n /** Size variant */\n size?: FABSizeType\n /** Position on screen */\n position?: FABPositionType\n /** Click handler */\n onClick?: () => void\n /** Show loading state */\n loading?: boolean\n /** Custom class */\n className?: string\n /** Extended FAB with label always visible */\n extended?: boolean\n}\n\nexport function FloatingActionButton({\n icon,\n label,\n color = 'ios-blue',\n size = 'md',\n position = 'bottom-right',\n onClick,\n loading,\n className,\n extended,\n}: FABProps) {\n const handleClick = () => {\n if (!loading) {\n triggerHaptic('medium')\n onClick?.()\n }\n }\n\n return (\n <motion.button\n onClick={handleClick}\n disabled={loading}\n initial={{ scale: 0, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n exit={{ scale: 0, opacity: 0 }}\n whileHover={{ scale: 1.05 }}\n whileTap={{ scale: 0.95 }}\n transition={getTransition(springPresets.bouncy)}\n className={clsx(\n fabPositions[position],\n extended ? 'px-5 h-14 rounded-full' : clsx(fabSizes[size], 'rounded-full'),\n fabColors[color],\n 'flex items-center justify-center gap-2',\n 'shadow-lg hover:shadow-xl',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500/70',\n 'z-50',\n loading && 'opacity-70 cursor-not-allowed',\n className\n )}\n aria-label={label}\n >\n {loading ? (\n <LoadingSpinner className={fabIconSizes[size]} />\n ) : (\n <span className={fabIconSizes[size]}>{icon}</span>\n )}\n {extended && label && (\n <span className=\"font-semibold text-base\">{label}</span>\n )}\n </motion.button>\n )\n}\n\n/**\n * Icon Button - Compact button with just an icon\n */\ntype IconButtonProps = {\n icon: React.ReactNode\n label: string // Required for accessibility\n color?: ColorType\n size?: IconButtonSizeType\n variant?: 'solid' | 'ghost' | 'outline'\n onClick?: () => void\n disabled?: boolean\n loading?: boolean\n className?: string\n destructive?: boolean\n}\n\nexport function IconButton({\n icon,\n label,\n color = 'ios-blue',\n size = 'md',\n variant = 'ghost',\n onClick,\n disabled,\n loading,\n className,\n destructive,\n}: IconButtonProps) {\n const finalColor = destructive ? 'ios-red' : color\n const isIosColor = finalColor in iosColors\n\n const handleClick = () => {\n if (!disabled && !loading) {\n triggerHaptic(destructive ? 'medium' : 'light')\n onClick?.()\n }\n }\n\n const variantStyles = {\n solid: clsx(\n 'text-white',\n isIosColor && finalColor === 'ios-blue' && 'bg-[#007AFF] dark:bg-[#0A84FF]',\n isIosColor && finalColor === 'ios-red' && 'bg-[#FF3B30] dark:bg-[#FF453A]',\n isIosColor && finalColor === 'ios-green' && 'bg-[#34C759] dark:bg-[#30D158]',\n isIosColor && finalColor === 'ios-orange' && 'bg-[#FF9500] dark:bg-[#FF9F0A]',\n isIosColor && finalColor === 'ios-purple' && 'bg-[#AF52DE] dark:bg-[#BF5AF2]',\n ),\n ghost: clsx(\n 'bg-transparent hover:bg-white/40 dark:hover:bg-white/[0.08]',\n isIosColor && finalColor === 'ios-blue' && 'text-[#007AFF] dark:text-[#0A84FF]',\n isIosColor && finalColor === 'ios-red' && 'text-[#FF3B30] dark:text-[#FF453A]',\n isIosColor && finalColor === 'ios-green' && 'text-[#34C759] dark:text-[#30D158]',\n isIosColor && finalColor === 'ios-orange' && 'text-[#FF9500] dark:text-[#FF9F0A]',\n isIosColor && finalColor === 'ios-purple' && 'text-[#AF52DE] dark:text-[#BF5AF2]',\n !isIosColor && 'text-slate-700 dark:text-slate-300',\n ),\n outline: clsx(\n 'bg-transparent border',\n isIosColor && finalColor === 'ios-blue' && 'border-[#007AFF] text-[#007AFF] dark:border-[#0A84FF] dark:text-[#0A84FF]',\n isIosColor && finalColor === 'ios-red' && 'border-[#FF3B30] text-[#FF3B30] dark:border-[#FF453A] dark:text-[#FF453A]',\n isIosColor && finalColor === 'ios-green' && 'border-[#34C759] text-[#34C759] dark:border-[#30D158] dark:text-[#30D158]',\n isIosColor && finalColor === 'ios-orange' && 'border-[#FF9500] text-[#FF9500] dark:border-[#FF9F0A] dark:text-[#FF9F0A]',\n isIosColor && finalColor === 'ios-purple' && 'border-[#AF52DE] text-[#AF52DE] dark:border-[#BF5AF2] dark:text-[#BF5AF2]',\n ),\n }\n\n return (\n <motion.button\n onClick={handleClick}\n disabled={disabled || loading}\n whileTap={{ scale: 0.9 }}\n transition={getTransition(springPresets.stiff)}\n className={clsx(\n iconButtonSizes[size],\n 'rounded-full flex items-center justify-center',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500/70',\n 'transition-colors',\n variantStyles[variant],\n (disabled || loading) && 'opacity-50 cursor-not-allowed',\n className\n )}\n aria-label={label}\n >\n {loading ? (\n <LoadingSpinner className={iconSizes[size]} />\n ) : (\n <span className={iconSizes[size]}>{icon}</span>\n )}\n </motion.button>\n )\n}\n","import * as Headless from '@headlessui/react'\nimport clsx from 'clsx'\nimport React, { forwardRef, type ReactNode, type MouseEvent } from 'react'\nimport { XMarkIcon } from '@heroicons/react/20/solid'\nimport { TouchTarget } from '@ui/components/button'\nimport { Link } from '@ui/components/link'\n\n/**\n * Badge — the single primitive for \"small colored label / chip /\n * tag / removable pill\" across the entire design system. Subsumes\n * the legacy `Pill`, `TagBadge`, `RoleBadge`, `FilterBadge`, and\n * `FilterPill` primitives. Use:\n *\n * - `<Badge color=\"indigo\">Premium</Badge>` — neutral metadata tag\n * - `<Badge color=\"amber\" icon={<X />}>3 alertas</Badge>` — with icon\n * - `<Badge color=\"indigo\" removable onRemove={fn}>SP</Badge>` — chip\n * - `<Badge color=\"indigo\" onClick={fn}>3 filtros</Badge>` — clickable\n *\n * For status-message pills (active/pending/failed/etc.) use\n * `<StatusBadge>` — it ships `role=\"status\"` + `aria-live` semantics\n * that Badge intentionally doesn't.\n */\n\nconst colors = {\n red: 'bg-red-500/15 text-red-700 group-data-hover:bg-red-500/25 dark:bg-red-500/10 dark:text-red-300 dark:group-data-hover:bg-red-500/20',\n orange:\n 'bg-orange-500/15 text-orange-700 group-data-hover:bg-orange-500/25 dark:bg-orange-500/10 dark:text-orange-300 dark:group-data-hover:bg-orange-500/20',\n amber:\n 'bg-amber-400/20 text-amber-800 group-data-hover:bg-amber-400/30 dark:bg-amber-400/10 dark:text-amber-300 dark:group-data-hover:bg-amber-400/15',\n yellow:\n 'bg-yellow-400/20 text-yellow-800 group-data-hover:bg-yellow-400/30 dark:bg-yellow-400/10 dark:text-yellow-200 dark:group-data-hover:bg-yellow-400/15',\n lime: 'bg-lime-400/20 text-lime-800 group-data-hover:bg-lime-400/30 dark:bg-lime-400/10 dark:text-lime-200 dark:group-data-hover:bg-lime-400/15',\n green:\n 'bg-green-500/15 text-green-700 group-data-hover:bg-green-500/25 dark:bg-green-500/10 dark:text-green-300 dark:group-data-hover:bg-green-500/20',\n emerald:\n 'bg-emerald-500/15 text-emerald-700 group-data-hover:bg-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-300 dark:group-data-hover:bg-emerald-500/20',\n teal: 'bg-teal-500/15 text-teal-700 group-data-hover:bg-teal-500/25 dark:bg-teal-500/10 dark:text-teal-300 dark:group-data-hover:bg-teal-500/20',\n cyan: 'bg-cyan-400/20 text-cyan-800 group-data-hover:bg-cyan-400/30 dark:bg-cyan-400/10 dark:text-cyan-200 dark:group-data-hover:bg-cyan-400/15',\n sky: 'bg-sky-500/15 text-sky-700 group-data-hover:bg-sky-500/25 dark:bg-sky-500/10 dark:text-sky-300 dark:group-data-hover:bg-sky-500/20',\n blue: 'bg-blue-500/15 text-blue-700 group-data-hover:bg-blue-500/25 dark:text-blue-300 dark:group-data-hover:bg-blue-500/25',\n indigo:\n 'bg-indigo-500/15 text-indigo-700 group-data-hover:bg-indigo-500/25 dark:text-indigo-300 dark:group-data-hover:bg-indigo-500/20',\n violet:\n 'bg-violet-500/15 text-violet-700 group-data-hover:bg-violet-500/25 dark:text-violet-300 dark:group-data-hover:bg-violet-500/20',\n purple:\n 'bg-purple-500/15 text-purple-700 group-data-hover:bg-purple-500/25 dark:text-purple-300 dark:group-data-hover:bg-purple-500/20',\n fuchsia:\n 'bg-fuchsia-400/20 text-fuchsia-700 group-data-hover:bg-fuchsia-400/30 dark:bg-fuchsia-400/10 dark:text-fuchsia-300 dark:group-data-hover:bg-fuchsia-400/20',\n pink: 'bg-pink-400/20 text-pink-700 group-data-hover:bg-pink-400/30 dark:bg-pink-400/10 dark:text-pink-300 dark:group-data-hover:bg-pink-400/20',\n rose: 'bg-rose-400/20 text-rose-700 group-data-hover:bg-rose-400/30 dark:bg-rose-400/10 dark:text-rose-300 dark:group-data-hover:bg-rose-400/20',\n zinc: 'bg-slate-500/15 text-slate-700 group-data-hover:bg-slate-500/25 dark:bg-white/5 dark:text-slate-200 dark:group-data-hover:bg-white/10',\n}\n\nexport type BadgeColor = keyof typeof colors\nexport type BadgeSize = 'xs' | 'sm' | 'md' | 'lg'\n\n// Size scale. WCAG 1.4.4: `xs` stays at 11px (not 10) so badges\n// remain legible at zoom 200%.\nconst sizes: Record<BadgeSize, { container: string; icon: string; remove: string }> = {\n xs: { container: 'px-2 py-0.5 text-[11px] gap-1', icon: 'h-3 w-3', remove: 'h-3 w-3 -mr-0.5' },\n sm: { container: 'px-2.5 py-0.5 text-xs gap-1.5', icon: 'h-3.5 w-3.5', remove: 'h-3.5 w-3.5 -mr-1' },\n md: { container: 'px-3 py-1 text-sm gap-1.5', icon: 'h-4 w-4', remove: 'h-4 w-4 -mr-1' },\n lg: { container: 'px-3.5 py-1.5 text-sm gap-2', icon: 'h-4 w-4', remove: 'h-4 w-4 -mr-1' },\n}\n\ntype BaseBadgeProps = {\n color?: BadgeColor\n size?: BadgeSize\n /** Optional leading icon (rendered before the label). */\n icon?: ReactNode\n /** When true, a remove (×) button is rendered at the end and the\n * badge becomes a focusable button. */\n removable?: boolean\n /** Called when the remove (×) button is clicked. Required when\n * `removable` is true. */\n onRemove?: () => void\n /** Accessible label for the remove button (e.g. \"remove São Paulo\n * filter\"). Defaults to a generic \"Remove\". */\n removeLabel?: string\n /** When provided, the entire badge becomes clickable (button\n * semantics with the canonical focus ring). */\n onClick?: () => void\n /** When true, marks the badge as a live status message so screen\n * readers announce changes (`role=\"status\" aria-live=\"polite\"`).\n * Use for dynamic state (\"active\" → \"pending\"); leave off for\n * static metadata (tags, counts, roles). */\n live?: boolean\n}\n\n// Crystal chrome — same recipe as StatusBadge so both pills look\n// identical: backdrop-blur + saturate + inset white highlight at the\n// top edge + a subtle tinted drop shadow. Applied via inline style so\n// it survives any consumer-supplied className (would otherwise be\n// trumped by Tailwind cascade ordering issues).\nconst CRYSTAL_STYLE: React.CSSProperties = {\n backdropFilter: 'blur(12px) saturate(1.5)',\n WebkitBackdropFilter: 'blur(12px) saturate(1.5)',\n boxShadow:\n 'inset 0 1px 1.5px rgba(255,255,255,0.45), 0 1px 3px -1px rgba(15,23,42,0.12)',\n}\n\ntype SpanBadgeProps = BaseBadgeProps & Omit<React.ComponentPropsWithoutRef<'span'>, 'onClick'>\n\nexport function Badge({\n color = 'zinc',\n size = 'sm',\n icon,\n removable = false,\n onRemove,\n removeLabel = 'Remove',\n onClick,\n live = false,\n className,\n children,\n ...props\n}: SpanBadgeProps) {\n const sz = sizes[size]\n const base = clsx(\n 'inline-flex items-center rounded-full border font-semibold forced-colors:outline',\n 'border-current/20', // hair-line border in the badge's own hue\n sz.container,\n colors[color],\n className,\n )\n const liveProps = live ? ({ role: 'status', 'aria-live': 'polite' as const }) : {}\n\n // Clickable variant — becomes a real button with focus-visible ring.\n if (onClick) {\n return (\n <button\n type=\"button\"\n data-testid=\"badge\"\n onClick={onClick}\n style={CRYSTAL_STYLE}\n {...liveProps}\n className={clsx(\n base,\n 'cursor-pointer transition-colors',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500/70 focus-visible:ring-offset-1',\n )}\n >\n {icon && <span className={clsx('shrink-0', sz.icon)} aria-hidden>{icon}</span>}\n {children}\n </button>\n )\n }\n\n // Removable variant — span wrapper + inner × button.\n if (removable) {\n return (\n <span\n data-testid=\"badge\"\n {...props}\n {...liveProps}\n style={CRYSTAL_STYLE}\n className={clsx(base, 'pr-1')}\n >\n {icon && <span className={clsx('shrink-0', sz.icon)} aria-hidden>{icon}</span>}\n {children}\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation()\n onRemove?.()\n }}\n className={clsx(\n 'ml-0.5 inline-flex shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'opacity-70 hover:opacity-100 transition-opacity',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500/70',\n )}\n >\n <XMarkIcon className={sz.remove} />\n </button>\n </span>\n )\n }\n\n // Plain decorative badge.\n return (\n <span data-testid=\"badge\" {...props} {...liveProps} style={CRYSTAL_STYLE} className={base}>\n {icon && <span className={clsx('shrink-0', sz.icon)} aria-hidden>{icon}</span>}\n {children}\n </span>\n )\n}\n\n// ─────────────────────────────────────────────────────────────────────\n// BadgeButton — Link/Button-wrapping variant. Kept for callers that\n// need href-based badges (e.g. role pills that navigate to a settings\n// page). Internally uses <Badge> with the click handled by the wrapper.\n// ─────────────────────────────────────────────────────────────────────\n\nexport const BadgeButton = forwardRef(function BadgeButton(\n {\n color = 'zinc',\n size = 'sm',\n icon,\n className,\n children,\n ...props\n }: BaseBadgeProps & { className?: string; children: React.ReactNode } & (\n | ({ href?: never } & Omit<Headless.ButtonProps, 'as' | 'className'>)\n | ({ href: string } & Omit<React.ComponentPropsWithoutRef<typeof Link>, 'className'>)\n ),\n ref: React.ForwardedRef<HTMLAnchorElement | HTMLButtonElement>\n) {\n let classes = clsx(\n className,\n 'group relative inline-flex rounded-full',\n 'focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-indigo-500/70',\n )\n\n if (typeof props.href === 'string') {\n return (\n <Link {...(props as React.ComponentPropsWithoutRef<typeof Link>)} className={classes} ref={ref as React.ForwardedRef<HTMLAnchorElement>}>\n <TouchTarget>\n <Badge color={color} size={size} icon={icon}>{children}</Badge>\n </TouchTarget>\n </Link>\n )\n }\n\n return (\n <Headless.Button {...(props as Headless.ButtonProps)} className={classes} ref={ref as React.ForwardedRef<HTMLButtonElement>}>\n <TouchTarget>\n <Badge color={color} size={size} icon={icon}>{children}</Badge>\n </TouchTarget>\n </Headless.Button>\n )\n})\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { AdminOrganizationDetail } from './chunk-
|
|
3
|
-
import { UserProfile } from './chunk-
|
|
4
|
-
import { BillingPanel } from './chunk-
|
|
5
|
-
import { useAuth, InlineSpinner, SegmentedControl } from './chunk-
|
|
2
|
+
import { AdminOrganizationDetail } from './chunk-4JRMXHPU.mjs';
|
|
3
|
+
import { UserProfile } from './chunk-CYAAL3BY.mjs';
|
|
4
|
+
import { BillingPanel } from './chunk-ZYRL3WER.mjs';
|
|
5
|
+
import { useAuth, InlineSpinner, SegmentedControl } from './chunk-5LCWQKGQ.mjs';
|
|
6
6
|
import { useTranslations } from './chunk-7VJ7CMMT.mjs';
|
|
7
7
|
import { useMemo, useState, useEffect } from 'react';
|
|
8
8
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -94,5 +94,5 @@ function PlatformSettings({
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
export { PlatformSettings };
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-YRXDETBK.mjs.map
|
|
98
|
+
//# sourceMappingURL=chunk-YRXDETBK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/platform/settings/platform-settings.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/platform/settings/platform-settings.tsx"],"names":[],"mappings":"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","file":"chunk-YRXDETBK.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — PlatformSettings\n// Unified settings shell consumed by every product (astrlabe, kori).\n// Composes existing building blocks:\n// - `<UserProfile>` — Profile / Security / Sessions / Linked accounts\n// - `<AdminOrganizationDetail>` — Members / Invitations / Domains\n// - `<BillingPanel>` — Current subscription + plan catalogue\n// Apps mount this at their `/settings` route; feature toggles hide sections\n// that a given user's role cannot access.\n// =============================================================================\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslations } from '@ui/lib/i18n-context'\nimport { SegmentedControl, InlineSpinner } from '@ui/index'\nimport type { AdminClient, AuthOrganization } from '@datatechsolutions/shared-domain'\n\nimport { useAuth } from '../../_auth'\nimport { UserProfile } from '../auth/user-profile'\nimport { AdminOrganizationDetail } from '../admin/admin-organization-detail'\nimport { BillingPanel, type BillingPanelProps } from '../billing/billing-panel'\n\nexport type PlatformSettingsSection = 'account' | 'organization' | 'billing'\n\nexport interface PlatformSettingsProps {\n /**\n * Sections to surface to the current user. The host app is responsible for\n * picking the right set based on RBAC — e.g. hide `organization` for users\n * without `org:manage` and hide `billing` for users without `billing:read`.\n * Defaults to all three.\n */\n sections?: PlatformSettingsSection[]\n /** Starting section. Defaults to the first item in `sections`. */\n defaultSection?: PlatformSettingsSection\n /**\n * Windsock admin API client. Required when `organization` is in `sections`.\n * Create it once with `createAdminClient({ issuer, authClient })` and reuse.\n */\n adminClient?: AdminClient\n /**\n * Current organization id (usually `ctx.organizationId` from the JWT).\n * Required when `organization` is in `sections`.\n */\n organizationId?: string\n /** Forwarded to `<BillingPanel>` — e.g. redirect handler, billing interval. */\n billing?: BillingPanelProps\n}\n\nconst DEFAULT_SECTIONS: PlatformSettingsSection[] = ['account', 'organization', 'billing']\n\nexport function PlatformSettings({\n sections = DEFAULT_SECTIONS,\n defaultSection,\n adminClient,\n organizationId,\n billing,\n}: PlatformSettingsProps) {\n const t = useTranslations('windsock')\n const { status } = useAuth()\n\n const visibleSections = useMemo(() => {\n // Drop `organization` if the caller didn't pass an admin client + org id.\n return sections.filter((section) => {\n if (section === 'organization') {\n return Boolean(adminClient && organizationId)\n }\n return true\n })\n }, [sections, adminClient, organizationId])\n\n const initialSection: PlatformSettingsSection = (\n defaultSection && visibleSections.includes(defaultSection)\n ? defaultSection\n : visibleSections[0] ?? 'account'\n )\n\n const [activeSection, setActiveSection] = useState<PlatformSettingsSection>(initialSection)\n const [organization, setOrganization] = useState<AuthOrganization | null>(null)\n const [orgLoadError, setOrgLoadError] = useState<string | null>(null)\n\n // Resolve the org detail record (AdminOrganizationDetail needs the full\n // AuthOrganization, not just the id). Fires once the organization tab is\n // first selected so the listOrganizations round-trip is lazy.\n useEffect(() => {\n if (activeSection !== 'organization') return\n if (!adminClient || !organizationId) return\n if (organization?.id === organizationId) return\n\n let cancelled = false\n setOrgLoadError(null)\n void adminClient.listOrganizations()\n .then((orgs) => {\n if (cancelled) return\n const match = orgs.find((org) => org.id === organizationId)\n if (match) {\n setOrganization(match)\n } else {\n setOrgLoadError('Organization not found')\n }\n })\n .catch((loadError: unknown) => {\n if (cancelled) return\n setOrgLoadError(loadError instanceof Error ? loadError.message : String(loadError))\n })\n return () => {\n cancelled = true\n }\n }, [activeSection, adminClient, organizationId, organization?.id])\n\n if (status === 'loading') {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n }\n\n if (status !== 'authenticated') {\n return null\n }\n\n if (visibleSections.length === 0) {\n return null\n }\n\n const segments = visibleSections.map((section) => ({\n value: section,\n label: t(`platformSettings.sections.${section}`),\n }))\n\n return (\n <div className=\"space-y-6\">\n {visibleSections.length > 1 && (\n <SegmentedControl\n segments={segments}\n value={activeSection}\n onChange={(value: string) => setActiveSection(value as PlatformSettingsSection)}\n fullWidth\n />\n )}\n\n {activeSection === 'account' && <UserProfile />}\n\n {activeSection === 'organization' && adminClient && organizationId && (\n organization ? (\n <AdminOrganizationDetail\n client={adminClient}\n organization={organization}\n />\n ) : orgLoadError ? (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-red-300/40 bg-red-50/80 px-4 py-3 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300\"\n >\n {orgLoadError}\n </div>\n ) : (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n )}\n\n {activeSection === 'billing' && <BillingPanel {...billing} />}\n </div>\n )\n}\n"]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useAuth, InlineSpinner, SectionCard, StatusBadge,
|
|
3
|
-
import { triggerHaptic } from './chunk-D2JF6C3E.mjs';
|
|
2
|
+
import { useAuth, InlineSpinner, SectionCard, StatusBadge, ListCard, ListCardItem } from './chunk-5LCWQKGQ.mjs';
|
|
4
3
|
import { useTranslations, useFormatter } from './chunk-7VJ7CMMT.mjs';
|
|
4
|
+
import { Badge, Button } from './chunk-WR55H7DH.mjs';
|
|
5
|
+
import { triggerHaptic } from './chunk-D2JF6C3E.mjs';
|
|
5
6
|
import { useState, useCallback, useEffect } from 'react';
|
|
6
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
8
|
|
|
@@ -234,5 +235,5 @@ function BillingPanel({
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
export { BillingPanel };
|
|
237
|
-
//# sourceMappingURL=chunk-
|
|
238
|
-
//# sourceMappingURL=chunk-
|
|
238
|
+
//# sourceMappingURL=chunk-ZYRL3WER.mjs.map
|
|
239
|
+
//# sourceMappingURL=chunk-ZYRL3WER.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/billing/billing-panel.tsx"],"names":[],"mappings":"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","file":"chunk-ZYRL3WER.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — BillingPanel\n// Shows the current organization subscription plus the plan catalogue, with\n// actions for opening the Stripe portal, starting checkout, or cancelling.\n// Backed by `AuthClient.getSubscription / getPlans / createPortalSession /\n// createCheckoutSession / cancelSubscription`.\n// =============================================================================\n\nimport { useEffect, useState, useCallback } from 'react'\nimport { useTranslations, useFormatter } from '@ui/lib/i18n-context'\nimport {\n SectionCard,\n Button,\n Badge,\n StatusBadge,\n InlineSpinner,\n ListCard,\n ListCardItem,\n triggerHaptic,\n} from '@ui/index'\nimport type {\n SubscriptionDetails,\n PlanDefinition,\n SubscriptionTier,\n} from '@datatechsolutions/shared-domain'\nimport { useAuth } from '../../_auth'\n\nexport interface BillingPanelProps {\n /**\n * Which billing interval to prefer when starting checkout. Defaults to\n * `'monthly'`. Surface a toggle in the host app if both matter.\n */\n defaultBillingInterval?: 'monthly' | 'yearly'\n /**\n * Called after the portal/checkout URL is resolved. Defaults to\n * `window.location.assign(url)`. Override to open in a new tab, use a\n * router, etc.\n */\n onRedirect?: (url: string) => void\n}\n\nconst TIER_ORDER: Record<SubscriptionTier, number> = {\n free_trial: 0,\n starter: 1,\n professional: 2,\n enterprise: 3,\n}\n\nexport function BillingPanel({\n defaultBillingInterval = 'monthly',\n onRedirect,\n}: BillingPanelProps) {\n const t = useTranslations('windsock')\n const format = useFormatter()\n const { client } = useAuth()\n\n const [subscription, setSubscription] = useState<SubscriptionDetails | null>(null)\n const [plans, setPlans] = useState<PlanDefinition[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [busyAction, setBusyAction] = useState<string | null>(null)\n\n const redirect = useCallback((url: string) => {\n if (onRedirect) {\n onRedirect(url)\n } else if (typeof window !== 'undefined') {\n window.location.assign(url)\n }\n }, [onRedirect])\n\n const load = useCallback(async () => {\n setIsLoading(true)\n setError(null)\n try {\n const [sub, availablePlans] = await Promise.all([\n client.getSubscription(),\n client.getPlans(),\n ])\n setSubscription(sub)\n setPlans(\n [...availablePlans]\n .filter((plan: { active: boolean }) => plan.active)\n .sort(\n (a: { tier: SubscriptionTier }, b: { tier: SubscriptionTier }) =>\n (TIER_ORDER[a.tier] ?? 0) - (TIER_ORDER[b.tier] ?? 0),\n ),\n )\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : String(loadError))\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const handleOpenPortal = useCallback(async () => {\n setBusyAction('portal')\n triggerHaptic('light')\n try {\n const { url } = await client.createPortalSession()\n redirect(url)\n } catch (portalError) {\n setError(portalError instanceof Error ? portalError.message : String(portalError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, redirect])\n\n const handleStartCheckout = useCallback(async (planCode: string) => {\n setBusyAction(`checkout:${planCode}`)\n triggerHaptic('light')\n try {\n const { url } = await client.createCheckoutSession(planCode, defaultBillingInterval)\n redirect(url)\n } catch (checkoutError) {\n setError(checkoutError instanceof Error ? checkoutError.message : String(checkoutError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, defaultBillingInterval, redirect])\n\n const handleCancel = useCallback(async () => {\n if (typeof window !== 'undefined') {\n const confirmed = window.confirm(t('billing.cancelConfirm'))\n if (!confirmed) return\n }\n setBusyAction('cancel')\n triggerHaptic('warning')\n try {\n const result = await client.cancelSubscription()\n if (!result.success) {\n throw new Error(result.error ?? 'Subscription cancellation failed')\n }\n triggerHaptic('success')\n await load()\n } catch (cancelError) {\n setError(cancelError instanceof Error ? cancelError.message : String(cancelError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, load, t])\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n }\n\n const currentPlan = subscription?.plan ?? plans.find((plan) => plan.id === subscription?.planId) ?? null\n const currentTier = subscription?.tier ?? currentPlan?.tier ?? null\n\n return (\n <div className=\"space-y-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-red-300/40 bg-red-50/80 px-4 py-3 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300\"\n >\n {error}\n </div>\n )}\n\n <SectionCard\n header={{\n title: t('billing.currentPlan.title'),\n subtitle: t('billing.currentPlan.description'),\n }}\n >\n {subscription && currentPlan ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n {currentPlan.name}\n </span>\n <StatusBadge\n status={\n subscription.status === 'active' ? 'success'\n : subscription.status === 'past_due' ? 'pending'\n : 'error'\n }\n label={t(`billing.status.${subscription.status}`)}\n />\n {subscription.cancelAtPeriodEnd && (\n <Badge color=\"amber\">{t('billing.currentPlan.cancelAtPeriodEnd')}</Badge>\n )}\n </div>\n\n <dl className=\"grid grid-cols-1 gap-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.price')}\n </dt>\n <dd className=\"font-medium text-gray-900 dark:text-white\">\n {format.number(currentPlan.price, { style: 'currency', currency: currentPlan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${currentPlan.interval}`)}\n </dd>\n </div>\n {subscription.currentPeriodEnd && (\n <div>\n <dt className=\"text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.renewsOn')}\n </dt>\n <dd className=\"font-medium text-gray-900 dark:text-white\">\n {format.dateTime(new Date(subscription.currentPeriodEnd), { dateStyle: 'medium' })}\n </dd>\n </div>\n )}\n </dl>\n\n <div className=\"flex flex-wrap gap-2 pt-2\">\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={handleOpenPortal}\n loading={busyAction === 'portal'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.manageInPortal')}\n </Button>\n {subscription.status === 'active' && !subscription.cancelAtPeriodEnd && (\n <Button\n size=\"sm\"\n color=\"ios-glass-red\"\n onClick={handleCancel}\n loading={busyAction === 'cancel'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.cancel')}\n </Button>\n )}\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.noSubscription')}\n </p>\n )}\n </SectionCard>\n\n <SectionCard\n header={{\n title: t('billing.plans.title'),\n subtitle: t('billing.plans.description'),\n }}\n >\n {plans.length === 0 ? (\n <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('billing.plans.empty')}\n </p>\n ) : (\n <ListCard>\n {plans.map((plan) => {\n const isCurrent = currentPlan?.id === plan.id\n const isDowngrade = currentTier != null\n && (TIER_ORDER[plan.tier] ?? 0) < (TIER_ORDER[currentTier] ?? 0)\n return (\n <ListCardItem\n key={plan.id}\n leading={\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500/20 to-blue-500/20 text-violet-600 dark:text-violet-300\">\n <span className=\"text-sm font-bold uppercase\">{plan.tier.charAt(0)}</span>\n </div>\n }\n trailing={\n isCurrent ? (\n <Badge color=\"green\">{t('billing.plans.currentBadge')}</Badge>\n ) : (\n isDowngrade ? (\n <Button\n size=\"sm\"\n plain\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.downgradeAction')}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.selectAction')}\n </Button>\n )\n )\n }\n >\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2\">\n <p className=\"text-sm font-medium text-gray-900 dark:text-white\">\n {plan.name}\n </p>\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\n {format.number(plan.price, { style: 'currency', currency: plan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${plan.interval}`)}\n </span>\n </div>\n {plan.description && (\n <p className=\"text-xs text-gray-500 dark:text-gray-400\">\n {plan.description}\n </p>\n )}\n </div>\n </ListCardItem>\n )\n })}\n </ListCard>\n )}\n </SectionCard>\n </div>\n )\n}\n"]}
|