@loafmarkets/ui 0.1.402 → 0.1.404

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.mjs CHANGED
@@ -5076,6 +5076,7 @@ var Header = ({
5076
5076
  onOrdersNavigate: _onOrdersNavigate,
5077
5077
  onWalletNavigate: _onWalletNavigate,
5078
5078
  onSettingsClick,
5079
+ onReferClick,
5079
5080
  portfolioSummary,
5080
5081
  fundsPending = false,
5081
5082
  transparentOnTop = false,
@@ -5514,7 +5515,7 @@ var Header = ({
5514
5515
  onClick: (event) => {
5515
5516
  event?.preventDefault();
5516
5517
  closeMenus();
5517
- onSettingsClick?.();
5518
+ (onReferClick ?? onSettingsClick)?.();
5518
5519
  },
5519
5520
  children: "Refer"
5520
5521
  }
@@ -5557,7 +5558,7 @@ var Header = ({
5557
5558
  onClick: (event) => {
5558
5559
  event?.preventDefault();
5559
5560
  closeMenus();
5560
- onSettingsClick?.();
5561
+ (onReferClick ?? onSettingsClick)?.();
5561
5562
  },
5562
5563
  children: /* @__PURE__ */ jsx(MenuItem, { children: "Refer" })
5563
5564
  }
@@ -18881,13 +18882,14 @@ var CloseButton3 = styled10.button`
18881
18882
  var MainImageContainer = styled10.div`
18882
18883
  position: relative;
18883
18884
  flex: 1;
18885
+ min-height: 0;
18884
18886
  display: flex;
18885
18887
  align-items: center;
18886
18888
  justify-content: center;
18887
- padding: 80px 20px 140px;
18889
+ padding: 20px 20px 160px;
18888
18890
 
18889
18891
  @media (max-width: 768px) {
18890
- padding: 60px 0 110px;
18892
+ padding: 10px 0 130px;
18891
18893
  }
18892
18894
  `;
18893
18895
  var MainImage = styled10.img`
@@ -18899,8 +18901,11 @@ var MainImage = styled10.img`
18899
18901
  opacity: ${(p) => p.$visible ? 1 : 0};
18900
18902
  pointer-events: ${(p) => p.$visible ? "auto" : "none"};
18901
18903
  transition: opacity 300ms ease;
18902
- /* Inset box excludes the bottom thumbnail strip so margin:auto centres the image in the
18903
- space ABOVE the thumbnails (absolute ignores the parent's padding). */
18904
+ /* All slides share the same absolute box so switching only crossfades opacity
18905
+ no relative↔absolute size jump (the "grow then shrink" on navigation).
18906
+ The inset box excludes the bottom thumbnail strip so margin:auto centres the image
18907
+ in the space ABOVE the thumbnails (absolute positioning ignores the parent's padding,
18908
+ which otherwise let the image sink behind the thumbnails / "lean down"). */
18904
18909
  position: absolute;
18905
18910
  top: 24px;
18906
18911
  left: 24px;
@@ -19094,9 +19099,11 @@ function PropertyPhotoGallery({
19094
19099
  isOpen,
19095
19100
  onClose,
19096
19101
  startIndex = 0,
19102
+ startWithVideo = false,
19097
19103
  title = "28 Derby Street, Vaucluse",
19098
19104
  subtitle = "Elara \u2014 Luxury Harbour Residence",
19099
- images
19105
+ images,
19106
+ videoUrl
19100
19107
  }) {
19101
19108
  const galleryImages = images?.length ? images : DEFAULT_IMAGES;
19102
19109
  if (!isOpen) return null;
@@ -19105,16 +19112,19 @@ function PropertyPhotoGallery({
19105
19112
  {
19106
19113
  galleryImages,
19107
19114
  startIndex,
19115
+ startWithVideo,
19108
19116
  title,
19109
19117
  subtitle,
19110
- onClose
19118
+ onClose,
19119
+ videoUrl
19111
19120
  },
19112
- `${startIndex}-${galleryImages.length}`
19121
+ `${startIndex}-${galleryImages.length}-${startWithVideo}`
19113
19122
  );
19114
19123
  }
19115
- function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose }) {
19124
+ function GalleryContent({ galleryImages, startIndex, startWithVideo, title, subtitle, onClose, videoUrl }) {
19116
19125
  const [currentIndex, setCurrentIndex] = useState(() => clampIndex(startIndex, galleryImages.length));
19117
19126
  const [activeHotspotId, setActiveHotspotId] = useState(null);
19127
+ const [showVideo, setShowVideo] = useState(startWithVideo ?? false);
19118
19128
  const sliderRef = useRef(null);
19119
19129
  const [isDragging, setIsDragging] = useState(false);
19120
19130
  const wasDraggingRef = useRef(false);
@@ -19164,7 +19174,7 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19164
19174
  ] }),
19165
19175
  /* @__PURE__ */ jsx(CloseButton3, { onClick: onClose, "aria-label": "Close gallery", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M6 18L18 6" }) }) })
19166
19176
  ] }),
19167
- /* @__PURE__ */ jsxs(SliderContainer, { onClick: (event) => event.stopPropagation(), children: [
19177
+ !showVideo && /* @__PURE__ */ jsxs(SliderContainer, { onClick: (event) => event.stopPropagation(), children: [
19168
19178
  /* @__PURE__ */ jsxs(
19169
19179
  SliderTrack,
19170
19180
  {
@@ -19227,7 +19237,21 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19227
19237
  children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6" }) })
19228
19238
  }
19229
19239
  ),
19230
- galleryImages.map((image, idx) => /* @__PURE__ */ jsx(MainImage, { src: image.src, alt: image.alt, $visible: idx === currentIndex }, image.alt)),
19240
+ showVideo && videoUrl ? /* @__PURE__ */ jsx(GalleryVideoWrap, { children: /* @__PURE__ */ jsx(
19241
+ "video",
19242
+ {
19243
+ autoPlay: true,
19244
+ loop: true,
19245
+ playsInline: true,
19246
+ muted: true,
19247
+ controls: true,
19248
+ onVolumeChange: (e) => {
19249
+ if (!e.currentTarget.muted) e.currentTarget.muted = true;
19250
+ },
19251
+ style: { objectFit: "contain", borderRadius: 12, boxShadow: "0 30px 80px rgba(0,0,0,0.55)" },
19252
+ children: /* @__PURE__ */ jsx("source", { src: videoUrl, type: "video/mp4" })
19253
+ }
19254
+ ) }) : galleryImages.map((image, idx) => /* @__PURE__ */ jsx(MainImage, { src: image.src, alt: image.alt, $visible: idx === currentIndex }, image.alt)),
19231
19255
  galleryImages[currentIndex]?.hotspots?.map((hotspot) => /* @__PURE__ */ jsx(
19232
19256
  Hotspot,
19233
19257
  {
@@ -19272,11 +19296,83 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19272
19296
  ]
19273
19297
  }
19274
19298
  ),
19275
- /* @__PURE__ */ jsx(ThumbnailStrip, { onClick: (event) => event.stopPropagation(), children: galleryImages.map((image, idx) => /* @__PURE__ */ jsx(Thumbnail3, { $active: idx === currentIndex, onClick: () => setCurrentIndex(idx), "aria-label": `Preview ${image.label}`, children: /* @__PURE__ */ jsx("img", { src: image.src, alt: image.alt }) }, image.alt)) })
19299
+ /* @__PURE__ */ jsxs(ThumbnailStrip, { onClick: (event) => event.stopPropagation(), children: [
19300
+ galleryImages.map((image, idx) => /* @__PURE__ */ jsx(Thumbnail3, { $active: !showVideo && idx === currentIndex, onClick: () => {
19301
+ setShowVideo(false);
19302
+ setCurrentIndex(idx);
19303
+ }, "aria-label": `Preview ${image.label}`, children: /* @__PURE__ */ jsx("img", { src: image.src, alt: image.alt }) }, image.alt)),
19304
+ videoUrl && /* @__PURE__ */ jsxs(Fragment, { children: [
19305
+ /* @__PURE__ */ jsx(ThumbnailDivider, {}),
19306
+ /* @__PURE__ */ jsxs(VideoBtn, { $active: showVideo, onClick: () => setShowVideo(true), children: [
19307
+ /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
19308
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "4", width: "14", height: "16", rx: "2" }),
19309
+ /* @__PURE__ */ jsx("path", { d: "M16 8l6-4v16l-6-4z" })
19310
+ ] }),
19311
+ "Video"
19312
+ ] })
19313
+ ] })
19314
+ ] })
19276
19315
  ]
19277
19316
  }
19278
19317
  );
19279
19318
  }
19319
+ var GalleryVideoWrap = styled10.div`
19320
+ position: absolute;
19321
+ inset: 0;
19322
+ display: flex;
19323
+ align-items: center;
19324
+ justify-content: center;
19325
+ padding: 20px 20px 160px;
19326
+
19327
+ video {
19328
+ max-width: 90%;
19329
+ max-height: 100%;
19330
+ }
19331
+
19332
+ /* Property videos stay permanently muted — remove the volume + mute buttons
19333
+ from the native player (Chrome/Edge/Safari/iOS/Android). Firefox ignores
19334
+ these and is covered by the onVolumeChange force-mute fallback. */
19335
+ video::-webkit-media-controls-mute-button,
19336
+ video::-webkit-media-controls-volume-slider,
19337
+ video::-webkit-media-controls-volume-control-container {
19338
+ display: none !important;
19339
+ }
19340
+
19341
+ @media (max-width: 768px) {
19342
+ padding: 10px 0 130px;
19343
+
19344
+ video {
19345
+ max-width: 100%;
19346
+ }
19347
+ }
19348
+ `;
19349
+ var ThumbnailDivider = styled10.div`
19350
+ width: 1px;
19351
+ height: 48px;
19352
+ background: rgba(255, 255, 255, 0.15);
19353
+ flex-shrink: 0;
19354
+ align-self: center;
19355
+ `;
19356
+ var VideoBtn = styled10.button`
19357
+ display: flex;
19358
+ align-items: center;
19359
+ gap: 6px;
19360
+ padding: 8px 14px;
19361
+ border-radius: 8px;
19362
+ border: 1px solid ${(p) => p.$active ? "var(--color-accent, #E6C87E)" : "rgba(255, 255, 255, 0.2)"};
19363
+ background: ${(p) => p.$active ? "rgba(240, 185, 11, 0.15)" : "rgba(255, 255, 255, 0.08)"};
19364
+ color: ${(p) => p.$active ? "var(--color-accent, #E6C87E)" : "#fff"};
19365
+ font-size: 0.82rem;
19366
+ font-weight: 500;
19367
+ cursor: pointer;
19368
+ flex-shrink: 0;
19369
+ transition: all 0.2s ease;
19370
+
19371
+ &:hover {
19372
+ background: rgba(255, 255, 255, 0.15);
19373
+ border-color: rgba(255, 255, 255, 0.3);
19374
+ }
19375
+ `;
19280
19376
  var slideIn2 = keyframes`
19281
19377
  from { transform: translateX(110%); opacity: 0; }
19282
19378
  to { transform: translateX(0); opacity: 1; }