Complete rename of "swift" terminology to "cortex" across the codebase: Code Changes: - Rename directories: lib/swift → lib/cortex, components/swift → components/cortex - Rename API routes: /api/swift/* → /api/cortex/* - Rename page routes: /epd/swift → /epd/cortex - Rename store: swift-store.ts → cortex-store.ts Type Renames: - SwiftIntent → CortexIntent - SwiftStore → CortexStore - useSwiftStore → useCortexStore - SwiftContext → CortexContext - useSwiftVoice → useCortexVoice Documentation Updates (docs/intent/): - Safety Net → Nudge (Layer 3 rename) - SafetySuggestion → NudgeSuggestion - evaluateSafetyNet → evaluateNudge - SWIFT_* feature flags → CORTEX_* - All path references updated to match new structure Files affected: 47 files, ~700 lines changed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
114 lines
2.8 KiB
TypeScript
114 lines
2.8 KiB
TypeScript
'use client';
|
|
|
|
/**
|
|
* Block Container
|
|
*
|
|
* Wrapper for ephemeral blocks with animation, close button, and sizing.
|
|
*/
|
|
|
|
import { ReactNode } from 'react';
|
|
import { motion, type Variants } from 'framer-motion';
|
|
import { X } from 'lucide-react';
|
|
import { useCortexStore } from '@/stores/cortex-store';
|
|
import type { BlockSize } from '@/lib/cortex/types';
|
|
|
|
interface BlockContainerProps {
|
|
title: string;
|
|
size?: BlockSize;
|
|
children: ReactNode;
|
|
}
|
|
|
|
const SIZE_CLASSES: Record<BlockSize, string> = {
|
|
sm: 'max-w-sm',
|
|
md: 'max-w-md',
|
|
lg: 'max-w-2xl',
|
|
full: 'max-w-4xl',
|
|
};
|
|
|
|
// Container animations - consistent met CanvasArea slide up/down
|
|
// Slide up + fade in bij openen, scale 0.95 → 1.0 (200ms)
|
|
const containerVariants: Variants = {
|
|
initial: {
|
|
scale: 0.95,
|
|
opacity: 0,
|
|
y: 0, // BlockContainer animatie wordt door CanvasArea gedaan
|
|
},
|
|
animate: {
|
|
scale: 1,
|
|
opacity: 1,
|
|
y: 0,
|
|
transition: {
|
|
duration: 0.2,
|
|
ease: [0.4, 0, 0.2, 1] as [number, number, number, number],
|
|
},
|
|
},
|
|
};
|
|
|
|
// Content stagger animation
|
|
const contentVariants: Variants = {
|
|
initial: { opacity: 0, y: 10 },
|
|
animate: {
|
|
opacity: 1,
|
|
y: 0,
|
|
transition: {
|
|
delay: 0.1,
|
|
duration: 0.2,
|
|
ease: [0.4, 0, 0.2, 1] as [number, number, number, number],
|
|
},
|
|
},
|
|
};
|
|
|
|
// Close button hover animation
|
|
const closeButtonVariants = {
|
|
rest: { scale: 1, rotate: 0 },
|
|
hover: { scale: 1.1, rotate: 90 },
|
|
tap: { scale: 0.95 },
|
|
};
|
|
|
|
export function BlockContainer({ title, size = 'md', children }: BlockContainerProps) {
|
|
const { closeBlock } = useCortexStore();
|
|
|
|
return (
|
|
<motion.div
|
|
variants={containerVariants}
|
|
initial="initial"
|
|
animate="animate"
|
|
className={`w-full ${SIZE_CLASSES[size]} bg-white rounded-xl border border-slate-200 shadow-lg`}
|
|
>
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-4 py-3 border-b border-slate-200">
|
|
<motion.h2
|
|
initial={{ opacity: 0, x: -10 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ delay: 0.05, duration: 0.2 }}
|
|
className="text-lg font-medium text-slate-900"
|
|
>
|
|
{title}
|
|
</motion.h2>
|
|
<motion.button
|
|
onClick={closeBlock}
|
|
variants={closeButtonVariants}
|
|
initial="rest"
|
|
whileHover="hover"
|
|
whileTap="tap"
|
|
className="p-1 rounded hover:bg-slate-100 text-slate-400 hover:text-slate-700 transition-colors"
|
|
title="Sluiten (Esc)"
|
|
aria-label="Block sluiten"
|
|
>
|
|
<X size={20} />
|
|
</motion.button>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<motion.div
|
|
variants={contentVariants}
|
|
initial="initial"
|
|
animate="animate"
|
|
className="p-4"
|
|
>
|
|
{children}
|
|
</motion.div>
|
|
</motion.div>
|
|
);
|
|
}
|