@adstage/web-sdk 2.2.1 โ†’ 2.2.3

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.cjs.js CHANGED
@@ -392,18 +392,23 @@ class BaseAdRenderer {
392
392
  getImageStyles(slot) {
393
393
  const styles = {
394
394
  display: 'block',
395
- 'max-width': '100%',
396
- height: 'auto',
397
395
  'object-position': 'center', // ๐ŸŽฏ ์ด๋ฏธ์ง€ ํ•ญ์ƒ ์ค‘์•™ ์ •๋ ฌ
398
396
  };
399
- // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํฌ๊ธฐ ์ œํ•œ
397
+ // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
400
398
  const parsedWidth = this.parseSizeValue(slot?.width);
401
399
  const parsedHeight = this.parseSizeValue(slot?.height);
402
- if (parsedWidth && parsedHeight) {
400
+ const hasUserDefinedSize = parsedWidth || parsedHeight;
401
+ if (hasUserDefinedSize) {
402
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
403
403
  styles.width = '100%';
404
404
  styles.height = '100%';
405
- styles['object-fit'] = 'cover';
406
- styles['object-position'] = 'center'; // ๐ŸŽฏ ํฌ๊ธฐ ์กฐ์ • ์‹œ์—๋„ ์ค‘์•™ ์ •๋ ฌ
405
+ styles['object-fit'] = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
406
+ styles['object-position'] = 'center';
407
+ }
408
+ else {
409
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์œ ์ง€
410
+ styles['max-width'] = '100%';
411
+ styles.height = 'auto';
407
412
  }
408
413
  return styles;
409
414
  }
@@ -911,7 +916,7 @@ class CarouselSliderManager {
911
916
  let currentSlide = 0;
912
917
  const totalSlides = advertisements.length;
913
918
  const autoSlideInterval = (options?.autoSlideInterval || 3) * 1000; // ๊ธฐ๋ณธ 3์ดˆ
914
- // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์›)
919
+ // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์› + ๋™์  ๋†’์ด ์กฐ์ •)
915
920
  const moveToSlide = (index, instant = false) => {
916
921
  currentSlide = index;
917
922
  // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ž„์‹œ ๋น„ํ™œ์„ฑํ™” (๋ฌดํ•œ ๋ฃจํ”„์šฉ)
@@ -923,6 +928,33 @@ class CarouselSliderManager {
923
928
  }
924
929
  // ํ•ญ์ƒ ํผ์„ผํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋™
925
930
  slideContainer.style.transform = `translateX(-${(100 / extendedAds.length) * currentSlide}%)`;
931
+ // ๐Ÿ†• ๋™์  ๋†’์ด ์กฐ์ •: ํ˜„์žฌ ์Šฌ๋ผ์ด๋“œ์˜ ์ด๋ฏธ์ง€ ๋†’์ด์— ๋งž์ถฐ ์ปจํ…Œ์ด๋„ˆ ๋†’์ด ์กฐ์ •
932
+ if (!instant && !slot.height && !slot.width) { // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ
933
+ const currentSlideElement = slideContainer.children[currentSlide];
934
+ if (currentSlideElement) {
935
+ const currentAdElement = currentSlideElement.children[0];
936
+ if (currentAdElement) {
937
+ // ์ด๋ฏธ์ง€ ์š”์†Œ ์ฐพ๊ธฐ
938
+ const imgElement = currentAdElement.querySelector('img');
939
+ if (imgElement) {
940
+ // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ํ›„ ๋†’์ด ์กฐ์ •
941
+ const adjustHeight = () => {
942
+ const imgHeight = imgElement.getBoundingClientRect().height;
943
+ if (imgHeight > 0) {
944
+ sliderWrapper.style.height = `${imgHeight}px`;
945
+ sliderWrapper.style.transition = instant ? 'none' : 'height 0.4s ease-out';
946
+ }
947
+ };
948
+ if (imgElement.complete && imgElement.naturalHeight > 0) {
949
+ adjustHeight();
950
+ }
951
+ else {
952
+ imgElement.addEventListener('load', adjustHeight, { once: true });
953
+ }
954
+ }
955
+ }
956
+ }
957
+ }
926
958
  // ๋„ํŠธ ์—…๋ฐ์ดํŠธ (๋ฌด์ฑ„์ƒ‰ ์Šคํƒ€์ผ) - ์‹ค์ œ ๊ด‘๊ณ  ์ธ๋ฑ์Šค ๊ธฐ์ค€, ํ…์ŠคํŠธ ๊ด‘๊ณ ๊ฐ€ ์•„๋‹ ๋•Œ๋งŒ
927
959
  const actualIndex = currentSlide === totalSlides ? 0 : currentSlide;
928
960
  if (dotContainer) {
@@ -2886,23 +2918,45 @@ class AdsModule {
2886
2918
  */
2887
2919
  async renderOptimizedBannerImage(adElement, ad, slot) {
2888
2920
  try {
2889
- // ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์ •๋ณด ๋กœ๋“œ
2890
- const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2891
- const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2892
- // ์ปจํ…Œ์ด๋„ˆ ๋น„์œจ ๊ณ„์‚ฐ
2893
- const containerAspectRatio = slot.aspectRatio || 16 / 9;
2921
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
2922
+ const configWidth = slot.config?.width;
2923
+ const configHeight = slot.config?.height;
2924
+ const hasUserDefinedWidth = configWidth &&
2925
+ (typeof configWidth === 'number' || (typeof configWidth === 'string' && configWidth !== '100%'));
2926
+ const hasUserDefinedHeight = configHeight &&
2927
+ (typeof configHeight === 'number' || (typeof configHeight === 'string' && configHeight !== 'auto'));
2928
+ const hasUserDefinedSize = hasUserDefinedWidth || hasUserDefinedHeight;
2894
2929
  // ์ด๋ฏธ์ง€ ์š”์†Œ ์ƒ์„ฑ
2895
2930
  const img = document.createElement('img');
2896
2931
  img.src = ad.imageUrl;
2897
2932
  img.alt = ad.title;
2898
- img.style.width = '100%';
2899
- img.style.height = '100%';
2900
- // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2901
- this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2933
+ if (hasUserDefinedSize) {
2934
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
2935
+ img.style.width = '100%';
2936
+ img.style.height = '100%';
2937
+ img.style.objectFit = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
2938
+ img.style.objectPosition = 'center';
2939
+ if (this._config?.debug) {
2940
+ console.log(`๐ŸŽฏ User-defined size detected: filling container completely`);
2941
+ }
2942
+ }
2943
+ else {
2944
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ๋™์  ์ตœ์ ํ™” ์ ์šฉ
2945
+ const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2946
+ const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2947
+ const containerAspectRatio = slot.aspectRatio || 16 / 9;
2948
+ img.style.width = '100%';
2949
+ img.style.height = '100%';
2950
+ // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2951
+ this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2952
+ if (this._config?.debug) {
2953
+ console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2954
+ }
2955
+ }
2902
2956
  // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ์ฒ˜๋ฆฌ
2903
2957
  img.onload = () => {
2904
2958
  if (this._config?.debug) {
2905
- console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2959
+ console.log(`โœ… Banner image loaded successfully`);
2906
2960
  }
2907
2961
  };
2908
2962
  // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
package/dist/index.esm.js CHANGED
@@ -390,18 +390,23 @@ class BaseAdRenderer {
390
390
  getImageStyles(slot) {
391
391
  const styles = {
392
392
  display: 'block',
393
- 'max-width': '100%',
394
- height: 'auto',
395
393
  'object-position': 'center', // ๐ŸŽฏ ์ด๋ฏธ์ง€ ํ•ญ์ƒ ์ค‘์•™ ์ •๋ ฌ
396
394
  };
397
- // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํฌ๊ธฐ ์ œํ•œ
395
+ // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
398
396
  const parsedWidth = this.parseSizeValue(slot?.width);
399
397
  const parsedHeight = this.parseSizeValue(slot?.height);
400
- if (parsedWidth && parsedHeight) {
398
+ const hasUserDefinedSize = parsedWidth || parsedHeight;
399
+ if (hasUserDefinedSize) {
400
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
401
401
  styles.width = '100%';
402
402
  styles.height = '100%';
403
- styles['object-fit'] = 'cover';
404
- styles['object-position'] = 'center'; // ๐ŸŽฏ ํฌ๊ธฐ ์กฐ์ • ์‹œ์—๋„ ์ค‘์•™ ์ •๋ ฌ
403
+ styles['object-fit'] = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
404
+ styles['object-position'] = 'center';
405
+ }
406
+ else {
407
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์œ ์ง€
408
+ styles['max-width'] = '100%';
409
+ styles.height = 'auto';
405
410
  }
406
411
  return styles;
407
412
  }
@@ -909,7 +914,7 @@ class CarouselSliderManager {
909
914
  let currentSlide = 0;
910
915
  const totalSlides = advertisements.length;
911
916
  const autoSlideInterval = (options?.autoSlideInterval || 3) * 1000; // ๊ธฐ๋ณธ 3์ดˆ
912
- // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์›)
917
+ // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์› + ๋™์  ๋†’์ด ์กฐ์ •)
913
918
  const moveToSlide = (index, instant = false) => {
914
919
  currentSlide = index;
915
920
  // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ž„์‹œ ๋น„ํ™œ์„ฑํ™” (๋ฌดํ•œ ๋ฃจํ”„์šฉ)
@@ -921,6 +926,33 @@ class CarouselSliderManager {
921
926
  }
922
927
  // ํ•ญ์ƒ ํผ์„ผํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋™
923
928
  slideContainer.style.transform = `translateX(-${(100 / extendedAds.length) * currentSlide}%)`;
929
+ // ๐Ÿ†• ๋™์  ๋†’์ด ์กฐ์ •: ํ˜„์žฌ ์Šฌ๋ผ์ด๋“œ์˜ ์ด๋ฏธ์ง€ ๋†’์ด์— ๋งž์ถฐ ์ปจํ…Œ์ด๋„ˆ ๋†’์ด ์กฐ์ •
930
+ if (!instant && !slot.height && !slot.width) { // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ
931
+ const currentSlideElement = slideContainer.children[currentSlide];
932
+ if (currentSlideElement) {
933
+ const currentAdElement = currentSlideElement.children[0];
934
+ if (currentAdElement) {
935
+ // ์ด๋ฏธ์ง€ ์š”์†Œ ์ฐพ๊ธฐ
936
+ const imgElement = currentAdElement.querySelector('img');
937
+ if (imgElement) {
938
+ // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ํ›„ ๋†’์ด ์กฐ์ •
939
+ const adjustHeight = () => {
940
+ const imgHeight = imgElement.getBoundingClientRect().height;
941
+ if (imgHeight > 0) {
942
+ sliderWrapper.style.height = `${imgHeight}px`;
943
+ sliderWrapper.style.transition = instant ? 'none' : 'height 0.4s ease-out';
944
+ }
945
+ };
946
+ if (imgElement.complete && imgElement.naturalHeight > 0) {
947
+ adjustHeight();
948
+ }
949
+ else {
950
+ imgElement.addEventListener('load', adjustHeight, { once: true });
951
+ }
952
+ }
953
+ }
954
+ }
955
+ }
924
956
  // ๋„ํŠธ ์—…๋ฐ์ดํŠธ (๋ฌด์ฑ„์ƒ‰ ์Šคํƒ€์ผ) - ์‹ค์ œ ๊ด‘๊ณ  ์ธ๋ฑ์Šค ๊ธฐ์ค€, ํ…์ŠคํŠธ ๊ด‘๊ณ ๊ฐ€ ์•„๋‹ ๋•Œ๋งŒ
925
957
  const actualIndex = currentSlide === totalSlides ? 0 : currentSlide;
926
958
  if (dotContainer) {
@@ -2884,23 +2916,45 @@ class AdsModule {
2884
2916
  */
2885
2917
  async renderOptimizedBannerImage(adElement, ad, slot) {
2886
2918
  try {
2887
- // ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์ •๋ณด ๋กœ๋“œ
2888
- const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2889
- const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2890
- // ์ปจํ…Œ์ด๋„ˆ ๋น„์œจ ๊ณ„์‚ฐ
2891
- const containerAspectRatio = slot.aspectRatio || 16 / 9;
2919
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
2920
+ const configWidth = slot.config?.width;
2921
+ const configHeight = slot.config?.height;
2922
+ const hasUserDefinedWidth = configWidth &&
2923
+ (typeof configWidth === 'number' || (typeof configWidth === 'string' && configWidth !== '100%'));
2924
+ const hasUserDefinedHeight = configHeight &&
2925
+ (typeof configHeight === 'number' || (typeof configHeight === 'string' && configHeight !== 'auto'));
2926
+ const hasUserDefinedSize = hasUserDefinedWidth || hasUserDefinedHeight;
2892
2927
  // ์ด๋ฏธ์ง€ ์š”์†Œ ์ƒ์„ฑ
2893
2928
  const img = document.createElement('img');
2894
2929
  img.src = ad.imageUrl;
2895
2930
  img.alt = ad.title;
2896
- img.style.width = '100%';
2897
- img.style.height = '100%';
2898
- // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2899
- this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2931
+ if (hasUserDefinedSize) {
2932
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
2933
+ img.style.width = '100%';
2934
+ img.style.height = '100%';
2935
+ img.style.objectFit = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
2936
+ img.style.objectPosition = 'center';
2937
+ if (this._config?.debug) {
2938
+ console.log(`๐ŸŽฏ User-defined size detected: filling container completely`);
2939
+ }
2940
+ }
2941
+ else {
2942
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ๋™์  ์ตœ์ ํ™” ์ ์šฉ
2943
+ const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2944
+ const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2945
+ const containerAspectRatio = slot.aspectRatio || 16 / 9;
2946
+ img.style.width = '100%';
2947
+ img.style.height = '100%';
2948
+ // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2949
+ this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2950
+ if (this._config?.debug) {
2951
+ console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2952
+ }
2953
+ }
2900
2954
  // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ์ฒ˜๋ฆฌ
2901
2955
  img.onload = () => {
2902
2956
  if (this._config?.debug) {
2903
- console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2957
+ console.log(`โœ… Banner image loaded successfully`);
2904
2958
  }
2905
2959
  };
2906
2960
  // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
@@ -390,18 +390,23 @@ class BaseAdRenderer {
390
390
  getImageStyles(slot) {
391
391
  const styles = {
392
392
  display: 'block',
393
- 'max-width': '100%',
394
- height: 'auto',
395
393
  'object-position': 'center', // ๐ŸŽฏ ์ด๋ฏธ์ง€ ํ•ญ์ƒ ์ค‘์•™ ์ •๋ ฌ
396
394
  };
397
- // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํฌ๊ธฐ ์ œํ•œ
395
+ // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
398
396
  const parsedWidth = this.parseSizeValue(slot?.width);
399
397
  const parsedHeight = this.parseSizeValue(slot?.height);
400
- if (parsedWidth && parsedHeight) {
398
+ const hasUserDefinedSize = parsedWidth || parsedHeight;
399
+ if (hasUserDefinedSize) {
400
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
401
401
  styles.width = '100%';
402
402
  styles.height = '100%';
403
- styles['object-fit'] = 'cover';
404
- styles['object-position'] = 'center'; // ๐ŸŽฏ ํฌ๊ธฐ ์กฐ์ • ์‹œ์—๋„ ์ค‘์•™ ์ •๋ ฌ
403
+ styles['object-fit'] = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
404
+ styles['object-position'] = 'center';
405
+ }
406
+ else {
407
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์œ ์ง€
408
+ styles['max-width'] = '100%';
409
+ styles.height = 'auto';
405
410
  }
406
411
  return styles;
407
412
  }
@@ -909,7 +914,7 @@ class CarouselSliderManager {
909
914
  let currentSlide = 0;
910
915
  const totalSlides = advertisements.length;
911
916
  const autoSlideInterval = (options?.autoSlideInterval || 3) * 1000; // ๊ธฐ๋ณธ 3์ดˆ
912
- // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์›)
917
+ // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์› + ๋™์  ๋†’์ด ์กฐ์ •)
913
918
  const moveToSlide = (index, instant = false) => {
914
919
  currentSlide = index;
915
920
  // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ž„์‹œ ๋น„ํ™œ์„ฑํ™” (๋ฌดํ•œ ๋ฃจํ”„์šฉ)
@@ -921,6 +926,33 @@ class CarouselSliderManager {
921
926
  }
922
927
  // ํ•ญ์ƒ ํผ์„ผํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋™
923
928
  slideContainer.style.transform = `translateX(-${(100 / extendedAds.length) * currentSlide}%)`;
929
+ // ๐Ÿ†• ๋™์  ๋†’์ด ์กฐ์ •: ํ˜„์žฌ ์Šฌ๋ผ์ด๋“œ์˜ ์ด๋ฏธ์ง€ ๋†’์ด์— ๋งž์ถฐ ์ปจํ…Œ์ด๋„ˆ ๋†’์ด ์กฐ์ •
930
+ if (!instant && !slot.height && !slot.width) { // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ
931
+ const currentSlideElement = slideContainer.children[currentSlide];
932
+ if (currentSlideElement) {
933
+ const currentAdElement = currentSlideElement.children[0];
934
+ if (currentAdElement) {
935
+ // ์ด๋ฏธ์ง€ ์š”์†Œ ์ฐพ๊ธฐ
936
+ const imgElement = currentAdElement.querySelector('img');
937
+ if (imgElement) {
938
+ // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ํ›„ ๋†’์ด ์กฐ์ •
939
+ const adjustHeight = () => {
940
+ const imgHeight = imgElement.getBoundingClientRect().height;
941
+ if (imgHeight > 0) {
942
+ sliderWrapper.style.height = `${imgHeight}px`;
943
+ sliderWrapper.style.transition = instant ? 'none' : 'height 0.4s ease-out';
944
+ }
945
+ };
946
+ if (imgElement.complete && imgElement.naturalHeight > 0) {
947
+ adjustHeight();
948
+ }
949
+ else {
950
+ imgElement.addEventListener('load', adjustHeight, { once: true });
951
+ }
952
+ }
953
+ }
954
+ }
955
+ }
924
956
  // ๋„ํŠธ ์—…๋ฐ์ดํŠธ (๋ฌด์ฑ„์ƒ‰ ์Šคํƒ€์ผ) - ์‹ค์ œ ๊ด‘๊ณ  ์ธ๋ฑ์Šค ๊ธฐ์ค€, ํ…์ŠคํŠธ ๊ด‘๊ณ ๊ฐ€ ์•„๋‹ ๋•Œ๋งŒ
925
957
  const actualIndex = currentSlide === totalSlides ? 0 : currentSlide;
926
958
  if (dotContainer) {
@@ -2884,23 +2916,45 @@ class AdsModule {
2884
2916
  */
2885
2917
  async renderOptimizedBannerImage(adElement, ad, slot) {
2886
2918
  try {
2887
- // ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์ •๋ณด ๋กœ๋“œ
2888
- const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2889
- const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2890
- // ์ปจํ…Œ์ด๋„ˆ ๋น„์œจ ๊ณ„์‚ฐ
2891
- const containerAspectRatio = slot.aspectRatio || 16 / 9;
2919
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
2920
+ const configWidth = slot.config?.width;
2921
+ const configHeight = slot.config?.height;
2922
+ const hasUserDefinedWidth = configWidth &&
2923
+ (typeof configWidth === 'number' || (typeof configWidth === 'string' && configWidth !== '100%'));
2924
+ const hasUserDefinedHeight = configHeight &&
2925
+ (typeof configHeight === 'number' || (typeof configHeight === 'string' && configHeight !== 'auto'));
2926
+ const hasUserDefinedSize = hasUserDefinedWidth || hasUserDefinedHeight;
2892
2927
  // ์ด๋ฏธ์ง€ ์š”์†Œ ์ƒ์„ฑ
2893
2928
  const img = document.createElement('img');
2894
2929
  img.src = ad.imageUrl;
2895
2930
  img.alt = ad.title;
2896
- img.style.width = '100%';
2897
- img.style.height = '100%';
2898
- // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2899
- this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2931
+ if (hasUserDefinedSize) {
2932
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
2933
+ img.style.width = '100%';
2934
+ img.style.height = '100%';
2935
+ img.style.objectFit = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
2936
+ img.style.objectPosition = 'center';
2937
+ if (this._config?.debug) {
2938
+ console.log(`๐ŸŽฏ User-defined size detected: filling container completely`);
2939
+ }
2940
+ }
2941
+ else {
2942
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ๋™์  ์ตœ์ ํ™” ์ ์šฉ
2943
+ const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
2944
+ const imageAspectRatio = imageDimensions.width / imageDimensions.height;
2945
+ const containerAspectRatio = slot.aspectRatio || 16 / 9;
2946
+ img.style.width = '100%';
2947
+ img.style.height = '100%';
2948
+ // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
2949
+ this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
2950
+ if (this._config?.debug) {
2951
+ console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2952
+ }
2953
+ }
2900
2954
  // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ์ฒ˜๋ฆฌ
2901
2955
  img.onload = () => {
2902
2956
  if (this._config?.debug) {
2903
- console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
2957
+ console.log(`โœ… Banner image loaded successfully`);
2904
2958
  }
2905
2959
  };
2906
2960
  // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adstage/web-sdk",
3
- "version": "2.2.1",
4
- "description": "AdStage Web SDK - Production-ready marketing platform SDK with auto-initialization, dynamic sizing, and centered image positioning",
3
+ "version": "2.2.3",
4
+ "description": "AdStage Web SDK - Production-ready marketing platform SDK with auto-initialization, dynamic sizing, centered image positioning, user-defined size support, and adaptive height adjustment",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.esm.js",
@@ -184,7 +184,7 @@ export class CarouselSliderManager {
184
184
  const totalSlides = advertisements.length;
185
185
  const autoSlideInterval = (options?.autoSlideInterval || 3) * 1000; // ๊ธฐ๋ณธ 3์ดˆ
186
186
 
187
- // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์›)
187
+ // ์Šฌ๋ผ์ด๋“œ ์ด๋™ ํ•จ์ˆ˜ (๋ฌดํ•œ ๋ฃจํ”„ ์ง€์› + ๋™์  ๋†’์ด ์กฐ์ •)
188
188
  const moveToSlide = (index: number, instant = false) => {
189
189
  currentSlide = index;
190
190
 
@@ -198,6 +198,36 @@ export class CarouselSliderManager {
198
198
  // ํ•ญ์ƒ ํผ์„ผํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋™
199
199
  slideContainer.style.transform = `translateX(-${(100 / extendedAds.length) * currentSlide}%)`;
200
200
 
201
+ // ๐Ÿ†• ๋™์  ๋†’์ด ์กฐ์ •: ํ˜„์žฌ ์Šฌ๋ผ์ด๋“œ์˜ ์ด๋ฏธ์ง€ ๋†’์ด์— ๋งž์ถฐ ์ปจํ…Œ์ด๋„ˆ ๋†’์ด ์กฐ์ •
202
+ if (!instant && !slot.height && !slot.width) { // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ
203
+ const actualIndex = currentSlide === totalSlides ? 0 : currentSlide;
204
+ const currentSlideElement = slideContainer.children[currentSlide] as HTMLElement;
205
+
206
+ if (currentSlideElement) {
207
+ const currentAdElement = currentSlideElement.children[0] as HTMLElement;
208
+ if (currentAdElement) {
209
+ // ์ด๋ฏธ์ง€ ์š”์†Œ ์ฐพ๊ธฐ
210
+ const imgElement = currentAdElement.querySelector('img');
211
+ if (imgElement) {
212
+ // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ํ›„ ๋†’์ด ์กฐ์ •
213
+ const adjustHeight = () => {
214
+ const imgHeight = imgElement.getBoundingClientRect().height;
215
+ if (imgHeight > 0) {
216
+ sliderWrapper.style.height = `${imgHeight}px`;
217
+ sliderWrapper.style.transition = instant ? 'none' : 'height 0.4s ease-out';
218
+ }
219
+ };
220
+
221
+ if (imgElement.complete && imgElement.naturalHeight > 0) {
222
+ adjustHeight();
223
+ } else {
224
+ imgElement.addEventListener('load', adjustHeight, { once: true });
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+
201
231
  // ๋„ํŠธ ์—…๋ฐ์ดํŠธ (๋ฌด์ฑ„์ƒ‰ ์Šคํƒ€์ผ) - ์‹ค์ œ ๊ด‘๊ณ  ์ธ๋ฑ์Šค ๊ธฐ์ค€, ํ…์ŠคํŠธ ๊ด‘๊ณ ๊ฐ€ ์•„๋‹ ๋•Œ๋งŒ
202
232
  const actualIndex = currentSlide === totalSlides ? 0 : currentSlide;
203
233
  if (dotContainer) {
@@ -1076,27 +1076,52 @@ export class AdsModule implements BaseModule {
1076
1076
  */
1077
1077
  private async renderOptimizedBannerImage(adElement: HTMLElement, ad: Advertisement, slot: AdSlot): Promise<void> {
1078
1078
  try {
1079
- // ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์ •๋ณด ๋กœ๋“œ
1080
- const imageDimensions = await this.loadImageDimensions(ad.imageUrl!);
1081
- const imageAspectRatio = imageDimensions.width / imageDimensions.height;
1079
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
1080
+ const configWidth = slot.config?.width;
1081
+ const configHeight = slot.config?.height;
1082
1082
 
1083
- // ์ปจํ…Œ์ด๋„ˆ ๋น„์œจ ๊ณ„์‚ฐ
1084
- const containerAspectRatio = (slot as any).aspectRatio || 16/9;
1083
+ const hasUserDefinedWidth = configWidth &&
1084
+ (typeof configWidth === 'number' || (typeof configWidth === 'string' && configWidth !== '100%'));
1085
+ const hasUserDefinedHeight = configHeight &&
1086
+ (typeof configHeight === 'number' || (typeof configHeight === 'string' && configHeight !== 'auto'));
1087
+ const hasUserDefinedSize = hasUserDefinedWidth || hasUserDefinedHeight;
1085
1088
 
1086
1089
  // ์ด๋ฏธ์ง€ ์š”์†Œ ์ƒ์„ฑ
1087
1090
  const img = document.createElement('img');
1088
1091
  img.src = ad.imageUrl!;
1089
1092
  img.alt = ad.title;
1090
- img.style.width = '100%';
1091
- img.style.height = '100%';
1092
1093
 
1093
- // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
1094
- this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
1094
+ if (hasUserDefinedSize) {
1095
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
1096
+ img.style.width = '100%';
1097
+ img.style.height = '100%';
1098
+ img.style.objectFit = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
1099
+ img.style.objectPosition = 'center';
1100
+
1101
+ if (this._config?.debug) {
1102
+ console.log(`๐ŸŽฏ User-defined size detected: filling container completely`);
1103
+ }
1104
+ } else {
1105
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ๋™์  ์ตœ์ ํ™” ์ ์šฉ
1106
+ const imageDimensions = await this.loadImageDimensions(ad.imageUrl!);
1107
+ const imageAspectRatio = imageDimensions.width / imageDimensions.height;
1108
+ const containerAspectRatio = (slot as any).aspectRatio || 16/9;
1109
+
1110
+ img.style.width = '100%';
1111
+ img.style.height = '100%';
1112
+
1113
+ // ๐ŸŽจ ์ตœ์ ํ™”๋œ ์Šคํƒ€์ผ ์ ์šฉ
1114
+ this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
1115
+
1116
+ if (this._config?.debug) {
1117
+ console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
1118
+ }
1119
+ }
1095
1120
 
1096
1121
  // ์ด๋ฏธ์ง€ ๋กœ๋“œ ์™„๋ฃŒ ์ฒ˜๋ฆฌ
1097
1122
  img.onload = () => {
1098
1123
  if (this._config?.debug) {
1099
- console.log(`๐Ÿ–ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
1124
+ console.log(`โœ… Banner image loaded successfully`);
1100
1125
  }
1101
1126
  };
1102
1127
 
@@ -108,20 +108,24 @@ export abstract class BaseAdRenderer implements AdRenderer {
108
108
  protected getImageStyles(slot?: AdSlot): Record<string, string> {
109
109
  const styles: Record<string, string> = {
110
110
  display: 'block',
111
- 'max-width': '100%',
112
- height: 'auto',
113
111
  'object-position': 'center', // ๐ŸŽฏ ์ด๋ฏธ์ง€ ํ•ญ์ƒ ์ค‘์•™ ์ •๋ ฌ
114
112
  };
115
113
 
116
- // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํฌ๊ธฐ ์ œํ•œ
114
+ // ์‚ฌ์šฉ์ž๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ–ˆ๋Š”์ง€ ํ™•์ธ
117
115
  const parsedWidth = this.parseSizeValue(slot?.width);
118
116
  const parsedHeight = this.parseSizeValue(slot?.height);
117
+ const hasUserDefinedSize = parsedWidth || parsedHeight;
119
118
 
120
- if (parsedWidth && parsedHeight) {
119
+ if (hasUserDefinedSize) {
120
+ // ๐ŸŽฏ ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ: ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •
121
121
  styles.width = '100%';
122
122
  styles.height = '100%';
123
- styles['object-fit'] = 'cover';
124
- styles['object-position'] = 'center'; // ๐ŸŽฏ ํฌ๊ธฐ ์กฐ์ • ์‹œ์—๋„ ์ค‘์•™ ์ •๋ ฌ
123
+ styles['object-fit'] = 'cover'; // ์ปจํ…Œ์ด๋„ˆ์— ๊ฝ‰ ์ฐฌ ์ƒํƒœ๋กœ ๋น„์œจ ์œ ์ง€
124
+ styles['object-position'] = 'center';
125
+ } else {
126
+ // ์‚ฌ์šฉ์ž๊ฐ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ: ์›๋ณธ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์œ ์ง€
127
+ styles['max-width'] = '100%';
128
+ styles.height = 'auto';
125
129
  }
126
130
 
127
131
  return styles;