zuljaman-banner-components 1.0.20 → 1.0.21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"BannerRenderer.d.ts","sourceRoot":"","sources":["../../src/components/BannerRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAgE,MAAM,OAAO,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUvD,UAAU,mBAAmB;IAE3B,WAAW,EAAE,MAAM,CAAC;IAGpB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAGhD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAG7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAG5C,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvF,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAukBxD,CAAC"}
1
+ {"version":3,"file":"BannerRenderer.d.ts","sourceRoot":"","sources":["../../src/components/BannerRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAgE,MAAM,OAAO,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUvD,UAAU,mBAAmB;IAE3B,WAAW,EAAE,MAAM,CAAC;IAGpB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAGhD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAG7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACpE,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAG5C,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvF,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAivBxD,CAAC"}
@@ -61,6 +61,11 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
61
61
  const [recalcTrigger, setRecalcTrigger] = (0, react_1.useState)(0);
62
62
  const logoRef = (0, react_1.useRef)(null);
63
63
  const copyRefs = (0, react_1.useRef)([]);
64
+ const bannerContainerRef = (0, react_1.useRef)(null);
65
+ // Live drag position for guide lines
66
+ const [liveDragPosition, setLiveDragPosition] = (0, react_1.useState)(null);
67
+ // Track if currently dragging
68
+ const [isDragging, setIsDragging] = (0, react_1.useState)(false);
64
69
  // Get substyle configuration based on bannerStyle
65
70
  const config = (0, react_1.useMemo)(() => {
66
71
  switch (bannerStyle) {
@@ -276,7 +281,37 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
276
281
  shadowIntensityMultiplier,
277
282
  ]);
278
283
  // Shared logo component
279
- const logoComponent = ((0, jsx_runtime_1.jsx)(shared_1.DraggableElement, { enabled: draggableMode, position: { x: logoTranslateX, y: logoTranslateY }, rotation: logoRotation, width: logoWidth, scale: sizeMultiplier, elementId: "logo", isSelected: selectedElement === "logo", onPositionChange: onLogoPositionChange, onRotationChange: onLogoRotationChange, onWidthChange: onLogoWidthChange, onSelect: (id) => setSelectedElement(id), onDeselect: () => setSelectedElement(null), onRotationSnap: handleRotationSnap, children: (0, jsx_runtime_1.jsx)("div", { ref: logoRef, className: "relative", style: {
284
+ const logoComponent = ((0, jsx_runtime_1.jsx)(shared_1.DraggableElement, { enabled: draggableMode, position: { x: logoTranslateX, y: logoTranslateY }, rotation: logoRotation, width: logoWidth, scale: sizeMultiplier, elementId: "logo", isSelected: selectedElement === "logo", onPositionChange: (pos) => {
285
+ // Clear dragging state when drag ends
286
+ setIsDragging(false);
287
+ setLiveDragPosition(null);
288
+ onLogoPositionChange === null || onLogoPositionChange === void 0 ? void 0 : onLogoPositionChange(pos);
289
+ }, onRotationChange: onLogoRotationChange, onWidthChange: onLogoWidthChange, onSelect: (id) => setSelectedElement(id), onDeselect: () => {
290
+ setSelectedElement(null);
291
+ setLiveDragPosition(null);
292
+ setIsDragging(false);
293
+ }, onRotationSnap: handleRotationSnap, onDragMove: (elementId, bounds) => {
294
+ // Set dragging state to true
295
+ setIsDragging(true);
296
+ // Calculate live position from element bounds
297
+ if (!bannerContainerRef.current)
298
+ return;
299
+ const bannerBounds = bannerContainerRef.current.getBoundingClientRect();
300
+ const elementCenterX = bounds.left + bounds.width / 2;
301
+ const elementCenterY = bounds.top + bounds.height / 2;
302
+ // Banner center in viewport coordinates
303
+ const bannerCenterX = bannerBounds.left + bannerBounds.width / 2;
304
+ const bannerCenterY = bannerBounds.top + bannerBounds.height / 2;
305
+ // Calculate offset from banner center (in scaled pixels)
306
+ const offsetX = (elementCenterX - bannerCenterX) / sizeMultiplier;
307
+ const offsetY = (elementCenterY - bannerCenterY) / sizeMultiplier;
308
+ // Store the live position
309
+ setLiveDragPosition({
310
+ elementId,
311
+ x: offsetX,
312
+ y: offsetY,
313
+ });
314
+ }, children: (0, jsx_runtime_1.jsx)("div", { ref: logoRef, className: "relative", style: {
280
315
  width: logoWidth ? `${logoWidth}px` : `${defaults_1.DEFAULT_LOGO_SIZE_REM * logoSizeMultiplier}rem`,
281
316
  height: logoWidth ? `${logoWidth}px` : `${defaults_1.DEFAULT_LOGO_SIZE_REM * logoSizeMultiplier}rem`,
282
317
  // Remove transform - DraggableElement already handles positioning
@@ -362,6 +397,9 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
362
397
  const finalWidth = copy.width || configWidth;
363
398
  const finalRotation = (_c = copy.rotation) !== null && _c !== void 0 ? _c : (isStyled ? ((_d = copyConfig === null || copyConfig === void 0 ? void 0 : copyConfig.rotation) !== null && _d !== void 0 ? _d : 0) : 0);
364
399
  return ((0, jsx_runtime_1.jsx)(shared_1.DraggableElement, { enabled: draggableMode, position: { x: finalX, y: finalY }, rotation: finalRotation, width: finalWidth, scale: sizeMultiplier, elementId: `copy-${copy.id}`, isSelected: selectedElement === `copy-${copy.id}`, centerOrigin: true, onPositionChange: (pos) => {
400
+ // Clear live drag position and dragging state when drag ends
401
+ setLiveDragPosition(null);
402
+ setIsDragging(false);
365
403
  // Subtract base position to get only user adjustment
366
404
  const adjustedPos = {
367
405
  x: pos.x - baseX,
@@ -382,7 +420,31 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
382
420
  if (copyIndex !== -1) {
383
421
  onCopyWidthChange === null || onCopyWidthChange === void 0 ? void 0 : onCopyWidthChange(copyIndex, w);
384
422
  }
385
- }, onSelect: (id) => setSelectedElement(id), onDeselect: () => setSelectedElement(null), onRotationSnap: handleRotationSnap, children: (0, jsx_runtime_1.jsx)("div", { ref: (el) => {
423
+ }, onSelect: (id) => setSelectedElement(id), onDeselect: () => {
424
+ setSelectedElement(null);
425
+ setLiveDragPosition(null);
426
+ }, onRotationSnap: handleRotationSnap, onDragMove: (elementId, bounds) => {
427
+ // Set dragging state to true
428
+ setIsDragging(true);
429
+ // Calculate live position from element bounds
430
+ if (!bannerContainerRef.current)
431
+ return;
432
+ const bannerBounds = bannerContainerRef.current.getBoundingClientRect();
433
+ const elementCenterX = bounds.left + bounds.width / 2;
434
+ const elementCenterY = bounds.top + bounds.height / 2;
435
+ // Banner center in viewport coordinates
436
+ const bannerCenterX = bannerBounds.left + bannerBounds.width / 2;
437
+ const bannerCenterY = bannerBounds.top + bannerBounds.height / 2;
438
+ // Calculate offset from banner center (in scaled pixels)
439
+ const offsetX = (elementCenterX - bannerCenterX) / sizeMultiplier;
440
+ const offsetY = (elementCenterY - bannerCenterY) / sizeMultiplier;
441
+ // Store the live position
442
+ setLiveDragPosition({
443
+ elementId,
444
+ x: offsetX,
445
+ y: offsetY,
446
+ });
447
+ }, children: (0, jsx_runtime_1.jsx)("div", { ref: (el) => {
386
448
  // Store ref by styleSlot for auto-positioning
387
449
  if (styleSlot === 0)
388
450
  copyRefs.current[0] = el;
@@ -395,7 +457,7 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
395
457
  display: copy.hidden ? 'none' : undefined,
396
458
  }, children: contentElement }) }, copy.id));
397
459
  };
398
- return ((0, jsx_runtime_1.jsx)("div", { className: "w-full h-full text-white leading-[1.05]", children: (0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.default)("inset-0 flex flex-col items-start h-full relative isolate overflow-hidden gap-4 px-20", postType === "STORY" ? "pb-32 pt-44" : "py-20"), children: [backgroundImageUrl && ((0, jsx_runtime_1.jsx)(ImageComponent, { src: backgroundImageUrl, alt: "Background", width: 1080, height: postType === "STORY" ? 1920 : 1350, className: "object-cover absolute inset-0 w-full h-full -z-10", style: { objectFit: "cover", pointerEvents: "none" } })), noiseEnabled && ((0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 pointer-events-none", style: {
460
+ return ((0, jsx_runtime_1.jsx)("div", { className: "w-full h-full text-white leading-[1.05]", children: (0, jsx_runtime_1.jsxs)("div", { ref: bannerContainerRef, className: (0, clsx_1.default)("inset-0 flex flex-col items-start h-full relative isolate overflow-hidden gap-4 px-20", postType === "STORY" ? "pb-32 pt-44" : "py-20"), children: [backgroundImageUrl && ((0, jsx_runtime_1.jsx)(ImageComponent, { src: backgroundImageUrl, alt: "Background", width: 1080, height: postType === "STORY" ? 1920 : 1350, className: "object-cover absolute inset-0 w-full h-full -z-10", style: { objectFit: "cover", pointerEvents: "none" } })), noiseEnabled && ((0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 pointer-events-none", style: {
399
461
  opacity: Math.min(noiseIntensity / 2, 1), // Normalize 0-2 range to 0-1
400
462
  mixBlendMode: 'overlay',
401
463
  backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
@@ -404,11 +466,80 @@ const BannerRenderer = ({ bannerStyle, copies = [], bannerSubstyle = 1, logoUrl,
404
466
  top: '50%',
405
467
  left: '50%',
406
468
  transform: `translate(${config.logo.x}px, ${config.logo.y}px)`,
407
- }, children: logoComponent }), (0, jsx_runtime_1.jsx)("div", { className: "absolute pointer-events-none", style: {
469
+ }, children: logoComponent }), draggableMode && isDragging && selectedElement && (() => {
470
+ var _a, _b;
471
+ let displayX = 0;
472
+ let displayY = 0;
473
+ if (selectedElement === 'logo') {
474
+ // Logo position
475
+ const finalX = logoTranslateX;
476
+ const finalY = logoTranslateY;
477
+ // Use live drag position if available, otherwise use final position
478
+ displayX = liveDragPosition && liveDragPosition.elementId === selectedElement
479
+ ? liveDragPosition.x
480
+ : finalX;
481
+ displayY = liveDragPosition && liveDragPosition.elementId === selectedElement
482
+ ? liveDragPosition.y
483
+ : finalY;
484
+ }
485
+ else if (selectedElement.startsWith('copy-')) {
486
+ // Copy position
487
+ const selectedCopyId = selectedElement.replace('copy-', '');
488
+ const selectedCopy = copies.find(c => c.id === selectedCopyId);
489
+ if (!selectedCopy)
490
+ return null;
491
+ // Calculate position for selected copy
492
+ const styleSlot = selectedCopy.styleSlot !== undefined ? selectedCopy.styleSlot : 0;
493
+ const isStyled = styleSlot === 0 || styleSlot === 1;
494
+ const copyConfig = styleSlot === 0
495
+ ? config.copy1
496
+ : ('copy2' in config ? config.copy2 : config.copy1);
497
+ const configX = (_a = copyConfig === null || copyConfig === void 0 ? void 0 : copyConfig.x) !== null && _a !== void 0 ? _a : 0;
498
+ const configY = (_b = copyConfig === null || copyConfig === void 0 ? void 0 : copyConfig.y) !== null && _b !== void 0 ? _b : 0;
499
+ const autoOffset = autoOffsets[styleSlot] || 0;
500
+ const baseX = isStyled ? configX : 0;
501
+ const baseY = isStyled ? (configY + autoOffset) : 0;
502
+ const finalX = baseX + (selectedCopy.translateX || 0);
503
+ const finalY = baseY + (selectedCopy.translateY || 0);
504
+ // Use live drag position if available, otherwise use final position
505
+ displayX = liveDragPosition && liveDragPosition.elementId === selectedElement
506
+ ? liveDragPosition.x
507
+ : finalX;
508
+ displayY = liveDragPosition && liveDragPosition.elementId === selectedElement
509
+ ? liveDragPosition.y
510
+ : finalY;
511
+ }
512
+ else {
513
+ return null;
514
+ }
515
+ // Threshold for considering element "centered" (in pixels)
516
+ const CENTER_THRESHOLD = 5;
517
+ // Check if element is centered on each axis
518
+ const isCenteredHorizontally = Math.abs(displayX) <= CENTER_THRESHOLD;
519
+ const isCenteredVertically = Math.abs(displayY) <= CENTER_THRESHOLD;
520
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isCenteredHorizontally && ((0, jsx_runtime_1.jsx)("div", { className: "absolute pointer-events-none", style: {
521
+ left: '50%',
522
+ top: 0,
523
+ bottom: 0,
524
+ width: '6px',
525
+ backgroundColor: 'rgb(125, 211, 252)', // sky-300
526
+ transform: `translateX(${displayX - 3}px)`, // -3px to center the 6px line
527
+ zIndex: 5,
528
+ } })), isCenteredVertically && ((0, jsx_runtime_1.jsx)("div", { className: "absolute pointer-events-none", style: {
529
+ top: '50%',
530
+ left: 0,
531
+ right: 0,
532
+ height: '6px',
533
+ backgroundColor: 'rgb(125, 211, 252)', // sky-300
534
+ transform: `translateY(${displayY - 3}px)`, // -3px to center the 6px line
535
+ zIndex: 5,
536
+ } }))] }));
537
+ })(), (0, jsx_runtime_1.jsx)("div", { className: "absolute pointer-events-none", style: {
408
538
  top: '50%',
409
539
  left: '50%',
410
540
  width: 0,
411
- height: 0
541
+ height: 0,
542
+ zIndex: 10,
412
543
  }, children: copies.map((copy) => {
413
544
  // Get width from config for the wrapper
414
545
  const styleSlot = copy.styleSlot !== undefined ? copy.styleSlot : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zuljaman-banner-components",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Shared banner components package for Next.js and AWS Lambda platforms",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",