@designbasekorea/ui 0.4.1 → 0.5.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/index.js CHANGED
@@ -4,6 +4,7 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var icons = require('@designbasekorea/icons');
6
6
  var $4AOtR$reactdom = require('react-dom');
7
+ var theme = require('@designbasekorea/theme');
7
8
 
8
9
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
9
10
 
@@ -2899,256 +2900,584 @@ var classnames = {exports: {}};
2899
2900
  var classnamesExports = classnames.exports;
2900
2901
  var classNames = /*@__PURE__*/getDefaultExportFromCjs(classnamesExports);
2901
2902
 
2902
- const AnimationBackground = ({ type = 'gradient', speed = 3000, repeat = 0, delay = 0, direction = 'left', colors = ['#667eea', '#764ba2', '#f093fb', '#f5576c'], width = '100%', height = '200px', borderRadius = 0, opacity = 1, blendMode = 'normal', particleCount = 50, particleSize = 2, starCount = 100, starSize = 2, clickable = false, disabled = false, className, onClick, children, }) => {
2903
- const [isVisible, setIsVisible] = React.useState(false);
2904
- const [isAnimating, setIsAnimating] = React.useState(false);
2905
- const containerRef = React.useRef(null);
2906
- const canvasRef = React.useRef(null);
2907
- React.useEffect(() => {
2908
- if (delay > 0) {
2909
- const timer = setTimeout(() => {
2910
- setIsVisible(true);
2911
- }, delay);
2912
- return () => clearTimeout(timer);
2913
- }
2914
- else {
2915
- setIsVisible(true);
2903
+ /**
2904
+ * Canvas 렌더러: particles, stars, wave, pulse
2905
+ */
2906
+ const hexToRgb$1 = (hex) => {
2907
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
2908
+ return result
2909
+ ? {
2910
+ r: parseInt(result[1], 16),
2911
+ g: parseInt(result[2], 16),
2912
+ b: parseInt(result[3], 16),
2916
2913
  }
2917
- }, [delay]);
2918
- // 반복 애니메이션
2919
- React.useEffect(() => {
2920
- if (repeat > 0) {
2921
- let repeatCount = 0;
2922
- const repeatAnimation = () => {
2923
- setIsAnimating(true);
2924
- setTimeout(() => {
2925
- setIsAnimating(false);
2926
- repeatCount++;
2927
- if (repeatCount < repeat) {
2928
- setTimeout(repeatAnimation, speed);
2929
- }
2930
- }, speed);
2931
- };
2932
- if (isVisible) {
2933
- setTimeout(repeatAnimation, speed);
2914
+ : { r: 0, g: 0, b: 0 };
2915
+ };
2916
+ const drawParticles = (ctx, width, height, particlesRef, options) => {
2917
+ if (particlesRef.current.length !== options.count) {
2918
+ particlesRef.current = Array.from({ length: options.count }).map(() => ({
2919
+ x: Math.random() * width,
2920
+ y: Math.random() * height,
2921
+ vx: (Math.random() - 0.5) * 1.5,
2922
+ vy: (Math.random() - 0.5) * 1.5,
2923
+ size: Math.random() * options.size + 1,
2924
+ color: options.colors[Math.floor(Math.random() * options.colors.length)],
2925
+ }));
2926
+ }
2927
+ const particles = particlesRef.current;
2928
+ const interactionRadius = 150;
2929
+ particles.forEach((p, i) => {
2930
+ p.x += p.vx;
2931
+ p.y += p.vy;
2932
+ if (p.x < 0 || p.x > width)
2933
+ p.vx *= -1;
2934
+ if (p.y < 0 || p.y > height)
2935
+ p.vy *= -1;
2936
+ if (options.clickable) {
2937
+ const dx = options.mouse.x - p.x;
2938
+ const dy = options.mouse.y - p.y;
2939
+ const distance = Math.sqrt(dx * dx + dy * dy);
2940
+ if (distance < interactionRadius) {
2941
+ const force = (interactionRadius - distance) / interactionRadius;
2942
+ p.vx += (dx / distance) * force * 0.5;
2943
+ p.vy += (dy / distance) * force * 0.5;
2944
+ }
2945
+ const maxSpeed = 3;
2946
+ const speed = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
2947
+ if (speed > maxSpeed) {
2948
+ p.vx = (p.vx / speed) * maxSpeed;
2949
+ p.vy = (p.vy / speed) * maxSpeed;
2950
+ }
2951
+ }
2952
+ ctx.beginPath();
2953
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
2954
+ ctx.fillStyle = p.color;
2955
+ ctx.fill();
2956
+ for (let j = i + 1; j < particles.length; j++) {
2957
+ const p2 = particles[j];
2958
+ const dx = p.x - p2.x;
2959
+ const dy = p.y - p2.y;
2960
+ const dist = Math.sqrt(dx * dx + dy * dy);
2961
+ if (dist < 100) {
2962
+ ctx.beginPath();
2963
+ ctx.strokeStyle = p.color;
2964
+ ctx.globalAlpha = 1 - dist / 100;
2965
+ ctx.lineWidth = 0.5;
2966
+ ctx.moveTo(p.x, p.y);
2967
+ ctx.lineTo(p2.x, p2.y);
2968
+ ctx.stroke();
2969
+ ctx.globalAlpha = 1;
2934
2970
  }
2935
2971
  }
2936
- }, [repeat, speed, isVisible]);
2937
- // Canvas 애니메이션 (particles, stars 타입용)
2938
- React.useEffect(() => {
2939
- if ((type === 'particles' || type === 'stars') && canvasRef.current && isVisible) {
2940
- const canvas = canvasRef.current;
2941
- const ctx = canvas.getContext('2d');
2942
- if (!ctx)
2943
- return;
2944
- const resizeCanvas = () => {
2945
- const rect = containerRef.current?.getBoundingClientRect();
2946
- if (rect) {
2947
- canvas.width = rect.width;
2948
- canvas.height = rect.height;
2949
- }
2950
- };
2951
- resizeCanvas();
2952
- window.addEventListener('resize', resizeCanvas);
2953
- const particles = [];
2954
- // 파티클 초기화
2955
- const initParticles = () => {
2956
- particles.length = 0;
2957
- const count = type === 'particles' ? particleCount : starCount;
2958
- const size = type === 'particles' ? particleSize : starSize;
2959
- for (let i = 0; i < count; i++) {
2960
- particles.push({
2961
- x: Math.random() * canvas.width,
2962
- y: Math.random() * canvas.height,
2963
- vx: (Math.random() - 0.5) * 2,
2964
- vy: (Math.random() - 0.5) * 2,
2965
- size: Math.random() * size + 1,
2966
- color: colors[Math.floor(Math.random() * colors.length)],
2967
- });
2968
- }
2969
- };
2970
- initParticles();
2971
- const animate = () => {
2972
- ctx.clearRect(0, 0, canvas.width, canvas.height);
2973
- particles.forEach(particle => {
2974
- // 위치 업데이트
2975
- particle.x += particle.vx;
2976
- particle.y += particle.vy;
2977
- // 경계 처리
2978
- if (particle.x < 0 || particle.x > canvas.width)
2979
- particle.vx *= -1;
2980
- if (particle.y < 0 || particle.y > canvas.height)
2981
- particle.vy *= -1;
2982
- // 그리기
2983
- ctx.beginPath();
2984
- ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
2985
- ctx.fillStyle = particle.color;
2986
- ctx.fill();
2972
+ });
2973
+ };
2974
+ const drawStars = (ctx, width, height, starsRef, options) => {
2975
+ if (starsRef.current.length !== options.count) {
2976
+ starsRef.current = Array.from({ length: options.count }).map(() => ({
2977
+ x: Math.random() * width,
2978
+ y: Math.random() * height,
2979
+ size: Math.random() * options.size,
2980
+ blinkSpeed: Math.random() * 0.05 + 0.01,
2981
+ color: options.colors[Math.floor(Math.random() * options.colors.length)],
2982
+ }));
2983
+ }
2984
+ starsRef.current.forEach(star => {
2985
+ star.y -= 0.05;
2986
+ if (star.y < 0)
2987
+ star.y = height;
2988
+ const opacity = 0.5 + Math.sin(options.time * star.blinkSpeed) * 0.5;
2989
+ ctx.beginPath();
2990
+ ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
2991
+ ctx.fillStyle = star.color;
2992
+ ctx.globalAlpha = opacity;
2993
+ ctx.fill();
2994
+ ctx.globalAlpha = 1;
2995
+ });
2996
+ };
2997
+ const drawWaves = (ctx, width, height, options) => {
2998
+ const { colors, offset, speedFactor } = options;
2999
+ offset.current += 0.005 * speedFactor; // Slower, smoother movement
3000
+ colors.forEach((color, i) => {
3001
+ const rgb = hexToRgb$1(color);
3002
+ const gradient = ctx.createLinearGradient(0, 0, 0, height);
3003
+ // Gradient from color to transparent for depth
3004
+ gradient.addColorStop(0, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0)`);
3005
+ gradient.addColorStop(0.5, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.5)`);
3006
+ gradient.addColorStop(1, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.8)`);
3007
+ ctx.fillStyle = gradient;
3008
+ ctx.beginPath();
3009
+ ctx.moveTo(0, height);
3010
+ // Organic wave generation
3011
+ for (let x = 0; x <= width; x += 5) {
3012
+ const freq1 = 0.002 + i * 0.0005;
3013
+ const freq2 = 0.005 + i * 0.001;
3014
+ const phase = offset.current + i * 1.5;
3015
+ // Combine two sine waves for more natural look
3016
+ const y1 = Math.sin(x * freq1 + phase) * (40 + i * 15);
3017
+ const y2 = Math.sin(x * freq2 + phase * 1.2) * (20 + i * 5);
3018
+ const y = height / 1.5 + y1 + y2 + (i * 30); // Base height + waves + layering offset
3019
+ ctx.lineTo(x, y);
3020
+ }
3021
+ ctx.lineTo(width, height);
3022
+ ctx.lineTo(0, height);
3023
+ ctx.closePath();
3024
+ // Add subtle blur for "dreamy" effect
3025
+ // Note: filter can be expensive, use sparingly.
3026
+ // If performance is an issue, remove this toggle or reduce canvas size.
3027
+ // ctx.filter = 'blur(4px)';
3028
+ ctx.globalAlpha = 0.6; // Base transparency
3029
+ ctx.fill();
3030
+ ctx.globalAlpha = 1.0;
3031
+ // ctx.filter = 'none';
3032
+ });
3033
+ };
3034
+ const drawPulse = (ctx, width, height, options) => {
3035
+ const { colors, time, intensity } = options;
3036
+ const centerX = width / 2;
3037
+ const centerY = height / 2;
3038
+ const maxRadius = Math.max(width, height) * 0.6; // Slightly reduced max radius to keep it contained
3039
+ const intensityMap = { subtle: 0.8, medium: 1.2, vivid: 1.8 }; // Increased base intensity
3040
+ const factor = intensityMap[intensity];
3041
+ colors.forEach((color, i) => {
3042
+ // Offset time for each color layer
3043
+ const t = time * 0.002 * factor + (i * (Math.PI / 1.5));
3044
+ // Breathing effect for radius
3045
+ const radius = (Math.sin(t) * 0.15 + 0.6) * maxRadius;
3046
+ // Breathing effect for opacity
3047
+ const alpha = (Math.sin(t + Math.PI / 2) * 0.3 + 0.5) * factor; // Higher base alpha (0.2->0.8 range)
3048
+ // Clamp alpha max to 1
3049
+ const safeAlpha = Math.min(Math.max(alpha, 0), 1);
3050
+ if (safeAlpha <= 0.01)
3051
+ return;
3052
+ const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius);
3053
+ const rgb = hexToRgb$1(color);
3054
+ // Harder center, softer edge
3055
+ gradient.addColorStop(0, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0)`);
3056
+ gradient.addColorStop(0.2, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${safeAlpha * 0.2})`);
3057
+ gradient.addColorStop(0.6, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${safeAlpha * 0.6})`);
3058
+ gradient.addColorStop(1, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0)`);
3059
+ ctx.fillStyle = gradient;
3060
+ // Use globalCompositeOperation to blend nicely
3061
+ ctx.globalCompositeOperation = 'screen';
3062
+ ctx.fillRect(0, 0, width, height);
3063
+ ctx.globalCompositeOperation = 'source-over';
3064
+ });
3065
+ };
3066
+
3067
+ const CanvasLayer = ({ type, colors, speed, particleCount, particleSize, starCount, starSize, intensity, clickable, }) => {
3068
+ const canvasRef = React.useRef(null);
3069
+ const containerRef = React.useRef(null);
3070
+ const requestRef = React.useRef(undefined);
3071
+ const frameCountRef = React.useRef(0);
3072
+ const mouseRef = React.useRef({ x: -9999, y: -9999 });
3073
+ const particlesRef = React.useRef([]);
3074
+ const starsRef = React.useRef([]);
3075
+ const waveOffsetRef = React.useRef(0);
3076
+ const handleResize = React.useCallback(() => {
3077
+ const canvas = canvasRef.current;
3078
+ const container = containerRef.current;
3079
+ if (!canvas || !container)
3080
+ return;
3081
+ const dpr = window.devicePixelRatio || 1;
3082
+ const rect = container.getBoundingClientRect();
3083
+ canvas.width = rect.width * dpr;
3084
+ canvas.height = rect.height * dpr;
3085
+ canvas.style.width = `${rect.width}px`;
3086
+ canvas.style.height = `${rect.height}px`;
3087
+ const ctx = canvas.getContext('2d');
3088
+ if (ctx)
3089
+ ctx.scale(dpr, dpr);
3090
+ }, []);
3091
+ const animate = React.useCallback(() => {
3092
+ const canvas = canvasRef.current;
3093
+ if (!canvas)
3094
+ return;
3095
+ const ctx = canvas.getContext('2d');
3096
+ if (!ctx)
3097
+ return;
3098
+ const dpr = window.devicePixelRatio || 1;
3099
+ const width = canvas.width / dpr;
3100
+ const height = canvas.height / dpr;
3101
+ ctx.clearRect(0, 0, width, height);
3102
+ const time = frameCountRef.current * (3000 / (speed || 3000));
3103
+ frameCountRef.current += 1;
3104
+ switch (type) {
3105
+ case 'particles':
3106
+ drawParticles(ctx, width, height, particlesRef, {
3107
+ count: particleCount,
3108
+ colors,
3109
+ size: particleSize,
3110
+ mouse: mouseRef.current,
3111
+ clickable,
2987
3112
  });
2988
- requestAnimationFrame(animate);
2989
- };
2990
- animate();
2991
- return () => {
2992
- window.removeEventListener('resize', resizeCanvas);
2993
- };
2994
- }
2995
- }, [type, isVisible, colors, particleCount, particleSize, starCount, starSize]);
2996
- const handleClick = () => {
2997
- if (clickable && !disabled && onClick) {
2998
- onClick();
2999
- }
3000
- };
3001
- const getGradientStyle = () => {
3002
- if (type === 'gradient' || type === 'rainbow') {
3003
- const gradientColors = type === 'rainbow'
3004
- ? ['#ff0000', '#ff8000', '#ffff00', '#80ff00', '#00ff00', '#00ff80', '#00ffff', '#0080ff', '#0000ff', '#8000ff', '#ff00ff', '#ff0080']
3005
- : colors;
3006
- if (direction === 'radial') {
3007
- return {
3008
- background: `radial-gradient(circle, ${gradientColors.join(', ')})`,
3009
- backgroundSize: '400% 400%',
3010
- };
3011
- }
3012
- else {
3013
- const angle = direction === 'left' ? '90deg' :
3014
- direction === 'right' ? '270deg' :
3015
- direction === 'up' ? '0deg' :
3016
- direction === 'down' ? '180deg' :
3017
- direction === 'diagonal' ? '45deg' : '90deg';
3018
- return {
3019
- background: `linear-gradient(${angle}, ${gradientColors.join(', ')})`,
3020
- backgroundSize: '400% 400%',
3021
- };
3022
- }
3023
- }
3024
- return {};
3025
- };
3026
- const getWaveStyle = () => {
3027
- if (type === 'wave') {
3028
- return {
3029
- '--wave-colors': colors.join(', '),
3030
- };
3031
- }
3032
- return {};
3033
- };
3034
- const getAuroraStyle = () => {
3035
- if (type === 'aurora') {
3036
- return {
3037
- '--aurora-colors': colors.join(', '),
3038
- };
3039
- }
3040
- return {};
3041
- };
3042
- const getFireStyle = () => {
3043
- if (type === 'fire') {
3044
- return {
3045
- '--fire-colors': colors.join(', '),
3046
- };
3113
+ break;
3114
+ case 'stars':
3115
+ drawStars(ctx, width, height, starsRef, {
3116
+ count: starCount,
3117
+ colors,
3118
+ size: starSize,
3119
+ time,
3120
+ });
3121
+ break;
3122
+ case 'wave':
3123
+ drawWaves(ctx, width, height, {
3124
+ colors,
3125
+ offset: waveOffsetRef,
3126
+ speedFactor: 10000 / (speed || 5000),
3127
+ });
3128
+ break;
3129
+ case 'pulse':
3130
+ drawPulse(ctx, width, height, {
3131
+ colors,
3132
+ time,
3133
+ intensity,
3134
+ });
3135
+ break;
3047
3136
  }
3048
- return {};
3137
+ requestRef.current = requestAnimationFrame(animate);
3138
+ }, [
3139
+ type,
3140
+ colors,
3141
+ speed,
3142
+ particleCount,
3143
+ particleSize,
3144
+ starCount,
3145
+ starSize,
3146
+ intensity,
3147
+ clickable,
3148
+ ]);
3149
+ React.useEffect(() => {
3150
+ handleResize();
3151
+ window.addEventListener('resize', handleResize);
3152
+ particlesRef.current = [];
3153
+ starsRef.current = [];
3154
+ waveOffsetRef.current = 0;
3155
+ frameCountRef.current = 0;
3156
+ requestRef.current = requestAnimationFrame(animate);
3157
+ return () => {
3158
+ window.removeEventListener('resize', handleResize);
3159
+ if (requestRef.current)
3160
+ cancelAnimationFrame(requestRef.current);
3161
+ };
3162
+ }, [animate, handleResize]);
3163
+ const handleMouseMove = (e) => {
3164
+ if (!containerRef.current)
3165
+ return;
3166
+ const rect = containerRef.current.getBoundingClientRect();
3167
+ mouseRef.current = {
3168
+ x: e.clientX - rect.left,
3169
+ y: e.clientY - rect.top,
3170
+ };
3049
3171
  };
3050
- const getOceanStyle = () => {
3051
- if (type === 'ocean') {
3052
- return {
3053
- '--ocean-colors': colors.join(', '),
3054
- };
3055
- }
3056
- return {};
3172
+ const handleMouseLeave = () => {
3173
+ mouseRef.current = { x: -9999, y: -9999 };
3057
3174
  };
3058
- const getSunsetStyle = () => {
3059
- if (type === 'sunset') {
3175
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: "designbase-animation-background__canvas-layer", onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, children: jsxRuntime.jsx("canvas", { ref: canvasRef, className: "designbase-animation-background__canvas" }) }));
3176
+ };
3177
+
3178
+ const CSSGradientLayer = ({ type, direction, colors, speed, }) => {
3179
+ const getBackgroundStyle = () => {
3180
+ const safeColors = colors.length > 0 ? colors : ['#ccc'];
3181
+ const gradientStr = safeColors.join(', ');
3182
+ if (type === 'gradient') {
3183
+ let angle = '90deg';
3184
+ switch (direction) {
3185
+ case 'up':
3186
+ angle = '0deg';
3187
+ break;
3188
+ case 'down':
3189
+ angle = '180deg';
3190
+ break;
3191
+ case 'left':
3192
+ angle = '270deg';
3193
+ break;
3194
+ case 'right':
3195
+ angle = '90deg';
3196
+ break;
3197
+ case 'diagonal':
3198
+ angle = '45deg';
3199
+ break;
3200
+ case 'radial':
3201
+ return {
3202
+ backgroundImage: `radial-gradient(circle, ${gradientStr})`,
3203
+ backgroundSize: '200% 200%',
3204
+ };
3205
+ }
3060
3206
  return {
3061
- '--sunset-colors': colors.join(', '),
3207
+ backgroundImage: `linear-gradient(${angle}, ${gradientStr})`,
3208
+ backgroundSize: '200% 200%',
3062
3209
  };
3063
3210
  }
3064
3211
  return {};
3065
3212
  };
3066
- const classes = classNames('designbase-animation-background', `designbase-animation-background--${type}`, `designbase-animation-background--${direction}`, {
3067
- 'designbase-animation-background--visible': isVisible,
3068
- 'designbase-animation-background--animating': isAnimating,
3069
- 'designbase-animation-background--clickable': clickable,
3070
- 'designbase-animation-background--disabled': disabled,
3071
- }, className);
3213
+ const duration = `${Math.max(2, speed / 1000)}s`;
3214
+ return (jsxRuntime.jsx("div", { className: "designbase-animation-background__css-layer", style: {
3215
+ ...getBackgroundStyle(),
3216
+ animation: `designbase-gradient-move ${duration} ease infinite`,
3217
+ }, children: jsxRuntime.jsx("style", { children: `
3218
+ @keyframes designbase-gradient-move {
3219
+ 0% { background-position: 0% 50%; }
3220
+ 50% { background-position: 100% 50%; }
3221
+ 100% { background-position: 0% 50%; }
3222
+ }
3223
+ ` }) }));
3224
+ };
3225
+
3226
+ const MeshAuroraLayer = ({ colors, speed, blur, intensity, theme, }) => {
3227
+ const baseOpacity = intensity === 'subtle' ? 0.3 : intensity === 'medium' ? 0.6 : 0.8;
3228
+ const duration = Math.max(5, speed / 1000);
3229
+ const palette = colors.length >= 3
3230
+ ? colors
3231
+ : ['#4f46e5', '#ec4899', '#06b6d4', '#8b5cf6'];
3232
+ const blendMode = theme === 'dark' ? 'screen' : 'multiply';
3233
+ const filterStyle = `blur(${blur}px)`;
3234
+ const blobBaseClass = 'designbase-animation-background__aurora-blob';
3235
+ return (jsxRuntime.jsxs("div", { className: "designbase-animation-background__aurora-mesh", children: [jsxRuntime.jsx("div", { className: blobBaseClass, style: {
3236
+ backgroundColor: palette[0],
3237
+ filter: filterStyle,
3238
+ opacity: baseOpacity,
3239
+ animationDuration: `${duration}s`,
3240
+ top: '-10%',
3241
+ left: '-10%',
3242
+ animationDelay: '0s',
3243
+ mixBlendMode: blendMode,
3244
+ } }), jsxRuntime.jsx("div", { className: blobBaseClass, style: {
3245
+ backgroundColor: palette[1],
3246
+ filter: filterStyle,
3247
+ opacity: baseOpacity,
3248
+ animationDuration: `${duration * 1.2}s`,
3249
+ top: '-10%',
3250
+ right: '-10%',
3251
+ animationDelay: '2s',
3252
+ mixBlendMode: blendMode,
3253
+ } }), jsxRuntime.jsx("div", { className: blobBaseClass, style: {
3254
+ backgroundColor: palette[2],
3255
+ filter: filterStyle,
3256
+ opacity: baseOpacity,
3257
+ animationDuration: `${duration * 1.5}s`,
3258
+ bottom: '-20%',
3259
+ left: '20%',
3260
+ animationDelay: '4s',
3261
+ mixBlendMode: blendMode,
3262
+ } }), palette[3] && (jsxRuntime.jsx("div", { className: blobBaseClass, style: {
3263
+ backgroundColor: palette[3],
3264
+ filter: filterStyle,
3265
+ opacity: baseOpacity,
3266
+ animationDuration: `${duration * 1.1}s`,
3267
+ bottom: '-10%',
3268
+ right: '-10%',
3269
+ animationDelay: '1s',
3270
+ mixBlendMode: blendMode,
3271
+ } })), jsxRuntime.jsx("div", { className: "designbase-animation-background__aurora-noise", style: {
3272
+ opacity: theme === 'dark' ? 0.03 : 0.05,
3273
+ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
3274
+ } })] }));
3275
+ };
3276
+
3277
+ const GridOverlay = ({ size = 40, color = '#ffffff', opacity = 0.1, }) => {
3072
3278
  const style = {
3279
+ position: 'absolute',
3280
+ inset: 0,
3281
+ width: '100%',
3282
+ height: '100%',
3283
+ pointerEvents: 'none',
3284
+ zIndex: 1,
3285
+ backgroundImage: `
3286
+ linear-gradient(to right, ${color} 1px, transparent 1px),
3287
+ linear-gradient(to bottom, ${color} 1px, transparent 1px)
3288
+ `,
3289
+ backgroundSize: `${size}px ${size}px`,
3290
+ opacity,
3291
+ // 은은하게 전체에 라인 유지, 맨 아래만 살짝 페이드
3292
+ maskImage: 'linear-gradient(to bottom, black 0%, black 92%, transparent 100%)',
3293
+ WebkitMaskImage: 'linear-gradient(to bottom, black 0%, black 92%, transparent 100%)',
3294
+ };
3295
+ return jsxRuntime.jsx("div", { className: "designbase-animation-background__grid-overlay", style: style });
3296
+ };
3297
+
3298
+ const AnimationBackground = ({ type = 'gradient', theme = 'dark', intensity = 'subtle', blur = 80, speed = 3000, repeat = 0, direction = 'left', colors = ['#667eea', '#764ba2', '#f093fb'], width = '100%', height = '100%', borderRadius = 0, opacity = 1, blendMode = 'normal', particleCount = 50, particleSize = 2, starCount = 100, starSize = 1.5, clickable = false, disabled = false, className = '', onClick, children, showGrid = false, gridSize = 40, gridColor, gridOpacity = 0.1, }) => {
3299
+ const backgroundColor = theme === 'dark' ? 'var(--db-surface-base, #0f172a)' : 'var(--db-surface-base, #ffffff)';
3300
+ const effectiveGridColor = gridColor ?? (theme === 'dark' ? '#ffffff' : '#000000');
3301
+ const containerStyle = {
3073
3302
  width: typeof width === 'number' ? `${width}px` : width,
3074
3303
  height: typeof height === 'number' ? `${height}px` : height,
3075
3304
  borderRadius: typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius,
3076
3305
  opacity,
3077
3306
  mixBlendMode: blendMode,
3078
- ...getGradientStyle(),
3079
- ...getWaveStyle(),
3080
- ...getAuroraStyle(),
3081
- ...getFireStyle(),
3082
- ...getOceanStyle(),
3083
- ...getSunsetStyle(),
3084
- '--db-animation-speed': `${speed}ms`,
3307
+ position: 'relative',
3308
+ overflow: 'hidden',
3309
+ backgroundColor: type !== 'gradient' ? backgroundColor : undefined,
3085
3310
  };
3086
- const renderContent = () => {
3087
- if (type === 'particles' || type === 'stars') {
3088
- return (jsxRuntime.jsx("canvas", { ref: canvasRef, className: "designbase-animation-background__canvas", style: { width: '100%', height: '100%' } }));
3311
+ const content = React.useMemo(() => {
3312
+ if (disabled)
3313
+ return null;
3314
+ switch (type) {
3315
+ case 'particles':
3316
+ case 'stars':
3317
+ case 'wave':
3318
+ case 'pulse':
3319
+ return (jsxRuntime.jsx(CanvasLayer, { type: type, colors: colors, speed: speed, particleCount: particleCount, particleSize: particleSize, starCount: starCount, starSize: starSize, intensity: intensity, clickable: clickable }));
3320
+ case 'aurora':
3321
+ return (jsxRuntime.jsx(MeshAuroraLayer, { colors: colors, speed: speed, blur: blur, intensity: intensity, theme: theme }));
3322
+ case 'gradient':
3323
+ return (jsxRuntime.jsx(CSSGradientLayer, { type: type, direction: direction, colors: colors, speed: speed }));
3324
+ default:
3325
+ return null;
3089
3326
  }
3090
- return children;
3091
- };
3092
- return (jsxRuntime.jsx("div", { ref: containerRef, className: classes, style: style, onClick: handleClick, children: renderContent() }));
3327
+ }, [
3328
+ type,
3329
+ disabled,
3330
+ colors,
3331
+ speed,
3332
+ intensity,
3333
+ blur,
3334
+ theme,
3335
+ particleCount,
3336
+ particleSize,
3337
+ starCount,
3338
+ starSize,
3339
+ clickable,
3340
+ direction,
3341
+ ]);
3342
+ const classes = classNames('designbase-animation-background', `designbase-animation-background--${type}`, {
3343
+ 'designbase-animation-background--clickable': clickable,
3344
+ 'designbase-animation-background--disabled': disabled,
3345
+ }, className);
3346
+ return (jsxRuntime.jsxs("div", { className: classes, style: containerStyle, onClick: clickable && !disabled ? onClick : undefined, children: [jsxRuntime.jsx("div", { className: "designbase-animation-background__layers", style: {
3347
+ position: 'absolute',
3348
+ inset: 0,
3349
+ width: '100%',
3350
+ height: '100%',
3351
+ zIndex: 0,
3352
+ }, children: content }), showGrid && (jsxRuntime.jsx(GridOverlay, { size: gridSize, color: effectiveGridColor, opacity: gridOpacity })), children && (jsxRuntime.jsx("div", { className: "designbase-animation-background__content", style: { position: 'relative', zIndex: 10, width: '100%', height: '100%' }, children: children }))] }));
3093
3353
  };
3094
3354
 
3095
- const AnimationText = ({ children, type = 'fade', speed = 1000, repeat = 0, delay = 0, direction = 'left', size = 'm', color = 'primary', customColor, weight = 'normal', align = 'left', gradientColors = ['#667eea', '#764ba2'], waveColors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#feca57'], glowColor = '#667eea', clickable = false, disabled = false, className, onClick, }) => {
3355
+ const AnimationText = ({ children, trigger = 'mount', type = 'fade', speed = 1000, repeat = 1, delay = 0, direction = 'left', size = 'm', color = 'primary', customColor, weight = 'normal', align = 'left', gradientColors = ['#667eea', '#764ba2'], waveColors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#feca57'], glowColor = '#667eea', clickable = false, disabled = false, className, onClick, }) => {
3096
3356
  const [isVisible, setIsVisible] = React.useState(false);
3097
- const [currentIndex, setCurrentIndex] = React.useState(0);
3098
3357
  const [isAnimating, setIsAnimating] = React.useState(false);
3358
+ // Initialize with full text unless it's a mount trigger for typing/decode
3359
+ const [displayText, setDisplayText] = React.useState((type === 'decode' || type === 'typing') && trigger === 'mount' ? '' : children);
3360
+ const [currentRepeat, setCurrentRepeat] = React.useState(0);
3099
3361
  const textRef = React.useRef(null);
3100
- React.useRef(null);
3101
- // 타이핑 애니메이션을 위한 상태
3102
- const [displayText, setDisplayText] = React.useState('');
3362
+ const observerRef = React.useRef(null);
3363
+ // Initial trigger logic
3103
3364
  React.useEffect(() => {
3104
- if (delay > 0) {
3365
+ if (trigger === 'mount') {
3105
3366
  const timer = setTimeout(() => {
3106
3367
  setIsVisible(true);
3368
+ startAnimation();
3107
3369
  }, delay);
3108
3370
  return () => clearTimeout(timer);
3109
3371
  }
3110
- else {
3111
- setIsVisible(true);
3372
+ else if (trigger === 'in-view' && textRef.current) {
3373
+ observerRef.current = new IntersectionObserver((entries) => {
3374
+ if (entries[0].isIntersecting) {
3375
+ setTimeout(() => {
3376
+ setIsVisible(true);
3377
+ startAnimation();
3378
+ }, delay);
3379
+ observerRef.current?.disconnect();
3380
+ }
3381
+ });
3382
+ observerRef.current.observe(textRef.current);
3383
+ return () => observerRef.current?.disconnect();
3112
3384
  }
3113
- }, [delay]);
3114
- // 타이핑 애니메이션
3385
+ }, [trigger, delay]);
3386
+ // Update initial text visibility when props change
3115
3387
  React.useEffect(() => {
3116
- if (type === 'typing' && isVisible) {
3117
- setDisplayText('');
3118
- setCurrentIndex(0);
3119
- const typeInterval = setInterval(() => {
3120
- setCurrentIndex(prev => {
3121
- if (prev >= children.length) {
3122
- clearInterval(typeInterval);
3123
- return prev;
3124
- }
3125
- setDisplayText(children.slice(0, prev + 1));
3126
- return prev + 1;
3127
- });
3128
- }, speed / children.length);
3129
- return () => clearInterval(typeInterval);
3388
+ if ((type === 'typing' || type === 'decode') && trigger === 'mount') ;
3389
+ else {
3390
+ // For hover/click, ensure text is visible when not animating
3391
+ if (!isAnimating) {
3392
+ setDisplayText(children);
3393
+ }
3130
3394
  }
3131
- }, [type, isVisible, children, speed]);
3132
- // 반복 애니메이션
3133
- React.useEffect(() => {
3134
- if (repeat > 0 && type !== 'typing') {
3135
- let repeatCount = 0;
3136
- const repeatAnimation = () => {
3137
- setIsAnimating(true);
3138
- setTimeout(() => {
3395
+ }, [children, type, trigger]);
3396
+ const startAnimation = () => {
3397
+ setIsAnimating(true);
3398
+ setCurrentRepeat(0);
3399
+ if (type === 'typing') {
3400
+ startTyping(0);
3401
+ }
3402
+ else if (type === 'decode') {
3403
+ startDecoding(0);
3404
+ }
3405
+ };
3406
+ const startTyping = (iteration) => {
3407
+ setDisplayText('');
3408
+ let currentIndex = 0;
3409
+ const interval = setInterval(() => {
3410
+ if (currentIndex >= children.length) {
3411
+ clearInterval(interval);
3412
+ // Repetition logic
3413
+ if (repeat === 0 || iteration < repeat - 1) {
3414
+ setTimeout(() => {
3415
+ startTyping(iteration + 1);
3416
+ }, 500);
3417
+ }
3418
+ else {
3139
3419
  setIsAnimating(false);
3140
- repeatCount++;
3141
- if (repeatCount < repeat) {
3142
- setTimeout(repeatAnimation, speed);
3143
- }
3144
- }, speed);
3145
- };
3146
- if (isVisible) {
3147
- setTimeout(repeatAnimation, speed);
3420
+ }
3421
+ return;
3422
+ }
3423
+ setDisplayText(children.slice(0, currentIndex + 1));
3424
+ currentIndex++;
3425
+ }, speed / children.length);
3426
+ };
3427
+ const startDecoding = (iteration) => {
3428
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+';
3429
+ let iterations = 0;
3430
+ const interval = setInterval(() => {
3431
+ setDisplayText(children.split('').map((char, index) => {
3432
+ if (index < iterations) {
3433
+ return children[index];
3434
+ }
3435
+ return characters[Math.floor(Math.random() * characters.length)];
3436
+ }).join(''));
3437
+ if (iterations >= children.length) {
3438
+ clearInterval(interval);
3439
+ setDisplayText(children);
3440
+ // Repetition logic
3441
+ if (repeat === 0 || iteration < repeat - 1) {
3442
+ setTimeout(() => {
3443
+ startDecoding(iteration + 1);
3444
+ }, 500);
3445
+ }
3446
+ else {
3447
+ setIsAnimating(false);
3448
+ }
3148
3449
  }
3450
+ iterations += 1 / 3;
3451
+ }, 30);
3452
+ };
3453
+ const handleMouseEnter = () => {
3454
+ if (trigger === 'hover') {
3455
+ setIsVisible(true);
3456
+ startAnimation();
3149
3457
  }
3150
- }, [repeat, type, speed, isVisible]);
3458
+ };
3459
+ const handleMouseLeave = () => {
3460
+ if (trigger === 'hover') {
3461
+ setIsVisible(false);
3462
+ setIsAnimating(false);
3463
+ if (type === 'typing' || type === 'decode') {
3464
+ setDisplayText(children);
3465
+ }
3466
+ }
3467
+ };
3151
3468
  const handleClick = () => {
3469
+ if (trigger === 'click') {
3470
+ setIsVisible(!isVisible);
3471
+ if (isVisible) {
3472
+ setIsAnimating(false);
3473
+ if (type === 'typing' || type === 'decode') {
3474
+ setDisplayText(children);
3475
+ }
3476
+ }
3477
+ else {
3478
+ startAnimation();
3479
+ }
3480
+ }
3152
3481
  if (clickable && !disabled && onClick) {
3153
3482
  onClick();
3154
3483
  }
@@ -3165,14 +3494,6 @@ const AnimationText = ({ children, type = 'fade', speed = 1000, repeat = 0, dela
3165
3494
  }
3166
3495
  return {};
3167
3496
  };
3168
- const getWaveStyle = () => {
3169
- if (type === 'wave') {
3170
- return {
3171
- '--wave-colors': waveColors.join(', '),
3172
- };
3173
- }
3174
- return {};
3175
- };
3176
3497
  const getGlowStyle = () => {
3177
3498
  if (type === 'glow') {
3178
3499
  return {
@@ -3181,26 +3502,52 @@ const AnimationText = ({ children, type = 'fade', speed = 1000, repeat = 0, dela
3181
3502
  }
3182
3503
  return {};
3183
3504
  };
3184
- const classes = classNames('designbase-animation-text', `designbase-animation-text--${type}`, `designbase-animation-text--${size}`, `designbase-animation-text--${color}`, `designbase-animation-text--${weight}`, `designbase-animation-text--${align}`, `designbase-animation-text--${direction}`, {
3505
+ // For typing, the class should be applied to the inner element to handle caret correctly with ghost element
3506
+ const containerClasses = classNames('designbase-animation-text',
3507
+ // Exclude typing logic from outer container to prevent caret on full-width ghost container
3508
+ type !== 'typing' && `designbase-animation-text--${type}`, `designbase-animation-text--${size}`, `designbase-animation-text--${color}`, `designbase-animation-text--${weight}`, `designbase-animation-text--${align}`, `designbase-animation-text--${direction}`, {
3185
3509
  'designbase-animation-text--visible': isVisible,
3186
3510
  'designbase-animation-text--animating': isAnimating,
3187
- 'designbase-animation-text--clickable': clickable,
3511
+ 'designbase-animation-text--clickable': clickable || trigger === 'click',
3188
3512
  'designbase-animation-text--disabled': disabled,
3189
3513
  }, className);
3190
3514
  const style = {
3191
3515
  ...getGradientStyle(),
3192
- ...getWaveStyle(),
3193
3516
  ...getGlowStyle(),
3194
3517
  '--db-animation-speed': `${speed}ms`,
3195
3518
  '--db-text-custom': customColor,
3519
+ '--db-wave-colors': waveColors.join(', '),
3520
+ '--db-animation-iteration-count': repeat === 0 ? 'infinite' : repeat,
3196
3521
  };
3197
- const renderText = () => {
3198
- if (type === 'typing') {
3199
- return displayText;
3200
- }
3201
- return children;
3202
- };
3203
- return (jsxRuntime.jsx("div", { ref: textRef, className: classes, style: style, onClick: handleClick, children: renderText() }));
3522
+ const renderContent = () => {
3523
+ if (type === 'wave' || type === 'shake') {
3524
+ if (!isVisible && !isAnimating)
3525
+ return children;
3526
+ return children.split('').map((char, index) => (jsxRuntime.jsx("span", { style: {
3527
+ animationDelay: `${index * 0.05}s`,
3528
+ display: 'inline-block'
3529
+ }, children: char === ' ' ? '\u00A0' : char }, index)));
3530
+ }
3531
+ return displayText;
3532
+ };
3533
+ return (jsxRuntime.jsxs("div", { ref: textRef, className: containerClasses, style: style, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [jsxRuntime.jsx("span", { "aria-hidden": "true", style: {
3534
+ visibility: 'hidden',
3535
+ pointerEvents: 'none',
3536
+ userSelect: 'none',
3537
+ whiteSpace: type === 'typing' ? 'pre-wrap' : undefined
3538
+ }, children: children }), jsxRuntime.jsx("span", { className: classNames({
3539
+ 'designbase-animation-text--typing': type === 'typing',
3540
+ 'designbase-animation-text--animating': isAnimating && type === 'typing' // Ensure animating class is passed for typing caret
3541
+ }), style: {
3542
+ position: 'absolute',
3543
+ top: 0,
3544
+ left: 0,
3545
+ // For typing, we want width to be auto so caret follows text
3546
+ // For others, width 100% matches ghost element
3547
+ width: type === 'typing' ? 'auto' : '100%',
3548
+ height: '100%',
3549
+ whiteSpace: type === 'typing' ? 'pre-wrap' : undefined // Ensure pre-wrap behavior matches
3550
+ }, children: renderContent() })] }));
3204
3551
  };
3205
3552
 
3206
3553
  const AudioPlayer = ({ src, title, artist, album, albumArt, size = 'm', variant = 'default', theme = 'auto', autoPlay = false, loop = false, muted = false, showControls = true, enableKeyboard = true, showProgress = true, showTime = true, showVolume = true, showSettings = false, playlist = [], currentIndex = 0, autoPause = true, playbackRates = [0.5, 0.75, 1, 1.25, 1.5, 2], defaultPlaybackRate = 1, repeatMode = 'none', shuffle = false, onPlay, onPause, onEnded, onTimeUpdate, onVolumeChange, onPlaylistChange, onPlaybackRateChange, onRepeatModeChange, onShuffleChange, onError, className, }) => {
@@ -3962,6 +4309,7 @@ SegmentControl.displayName = 'SegmentControl';
3962
4309
 
3963
4310
  const Modal = ({ isOpen, onClose, title, size = 'm', closeOnOutsideClick = true, closeOnEscape = true, children, className, overlayClassName, }) => {
3964
4311
  const modalRef = React.useRef(null);
4312
+ const titleId = React.useId();
3965
4313
  // 아이콘 크기 계산 (m이 기본값)
3966
4314
  const iconSize = size === 's' ? 16 : size === 'l' ? 20 : size === 'xl' ? 24 : 18;
3967
4315
  // Prevent scrolling while modal is open
@@ -3993,11 +4341,11 @@ const Modal = ({ isOpen, onClose, title, size = 'm', closeOnOutsideClick = true,
3993
4341
  return null;
3994
4342
  const modalClasses = clsx('designbase-modal', `designbase-modal--${size}`, className);
3995
4343
  const overlayClasses = clsx('designbase-modal__overlay', overlayClassName);
3996
- return (jsxRuntime.jsx("div", { className: overlayClasses, onClick: closeOnOutsideClick ? onClose : undefined, children: jsxRuntime.jsxs("div", { ref: modalRef, className: modalClasses, onClick: (e) => e.stopPropagation(), role: "dialog", "aria-modal": "true", "aria-labelledby": title ? 'modal-title' : undefined, children: [title && (jsxRuntime.jsx(ModalHeader, { title: title, showCloseButton: true, onClose: onClose, iconSize: iconSize })), jsxRuntime.jsx("div", { className: "designbase-modal__content", children: children })] }) }));
4344
+ return (jsxRuntime.jsx("div", { className: overlayClasses, onClick: closeOnOutsideClick ? onClose : undefined, children: jsxRuntime.jsxs("div", { ref: modalRef, className: modalClasses, onClick: (e) => e.stopPropagation(), role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, children: [title && (jsxRuntime.jsx(ModalHeader, { title: title, titleId: titleId, showCloseButton: true, onClose: onClose, iconSize: iconSize })), jsxRuntime.jsx("div", { className: "designbase-modal__content", children: children })] }) }));
3997
4345
  };
3998
- const ModalHeader = ({ title, showCloseButton = true, onClose, iconSize = 20, className, children, }) => {
4346
+ const ModalHeader = ({ title, titleId, showCloseButton = true, onClose, iconSize = 20, className, children, }) => {
3999
4347
  const classes = clsx('designbase-modal__header', className);
4000
- return (jsxRuntime.jsxs("div", { className: classes, children: [jsxRuntime.jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsxRuntime.jsx("h2", { id: "modal-title", className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsxRuntime.jsx(icons.CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4348
+ return (jsxRuntime.jsxs("div", { className: classes, children: [jsxRuntime.jsxs("div", { className: "designbase-modal__header-content", children: [title && (jsxRuntime.jsx("h2", { id: titleId || 'modal-title', className: "designbase-modal__title", children: title })), children] }), showCloseButton && onClose && (jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": "\uBAA8\uB2EC \uB2EB\uAE30", className: "designbase-modal__close-button", children: jsxRuntime.jsx(icons.CloseIcon, { size: iconSize, color: "currentColor" }) }))] }));
4001
4349
  };
4002
4350
  const ModalBody = ({ className, children, }) => {
4003
4351
  const classes = clsx('designbase-modal__body', className);
@@ -4255,11 +4603,12 @@ const SearchBar = ({ value, defaultValue = '', placeholder = '검색...', size =
4255
4603
  };
4256
4604
  SearchBar.displayName = 'SearchBar';
4257
4605
 
4258
- const Select = ({ value, defaultValue, options, label, placeholder = '선택하세요', multiple = false, searchable = false, disabled = false, readOnly = false, required = false, error = false, errorMessage, helperText, size = 'm', fullWidth = false, dropdownWidth = 'auto', position = 'bottom', maxHeight = 200, showClearButton = true, className, onChange, onFocus, onBlur, ...props }) => {
4606
+ const Select = ({ value, defaultValue, options, label, placeholder = '선택하세요', multiple = false, searchable = false, disabled = false, readOnly = false, required = false, error = false, errorMessage, helperText, size = 'm', fullWidth = false, dropdownWidth = 'auto', position = 'bottom', maxHeight = 200, showClearButton = true, useMobileBottomSheet = false, className, onChange, onFocus, onBlur, ...props }) => {
4259
4607
  const [isOpen, setIsOpen] = React.useState(false);
4260
4608
  const [selectedValue, setSelectedValue] = React.useState(value ?? defaultValue ?? (multiple ? [] : ''));
4261
4609
  const [searchTerm, setSearchTerm] = React.useState('');
4262
4610
  const [focusedIndex, setFocusedIndex] = React.useState(-1);
4611
+ const labelId = React.useId();
4263
4612
  const containerRef = React.useRef(null);
4264
4613
  const inputRef = React.useRef(null);
4265
4614
  const dropdownRef = React.useRef(null);
@@ -4414,11 +4763,12 @@ const Select = ({ value, defaultValue, options, label, placeholder = '선택하
4414
4763
  });
4415
4764
  const dropdownClasses = clsx('designbase-select__dropdown', `designbase-select__dropdown--${dropdownWidth}`, `designbase-select__dropdown--${position}`, {
4416
4765
  'designbase-select__dropdown--open': isOpen,
4766
+ 'designbase-select__dropdown--mobile-sheet': useMobileBottomSheet,
4417
4767
  });
4418
4768
  const filteredOptions = getFilteredOptions();
4419
4769
  const selectedLabels = getSelectedLabels();
4420
4770
  const hasValue = multiple ? selectedValue.length > 0 : selectedValue !== '';
4421
- return (jsxRuntime.jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { className: "designbase-select__label", children: [label, required && jsxRuntime.jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxRuntime.jsxs("div", { className: triggerClasses, onClick: handleToggle, onFocus: onFocus, onBlur: onBlur, tabIndex: disabled || readOnly ? -1 : 0, role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-labelledby": label ? 'select-label' : undefined, ...props, children: [jsxRuntime.jsx("div", { className: "designbase-select__value", children: multiple ? (jsxRuntime.jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4771
+ return (jsxRuntime.jsxs("div", { className: classes, ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { id: labelId, className: "designbase-select__label", children: [label, required && jsxRuntime.jsx("span", { className: "designbase-select__required", children: "*" })] })), jsxRuntime.jsxs("div", { className: triggerClasses, onClick: handleToggle, onFocus: onFocus, onBlur: onBlur, tabIndex: disabled || readOnly ? -1 : 0, role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-labelledby": label ? labelId : undefined, ...props, children: [jsxRuntime.jsx("div", { className: "designbase-select__value", children: multiple ? (jsxRuntime.jsx("div", { className: "designbase-select__tags", ref: tagsContainerRef, children: selectedValue.map((value) => {
4422
4772
  const option = options.find(opt => opt.value === value);
4423
4773
  return (jsxRuntime.jsxs("span", { className: "designbase-select__tag", children: [jsxRuntime.jsx("span", { className: "designbase-select__tag-label", children: option?.label || value }), jsxRuntime.jsx("button", { type: "button", className: "designbase-select__tag-remove", onClick: (e) => {
4424
4774
  e.stopPropagation();
@@ -5038,7 +5388,7 @@ const Card = React.forwardRef(function Card({ title, subtitle, description, chil
5038
5388
  return null;
5039
5389
  return (jsxRuntime.jsx("div", { className: "designbase-card__actions", children: actions.map((action, index) => {
5040
5390
  const ActionIcon = action.icon;
5041
- return (jsxRuntime.jsx(Button, { variant: action.variant || 'primary', size: action.size || 's', onClick: () => handleActionClick(action, index), disabled: action.disabled || disabled, loading: !!action.loading, icon: ActionIcon, children: action.label }, index));
5391
+ return (jsxRuntime.jsx(Button, { variant: action.variant || 'primary', size: action.size || 's', onClick: () => handleActionClick(action, index), disabled: action.disabled || disabled, loading: !!action.loading, startIcon: ActionIcon, children: action.label }, index));
5042
5392
  }) }));
5043
5393
  };
5044
5394
  const renderContent = () => (jsxRuntime.jsxs("div", { className: "designbase-card__content", children: [renderIcon(), (title || subtitle) && (jsxRuntime.jsxs("div", { className: "designbase-card__header", children: [title && jsxRuntime.jsx("h3", { className: "designbase-card__title", children: title }), subtitle && jsxRuntime.jsx("p", { className: "designbase-card__subtitle", children: subtitle })] })), description && jsxRuntime.jsx("p", { className: "designbase-card__description", children: description }), children && jsxRuntime.jsx("div", { className: "designbase-card__body", children: children }), renderTags(), renderMeta(), renderActions()] }));
@@ -7814,7 +8164,7 @@ const Stat = ({ value, label, icon, iconPosition = 'left', size = 'm', variant =
7814
8164
  return;
7815
8165
  onClick?.();
7816
8166
  };
7817
- return (jsxRuntime.jsxs("div", { className: classes, style: customStyle, onClick: handleClick, role: clickable ? 'button' : undefined, tabIndex: clickable ? 0 : undefined, children: [icon && (jsxRuntime.jsx("div", { className: clsx('designbase-stat__icon', `designbase-stat__icon--${iconPosition}`), children: icon })), jsxRuntime.jsxs("div", { className: "designbase-stat__content", children: [jsxRuntime.jsxs("div", { className: "designbase-stat__main", children: [jsxRuntime.jsx("div", { className: "designbase-stat__value", children: value }), jsxRuntime.jsx("div", { className: "designbase-stat__label", children: label })] }), showChange && change && (jsxRuntime.jsx("div", { className: clsx('designbase-stat__change', getChangeClass()), children: getChangeText() })), showDescription && description && (jsxRuntime.jsx("div", { className: "designbase-stat__description", children: description }))] }), showProgress && typeof progress === 'number' && (jsxRuntime.jsx("div", { className: "designbase-stat__progress", children: jsxRuntime.jsx(Progressbar, { value: Math.min(Math.max(progress, 0), 100), size: "s", variant: color === 'primary' ? 'primary' : color === 'success' ? 'success' : color === 'warning' ? 'warning' : color === 'error' ? 'danger' : 'default' }) }))] }));
8167
+ return (jsxRuntime.jsxs("div", { className: classes, style: customStyle, onClick: handleClick, role: clickable ? 'button' : undefined, tabIndex: clickable ? 0 : undefined, children: [icon && (jsxRuntime.jsx("div", { className: clsx('designbase-stat__icon', `designbase-stat__icon--${iconPosition}`), children: icon })), jsxRuntime.jsxs("div", { className: "designbase-stat__content", children: [jsxRuntime.jsx("div", { className: "designbase-stat__main", children: variant === 'iconBox' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "designbase-stat__label", children: label }), jsxRuntime.jsx("div", { className: "designbase-stat__value", children: value })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "designbase-stat__value", children: value }), jsxRuntime.jsx("div", { className: "designbase-stat__label", children: label })] })) }), showChange && change && (jsxRuntime.jsx("div", { className: clsx('designbase-stat__change', getChangeClass()), children: getChangeText() })), showDescription && description && (jsxRuntime.jsx("div", { className: "designbase-stat__description", children: description }))] }), showProgress && typeof progress === 'number' && (jsxRuntime.jsx("div", { className: "designbase-stat__progress", children: jsxRuntime.jsx(Progressbar, { value: Math.min(Math.max(progress, 0), 100), size: "s", variant: color === 'primary' ? 'primary' : color === 'success' ? 'success' : color === 'warning' ? 'warning' : color === 'error' ? 'danger' : 'default' }) }))] }));
7818
8168
  };
7819
8169
 
7820
8170
  const HeroFeature = ({ title, subtitle, description, image, imageAlt, backgroundImage, backgroundVideo, overlayColor, overlayOpacity = 0.5, buttons = [], badge, stats = [], icon, size = 'l', variant = 'default', theme = 'light', alignment = 'left', animated = false, parallax = false, fullHeight = false, minHeight, maxHeight, className, }) => {
@@ -10666,7 +11016,7 @@ const Share = ({ url, title, description = '', imageUrl, hashtags = [], variant
10666
11016
  }
10667
11017
  };
10668
11018
 
10669
- const Sidebar = ({ size = 'm', variant = 'default', position = 'left', logo, onLogoClick, items = [], onItemClick, userProfile, userMenuItems = [], onUserMenuItemClick, collapsed = false, onToggle, collapsible = true, fixed = false, fullHeight = false, shadow = false, className, ...props }) => {
11019
+ const Sidebar = ({ size = 'm', variant = 'default', position = 'left', showLogo = false, logo, onLogoClick, items = [], onItemClick, userProfile, userMenuItems = [], onUserMenuItemClick, collapsed = false, onToggle, collapsible = true, fixed = false, fullHeight = false, shadow = false, className, ...props }) => {
10670
11020
  const [expandedItems, setExpandedItems] = React.useState([]);
10671
11021
  const handleToggle = () => {
10672
11022
  if (onToggle) {
@@ -10707,24 +11057,24 @@ const Sidebar = ({ size = 'm', variant = 'default', position = 'left', logo, onL
10707
11057
  const hasChildren = item.children && item.children.length > 0;
10708
11058
  return (jsxRuntime.jsx("li", { className: "designbase-sidebar__item", children: jsxRuntime.jsx(MenuItem, { ...item, type: "block", style: "accordion", depth: level, expanded: isExpanded, expandable: hasChildren, onClick: () => handleItemClick(item), onChildClick: (child) => handleItemClick(child) }) }, item.id));
10709
11059
  };
10710
- return (jsxRuntime.jsx("aside", { className: classes, role: "complementary", "aria-label": "\uC0AC\uC774\uB4DC\uBC14 \uB124\uBE44\uAC8C\uC774\uC158", ...props, children: jsxRuntime.jsxs("div", { className: "designbase-sidebar__container", children: [jsxRuntime.jsxs("div", { className: "designbase-sidebar__header", children: [jsxRuntime.jsx("div", { className: "designbase-sidebar__logo", onClick: onLogoClick, role: onLogoClick ? 'button' : undefined, tabIndex: onLogoClick ? 0 : undefined, onKeyDown: (e) => {
11060
+ return (jsxRuntime.jsx("aside", { className: classes, role: "complementary", "aria-label": "\uC0AC\uC774\uB4DC\uBC14 \uB124\uBE44\uAC8C\uC774\uC158", ...props, children: jsxRuntime.jsxs("div", { className: "designbase-sidebar__container", children: [showLogo && (jsxRuntime.jsxs("div", { className: "designbase-sidebar__header", children: [jsxRuntime.jsx("div", { className: "designbase-sidebar__logo", onClick: onLogoClick, role: onLogoClick ? 'button' : undefined, tabIndex: onLogoClick ? 0 : undefined, onKeyDown: (e) => {
10711
11061
  if (onLogoClick && (e.key === 'Enter' || e.key === ' ')) {
10712
11062
  e.preventDefault();
10713
11063
  onLogoClick();
10714
11064
  }
10715
11065
  }, children: logo || jsxRuntime.jsx(Logo, { size: "s" }) }), collapsible && (jsxRuntime.jsx(Button, { variant: "ghost", size: "s", iconOnly: true, className: "designbase-sidebar__toggle", onPress: handleToggle, "aria-label": collapsed ? '사이드바 펼치기' : '사이드바 접기', children: jsxRuntime.jsx(icons.ChevronLeftIcon, { className: clsx('designbase-sidebar__toggle-icon', {
10716
11066
  'designbase-sidebar__toggle-icon--collapsed': collapsed,
10717
- }) }) }))] }), jsxRuntime.jsx("nav", { className: "designbase-sidebar__nav", children: jsxRuntime.jsx("ul", { className: "designbase-sidebar__nav-list", children: items.map((item) => renderSidebarItem(item)) }) }), userProfile && !collapsed && (jsxRuntime.jsxs("div", { className: "designbase-sidebar__user", children: [jsxRuntime.jsxs("div", { className: "designbase-sidebar__user-info", onClick: () => onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' }), role: "button", tabIndex: 0, onKeyDown: (e) => {
11067
+ }) }) }))] })), jsxRuntime.jsx("nav", { className: "designbase-sidebar__nav", children: jsxRuntime.jsx("ul", { className: "designbase-sidebar__nav-list", children: items.map((item) => renderSidebarItem(item)) }) }), userProfile && !collapsed && (jsxRuntime.jsxs("div", { className: "designbase-sidebar__user", children: [jsxRuntime.jsxs("div", { className: "designbase-sidebar__user-info", onClick: () => onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' }), role: "button", tabIndex: 0, onKeyDown: (e) => {
10718
11068
  if (e.key === 'Enter' || e.key === ' ') {
10719
11069
  e.preventDefault();
10720
11070
  onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' });
10721
11071
  }
10722
- }, style: { cursor: 'pointer' }, children: [userProfile.avatar ? (jsxRuntime.jsx("img", { src: userProfile.avatar, alt: userProfile.name, className: "designbase-sidebar__user-avatar" })) : (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-avatar-placeholder", children: userProfile.name.charAt(0).toUpperCase() })), jsxRuntime.jsxs("div", { className: "designbase-sidebar__user-details", children: [jsxRuntime.jsx("div", { className: "designbase-sidebar__user-name", children: userProfile.name }), userProfile.email && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-email", children: userProfile.email })), userProfile.role && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-role", children: userProfile.role }))] })] }), userMenuItems.length > 0 && (jsxRuntime.jsx("ul", { className: "designbase-sidebar__user-menu", children: userMenuItems.map((item) => (jsxRuntime.jsx("li", { children: jsxRuntime.jsx(MenuItem, { id: item.id, label: item.label, href: item.href, icon: item.icon, disabled: item.disabled, type: "block", style: "accordion", onClick: () => handleUserMenuItemClick(item) }) }, item.id))) }))] })), userProfile && collapsed && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-collapsed", onClick: () => onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' }), role: "button", tabIndex: 0, onKeyDown: (e) => {
11072
+ }, style: { cursor: 'pointer' }, children: [jsxRuntime.jsx(Avatar, { src: userProfile.avatar, initials: userProfile.name, alt: userProfile.name, size: "s", className: "designbase-sidebar__user-avatar" }), jsxRuntime.jsxs("div", { className: "designbase-sidebar__user-details", children: [jsxRuntime.jsx("div", { className: "designbase-sidebar__user-name", children: userProfile.name }), userProfile.email && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-email", children: userProfile.email })), userProfile.role && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-role", children: userProfile.role }))] })] }), userMenuItems.length > 0 && (jsxRuntime.jsx("ul", { className: "designbase-sidebar__user-menu", children: userMenuItems.map((item) => (jsxRuntime.jsx("li", { children: jsxRuntime.jsx(MenuItem, { id: item.id, label: item.label, href: item.href, icon: item.icon, disabled: item.disabled, type: "block", style: "accordion", onClick: () => handleUserMenuItemClick(item) }) }, item.id))) }))] })), userProfile && collapsed && (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-collapsed", onClick: () => onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' }), role: "button", tabIndex: 0, onKeyDown: (e) => {
10723
11073
  if (e.key === 'Enter' || e.key === ' ') {
10724
11074
  e.preventDefault();
10725
11075
  onUserMenuItemClick?.({ id: 'profile', label: '프로필', href: '#' });
10726
11076
  }
10727
- }, style: { cursor: 'pointer' }, children: userProfile.avatar ? (jsxRuntime.jsx("img", { src: userProfile.avatar, alt: userProfile.name, className: "designbase-sidebar__user-avatar-collapsed" })) : (jsxRuntime.jsx("div", { className: "designbase-sidebar__user-avatar-placeholder-collapsed", children: userProfile.name.charAt(0).toUpperCase() })) }))] }) }));
11077
+ }, style: { cursor: 'pointer' }, children: jsxRuntime.jsx(Avatar, { src: userProfile.avatar, initials: userProfile.name, alt: userProfile.name, size: "s", className: "designbase-sidebar__user-avatar-collapsed" }) }))] }) }));
10728
11078
  };
10729
11079
  Sidebar.displayName = 'Sidebar';
10730
11080
 
@@ -11492,7 +11842,7 @@ const Toast = ({ id, status = 'info', title, description, icon: Icon, duration =
11492
11842
  // 기본 상태 아이콘 (아이콘 패키지에서 가져온 아이콘 사용)
11493
11843
  const iconMap = {
11494
11844
  success: icons.CircleCheckFilledIcon,
11495
- error: icons.DeleteIcon,
11845
+ error: icons.ErrorIcon,
11496
11846
  warning: icons.WarningIcon,
11497
11847
  info: icons.InfoIcon,
11498
11848
  };
@@ -12159,25 +12509,18 @@ const YouTubePlayer = ({ videoId, title, description, size = 'm', variant = 'def
12159
12509
  };
12160
12510
  YouTubePlayer.displayName = 'YouTubePlayer';
12161
12511
 
12162
- /**
12163
- * Designbase UI 컴포넌트 라이브러리 메인 엔트리 포인트
12164
- *
12165
- * 목적: 모든 UI 컴포넌트와 타입을 내보냄
12166
- * 기능: Tree-shaking 가능한 개별 컴포넌트 내보내기
12167
- * 사용법: import { Button, Input } from '@designbasekorea/ui'
12168
- */
12169
- // 테마 CSS 자동 로드 (로컬 복사본 사용)
12170
- // 테마 관련 유틸리티 재내보내기
12171
- const setTheme = (theme) => {
12172
- console.log('setTheme called with:', theme);
12173
- };
12174
- const getTheme = () => {
12175
- return 'light';
12176
- };
12177
- const toggleTheme = () => {
12178
- console.log('toggleTheme called');
12179
- };
12180
-
12512
+ Object.defineProperty(exports, 'getTheme', {
12513
+ enumerable: true,
12514
+ get: function () { return theme.getTheme; }
12515
+ });
12516
+ Object.defineProperty(exports, 'setTheme', {
12517
+ enumerable: true,
12518
+ get: function () { return theme.setTheme; }
12519
+ });
12520
+ Object.defineProperty(exports, 'toggleTheme', {
12521
+ enumerable: true,
12522
+ get: function () { return theme.toggleTheme; }
12523
+ });
12181
12524
  exports.Accordion = Accordion;
12182
12525
  exports.AdBanner = AdBanner;
12183
12526
  exports.Alert = Alert;
@@ -12270,8 +12613,5 @@ exports.Tooltip = Tooltip;
12270
12613
  exports.Tutorial = Tutorial;
12271
12614
  exports.VideoPlayer = VideoPlayer;
12272
12615
  exports.YouTubePlayer = YouTubePlayer;
12273
- exports.getTheme = getTheme;
12274
- exports.setTheme = setTheme;
12275
- exports.toggleTheme = toggleTheme;
12276
12616
  exports.useToast = useToast;
12277
12617
  //# sourceMappingURL=index.js.map