@opensite/ui 3.11.2 → 3.12.1

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/registry.cjs CHANGED
@@ -35289,7 +35289,10 @@ var CAPTION_SCRIM_STYLE = {
35289
35289
  background: "linear-gradient(180deg, rgba(8,12,24,0) 0%, rgba(8,12,24,0.55) 45%, rgba(8,12,24,0.78) 100%)",
35290
35290
  borderBottomLeftRadius: IG_TILE_RADIUS,
35291
35291
  borderBottomRightRadius: IG_TILE_RADIUS,
35292
- pointerEvents: "none"
35292
+ pointerEvents: "none",
35293
+ // Hiding captions for now until we build in
35294
+ // the dynamic behavior that clients can dictate
35295
+ display: "none"
35293
35296
  };
35294
35297
  var CAPTION_TEXT_STYLE = {
35295
35298
  color: "#fff",
@@ -35369,7 +35372,7 @@ function likeBadge(likeCount) {
35369
35372
  letterSpacing: "0.01em"
35370
35373
  },
35371
35374
  children: [
35372
- /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/heart", size: 15, "aria-hidden": "true" }),
35375
+ /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "mdi/cards-heart", size: 15, "aria-hidden": "true" }),
35373
35376
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: likeCount.toLocaleString() })
35374
35377
  ]
35375
35378
  }
@@ -35378,157 +35381,148 @@ function likeBadge(likeCount) {
35378
35381
  var VIEWER_ACTIONS = [
35379
35382
  {
35380
35383
  id: "open-in-instagram",
35381
- icon: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/external-link", size: 22, "aria-hidden": "true" }),
35384
+ icon: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/instagram", size: 22, "aria-hidden": "true" }),
35382
35385
  label: "Instagram",
35383
35386
  ariaLabel: "Open in Instagram",
35384
35387
  onPress: (item) => openPermalink(item)
35385
35388
  }
35386
35389
  ];
35387
- function RailStat({
35388
- iconName,
35389
- count,
35390
- label,
35391
- onPress
35392
- }) {
35393
- return /* @__PURE__ */ jsxRuntime.jsxs(
35394
- "button",
35390
+ function InstagramViewerRail({ item }) {
35391
+ const meta = item.meta ?? {};
35392
+ return /* @__PURE__ */ jsxRuntime.jsx(
35393
+ "div",
35395
35394
  {
35396
- type: "button",
35397
- "aria-label": `${count.toLocaleString()} ${label}`,
35398
- onClick: (e) => {
35399
- e.stopPropagation();
35400
- onPress();
35401
- },
35402
35395
  style: {
35396
+ position: "absolute",
35397
+ right: 11,
35398
+ // Bottom-aligned with the caption card (see InstagramViewerCaption).
35399
+ bottom: 34,
35403
35400
  display: "flex",
35404
35401
  flexDirection: "column",
35405
35402
  alignItems: "center",
35406
- gap: 5,
35407
- padding: 0,
35408
- border: "none",
35409
- background: "transparent",
35410
- color: "inherit",
35411
- cursor: "pointer",
35412
- font: "inherit"
35403
+ color: "var(--psmi-chrome-fg, #fff)",
35404
+ zIndex: 3
35413
35405
  },
35414
- children: [
35415
- /* @__PURE__ */ jsxRuntime.jsx(
35416
- "span",
35417
- {
35418
- style: {
35419
- width: 46,
35420
- height: 46,
35421
- borderRadius: "50%",
35422
- background: "var(--psmi-chrome-bg, rgba(255,255,255,0.14))",
35423
- backdropFilter: "blur(6px)",
35424
- WebkitBackdropFilter: "blur(6px)",
35425
- display: "flex",
35426
- alignItems: "center",
35427
- justifyContent: "center"
35428
- },
35429
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: iconName, size: 22, "aria-hidden": "true" })
35430
- }
35431
- ),
35432
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { fontSize: 11, fontWeight: 600 }, children: count.toLocaleString() })
35433
- ]
35406
+ children: meta.href ? /* @__PURE__ */ jsxRuntime.jsx(
35407
+ "a",
35408
+ {
35409
+ href: meta.href,
35410
+ target: "_blank",
35411
+ rel: "noopener noreferrer",
35412
+ "aria-label": "Open in Instagram",
35413
+ onClick: (e) => e.stopPropagation(),
35414
+ style: {
35415
+ display: "flex",
35416
+ flexDirection: "column",
35417
+ alignItems: "center",
35418
+ padding: 0,
35419
+ border: "none",
35420
+ background: "transparent",
35421
+ color: "inherit",
35422
+ cursor: "pointer",
35423
+ font: "inherit",
35424
+ textDecoration: "none"
35425
+ },
35426
+ children: /* @__PURE__ */ jsxRuntime.jsx(
35427
+ "span",
35428
+ {
35429
+ style: {
35430
+ width: 46,
35431
+ height: 46,
35432
+ borderRadius: "50%",
35433
+ background: "var(--psmi-chrome-bg, rgba(255,255,255,0.14))",
35434
+ backdropFilter: "blur(6px)",
35435
+ WebkitBackdropFilter: "blur(6px)",
35436
+ display: "flex",
35437
+ alignItems: "center",
35438
+ justifyContent: "center"
35439
+ },
35440
+ children: /* @__PURE__ */ jsxRuntime.jsx(
35441
+ DynamicIcon,
35442
+ {
35443
+ name: "lucide/instagram",
35444
+ size: 22,
35445
+ "aria-hidden": "true"
35446
+ }
35447
+ )
35448
+ }
35449
+ )
35450
+ }
35451
+ ) : null
35434
35452
  }
35435
35453
  );
35436
35454
  }
35437
- function InstagramViewerRail({ item }) {
35438
- const meta = item.meta ?? {};
35439
- const open = () => openPermalink(item);
35455
+ function profileUrl(username) {
35456
+ return `https://www.instagram.com/${username.replace(/^@+/, "")}/`;
35457
+ }
35458
+ var USERNAME_BADGE_STYLE = {
35459
+ display: "inline-flex",
35460
+ alignItems: "center",
35461
+ gap: 7,
35462
+ marginBottom: 10,
35463
+ padding: "7px 12px",
35464
+ borderRadius: 999,
35465
+ background: "var(--psmi-chrome-bg, rgba(255,255,255,0.16))",
35466
+ backdropFilter: "blur(8px)",
35467
+ WebkitBackdropFilter: "blur(8px)",
35468
+ border: "1px solid rgba(255, 255, 255, 0.18)",
35469
+ color: "inherit",
35470
+ fontSize: 13,
35471
+ fontWeight: 700,
35472
+ lineHeight: 1,
35473
+ letterSpacing: "0.01em",
35474
+ textDecoration: "none",
35475
+ pointerEvents: "auto"
35476
+ };
35477
+ var VIEWER_TITLE_STYLE = {
35478
+ fontSize: 16,
35479
+ fontWeight: 700,
35480
+ lineHeight: 1.35,
35481
+ textShadow: "0 1px 2px rgba(0, 0, 0, 0.4)",
35482
+ display: "-webkit-box",
35483
+ WebkitLineClamp: 2,
35484
+ WebkitBoxOrient: "vertical",
35485
+ overflow: "hidden"
35486
+ };
35487
+ function InstagramViewerCaption({
35488
+ item,
35489
+ username
35490
+ }) {
35491
+ const handle = username?.replace(/^@+/, "");
35492
+ const badgeContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
35493
+ /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/instagram", size: 14, "aria-hidden": "true" }),
35494
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: handle ? `@${handle}` : "Instagram" })
35495
+ ] });
35440
35496
  return /* @__PURE__ */ jsxRuntime.jsxs(
35441
35497
  "div",
35442
35498
  {
35443
35499
  style: {
35444
35500
  position: "absolute",
35445
- right: 11,
35446
- bottom: 135,
35447
- display: "flex",
35448
- flexDirection: "column",
35449
- alignItems: "center",
35450
- gap: 18,
35501
+ left: 16,
35502
+ // Mirrors the library caption card's clearance for the actions rail.
35503
+ right: 78,
35504
+ bottom: 34,
35451
35505
  color: "var(--psmi-chrome-fg, #fff)",
35452
- zIndex: 3
35506
+ zIndex: 2
35453
35507
  },
35454
35508
  children: [
35455
- typeof meta.likeCount === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
35456
- RailStat,
35457
- {
35458
- iconName: "lucide/heart",
35459
- count: meta.likeCount,
35460
- label: "likes",
35461
- onPress: open
35462
- }
35463
- ) : null,
35464
- typeof meta.commentCount === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
35465
- RailStat,
35466
- {
35467
- iconName: "lucide/message-circle",
35468
- count: meta.commentCount,
35469
- label: "comments",
35470
- onPress: open
35471
- }
35472
- ) : null,
35473
- typeof meta.viewCount === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
35474
- RailStat,
35475
- {
35476
- iconName: "lucide/eye",
35477
- count: meta.viewCount,
35478
- label: "views",
35479
- onPress: open
35480
- }
35481
- ) : null,
35482
- meta.href ? /* @__PURE__ */ jsxRuntime.jsxs(
35509
+ handle ? /* @__PURE__ */ jsxRuntime.jsx(
35483
35510
  "a",
35484
35511
  {
35485
- href: meta.href,
35512
+ href: profileUrl(handle),
35486
35513
  target: "_blank",
35487
35514
  rel: "noopener noreferrer",
35488
- "aria-label": "Open in Instagram",
35515
+ "aria-label": `Open @${handle} on Instagram`,
35489
35516
  onClick: (e) => e.stopPropagation(),
35490
- style: {
35491
- display: "flex",
35492
- flexDirection: "column",
35493
- alignItems: "center",
35494
- gap: 5,
35495
- padding: 0,
35496
- border: "none",
35497
- background: "transparent",
35498
- color: "inherit",
35499
- cursor: "pointer",
35500
- font: "inherit",
35501
- textDecoration: "none"
35502
- },
35503
- children: [
35504
- /* @__PURE__ */ jsxRuntime.jsx(
35505
- "span",
35506
- {
35507
- style: {
35508
- width: 46,
35509
- height: 46,
35510
- borderRadius: "50%",
35511
- background: "var(--psmi-chrome-bg, rgba(255,255,255,0.14))",
35512
- backdropFilter: "blur(6px)",
35513
- WebkitBackdropFilter: "blur(6px)",
35514
- display: "flex",
35515
- alignItems: "center",
35516
- justifyContent: "center"
35517
- },
35518
- children: /* @__PURE__ */ jsxRuntime.jsx(
35519
- DynamicIcon,
35520
- {
35521
- name: "lucide/external-link",
35522
- size: 22,
35523
- "aria-hidden": "true"
35524
- }
35525
- )
35526
- }
35527
- ),
35528
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { fontSize: 11, fontWeight: 600 }, children: "Instagram" })
35529
- ]
35517
+ style: { ...USERNAME_BADGE_STYLE, cursor: "pointer" },
35518
+ children: badgeContent
35530
35519
  }
35531
- ) : null
35520
+ ) : (
35521
+ // No username supplied: never fabricate a handle — degrade to a
35522
+ // non-interactive "Instagram" chip in the same position.
35523
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: USERNAME_BADGE_STYLE, children: badgeContent })
35524
+ ),
35525
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: VIEWER_TITLE_STYLE, children: item.title })
35532
35526
  ]
35533
35527
  }
35534
35528
  );
@@ -35538,7 +35532,8 @@ function InstagramFeedGrid({
35538
35532
  gridClassName,
35539
35533
  itemClassName,
35540
35534
  imageClassName,
35541
- optixFlowConfig
35535
+ optixFlowConfig,
35536
+ showLikeBadges = false
35542
35537
  }) {
35543
35538
  const { open } = mediaImmersive.useImmersiveFeed();
35544
35539
  const posterImgProps = React30.useMemo(() => {
@@ -35575,7 +35570,7 @@ function InstagramFeedGrid({
35575
35570
  showDuration: false,
35576
35571
  glyphMode: "hover",
35577
35572
  posterImgProps,
35578
- badgeSlot: typeof likeCount === "number" ? likeBadge(likeCount) : void 0
35573
+ badgeSlot: showLikeBadges && typeof likeCount === "number" ? likeBadge(likeCount) : void 0
35579
35574
  }
35580
35575
  ),
35581
35576
  mediaItem.title ? (
@@ -35605,6 +35600,8 @@ function InstagramPostGrid({
35605
35600
  itemClassName,
35606
35601
  imageClassName,
35607
35602
  optixFlowConfig,
35603
+ username,
35604
+ showLikeBadges = false,
35608
35605
  background,
35609
35606
  pattern,
35610
35607
  patternOpacity,
@@ -35613,7 +35610,7 @@ function InstagramPostGrid({
35613
35610
  const mediaItems = React30.useMemo(() => {
35614
35611
  if (itemsSlot || !items) return [];
35615
35612
  const withImage = items.filter((item) => Boolean(item.image));
35616
- if (process.env.NODE_ENV !== "production" && withImage.length < items.length) {
35613
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production" && withImage.length < items.length) {
35617
35614
  const skipped = items.filter((item) => !item.image);
35618
35615
  const skippedIds = skipped.map((item) => item.id).join(", ");
35619
35616
  console.warn(
@@ -35642,7 +35639,7 @@ function InstagramPostGrid({
35642
35639
  "h2",
35643
35640
  {
35644
35641
  className: cn(
35645
- "text-xl font-medium tracking-tight md:text-2xl lg:text-3xl text-balance",
35642
+ "text-xl font-medium tracking-tight md:text-3xl lg:text-5xl text-balance",
35646
35643
  headingClassName
35647
35644
  ),
35648
35645
  children: heading
@@ -35652,7 +35649,7 @@ function InstagramPostGrid({
35652
35649
  "p",
35653
35650
  {
35654
35651
  className: cn(
35655
- "max-w-2xl text-balance text-muted-foreground",
35652
+ "max-w-full md:max-w-2xl text-balance opacity-75",
35656
35653
  subheadingClassName
35657
35654
  ),
35658
35655
  children: subheading
@@ -35676,14 +35673,16 @@ function InstagramPostGrid({
35676
35673
  gridClassName,
35677
35674
  itemClassName,
35678
35675
  imageClassName,
35679
- optixFlowConfig
35676
+ optixFlowConfig,
35677
+ showLikeBadges
35680
35678
  }
35681
35679
  ),
35682
35680
  /* @__PURE__ */ jsxRuntime.jsx(
35683
35681
  mediaImmersive.ImmersiveViewer,
35684
35682
  {
35685
35683
  ariaLabel: "Instagram post viewer",
35686
- renderActions: ({ item }) => /* @__PURE__ */ jsxRuntime.jsx(InstagramViewerRail, { item })
35684
+ renderActions: ({ item }) => /* @__PURE__ */ jsxRuntime.jsx(InstagramViewerRail, { item }),
35685
+ renderCaption: (item) => /* @__PURE__ */ jsxRuntime.jsx(InstagramViewerCaption, { item, username })
35687
35686
  }
35688
35687
  )
35689
35688
  ] })
@@ -111567,8 +111566,8 @@ var interiorCarousel = {
111567
111566
  }
111568
111567
  };
111569
111568
  var instagramPostGrid = {
111570
- exampleUsage: "Display a website's Instagram feed as a responsive grid of vertical (9:16) tiles that open a fullscreen, swipeable immersive viewer (TikTok/Reels-style). Photos and reels are both first-class media \u2014 reels play a muted preview and open with playback; photos open as a full-bleed still. Each tile shows a like-count pill top-left (when available), no duration timestamp, and a center glyph on hover only (a play triangle for reels, an expand icon for photos). The fullscreen viewer carries the caption plus a read-only engagement rail (likes/comments/views) and an explicit 'Open in Instagram' link (a real anchor opening in a new tab). Data is hydrated from the toastability Instagram feed (dataSource type 'instagram_feed', bindTo 'items').",
111571
- importantUsageNotes: `${GALLERY_MEDIA_NOTE} This is a DYNAMIC feed block: its 'items' are hydrated at routing-build time from the connected Instagram profile \u2014 do NOT hand-author post content. 'items[].image' and 'items[].videoUrl' MUST be the re-hosted MediaRecord CDN URLs served by the feed; expiring Instagram CDN URLs must never be used. Tiles are VERTICAL (9:16) and render both photos and reels; a post is treated as a reel only when 'isVideo' is true AND 'videoUrl' is present. Engagement counts ('likeCount', 'commentCount', 'viewCount') render only when the value is present \u2014 never fabricate a zero for a missing metric; 'likeCount' surfaces as the tile's top-left pill and, with comments/views, in the viewer rail. Tapping a tile OPENS THE FULLSCREEN VIEWER (the whole-tile link-out was replaced); the instagram.com permalink ('items[].href') opens from the viewer's 'Open in Instagram' egress, which is rendered as a REAL anchor (target=_blank, rel=noopener noreferrer) \u2014 a crawlable, affordance-correct link, not a scripted window.open button. 'items[].caption' should be a plain STRING when rendered immersively \u2014 it flows through as the tile/viewer title text; a rich ReactNode caption cannot be threaded through the immersive card/viewer and falls back to 'items[].imageAlt' (then a generic label). Consumer image styling is honored: 'imageClassName' and 'optixFlowConfig' are forwarded onto each tile's poster image. Items without an 'image' are skipped; an empty or missing 'items' array renders nothing. Requires the site to have a connected, fully-imported Instagram profile ('instagram_media' capability).`,
111569
+ exampleUsage: "Display a website's Instagram feed as a responsive grid of vertical (9:16) tiles that open a fullscreen, swipeable immersive viewer (TikTok/Reels-style). Photos and reels are both first-class media \u2014 reels play a muted preview and open with playback; photos open as a full-bleed still. Tiles show no duration timestamp and a center glyph on hover only (a play triangle for reels, an expand icon for photos); like-count pills are hidden by default (opt back in via 'showLikeBadges' once per-client dynamic visibility ships). The fullscreen viewer shows a prominent clickable '@username' profile badge (set the 'username' prop) above the post title and a single Instagram-glyph egress to the post's permalink (a real anchor opening in a new tab). Data is hydrated from the toastability Instagram feed (dataSource type 'instagram_feed', bindTo 'items').",
111570
+ importantUsageNotes: `${GALLERY_MEDIA_NOTE} This is a DYNAMIC feed block: its 'items' are hydrated at routing-build time from the connected Instagram profile \u2014 do NOT hand-author post content. 'items[].image' and 'items[].videoUrl' MUST be the re-hosted MediaRecord CDN URLs served by the feed; expiring Instagram CDN URLs must never be used. Tiles are VERTICAL (9:16) and render both photos and reels; a post is treated as a reel only when 'isVideo' is true AND 'videoUrl' is present. Engagement counts ('likeCount', 'commentCount', 'viewCount') are carried in the data but NOT currently displayed: the tile like-count pill is hidden by default ('showLikeBadges' opts back in; never fabricate a zero for a missing metric) and the viewer's engagement rail was removed per design review. Set 'username' to the account's handle (leading '@' tolerated) \u2014 it renders as the viewer caption's prominent clickable '@username' badge linking to the profile in a new tab; when omitted the badge degrades to a non-clickable 'Instagram' chip (a handle is never fabricated). Tapping a tile OPENS THE FULLSCREEN VIEWER (the whole-tile link-out was replaced); the instagram.com permalink ('items[].href') opens from the viewer's single Instagram-glyph egress, which is rendered as a REAL anchor (target=_blank, rel=noopener noreferrer) \u2014 a crawlable, affordance-correct link, not a scripted window.open button. 'items[].caption' should be a plain STRING when rendered immersively \u2014 it flows through as the tile/viewer title text; a rich ReactNode caption cannot be threaded through the immersive card/viewer and falls back to 'items[].imageAlt' (then a generic label). Consumer image styling is honored: 'imageClassName' and 'optixFlowConfig' are forwarded onto each tile's poster image. Items without an 'image' are skipped; an empty or missing 'items' array renders nothing. Requires the site to have a connected, fully-imported Instagram profile ('instagram_media' capability).`,
111572
111571
  usageRequirements: {
111573
111572
  requiredProps: ["items"],
111574
111573
  requiresSiteCapabilities: galleryCapabilities(
@@ -111600,6 +111599,7 @@ var instagramPostGrid = {
111600
111599
  exampleProps: {
111601
111600
  heading: "Follow us on Instagram",
111602
111601
  subheading: "The latest from our feed.",
111602
+ username: "acmecafe",
111603
111603
  background: "white",
111604
111604
  spacing: "lg",
111605
111605
  items: [
@@ -125110,7 +125110,7 @@ var BLOCK_REGISTRY = {
125110
125110
  "instagram-post-grid": {
125111
125111
  id: "instagram-post-grid",
125112
125112
  name: "Instagram Post Grid",
125113
- description: "A responsive grid of vertical (9:16) tiles rendering a website's Instagram feed. Tapping a tile opens a fullscreen, swipeable immersive viewer (TikTok/Reels-style) with the caption, a read-only engagement rail (likes/comments/views), and an 'Open in Instagram' action. Photos and reels are both first-class media; each tile shows a like-count pill and a hover-only center glyph (play for reels, expand for photos). Content is hydrated dynamically from the connected Instagram profile. Ideal for social proof sections, footers, and community pages that showcase a live Instagram presence.",
125113
+ description: "A responsive grid of vertical (9:16) tiles rendering a website's Instagram feed. Tapping a tile opens a fullscreen, swipeable immersive viewer (TikTok/Reels-style) with a clickable @username profile badge, the post title, and a single Instagram-glyph link to the post. Photos and reels are both first-class media; tiles use a hover-only center glyph (play for reels, expand for photos), with like-count pills hidden by default. Content is hydrated dynamically from the connected Instagram profile. Ideal for social proof sections, footers, and community pages that showcase a live Instagram presence.",
125114
125114
  semanticTags: [
125115
125115
  "gallery",
125116
125116
  "instagram",