@yoamigo.com/core 0.3.0 → 0.3.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/lib.js CHANGED
@@ -116,6 +116,9 @@ var BuilderSelectionManager = class {
116
116
  elementMap = /* @__PURE__ */ new Map();
117
117
  // Current selections from parent (for re-rendering on mode change)
118
118
  currentSelections = [];
119
+ // Throttle screenshot captures to prevent overlapping
120
+ lastCaptureTime = 0;
121
+ CAPTURE_THROTTLE_MS = 3e3;
119
122
  constructor() {
120
123
  if (window.parent === window) {
121
124
  console.log("[BuilderSelection] Not in iframe, skipping initialization");
@@ -239,6 +242,16 @@ var BuilderSelectionManager = class {
239
242
  });
240
243
  };
241
244
  handleKeyDown = (e) => {
245
+ const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
246
+ const modifier = isMac ? e.metaKey : e.ctrlKey;
247
+ if (modifier) {
248
+ if (e.key === "=" || e.key === "+" || e.key === "-" || e.key === "0" || e.key === "1") {
249
+ e.preventDefault();
250
+ const normalizedKey = e.key === "=" ? "+" : e.key;
251
+ this.sendToParent({ type: "IFRAME_KEYBOARD_ZOOM", key: normalizedKey });
252
+ return;
253
+ }
254
+ }
242
255
  if (e.key === "Shift") {
243
256
  const activeElement = document.activeElement;
244
257
  const isEditing = activeElement?.closest(".ya-text-editing") || activeElement?.closest(".ya-link-editing");
@@ -555,10 +568,16 @@ var BuilderSelectionManager = class {
555
568
  /**
556
569
  * Capture a full-page screenshot for loading placeholder
557
570
  * Uses html2canvas to render the page at reduced quality for smaller file size
571
+ * Throttled to prevent overlapping captures (3 second minimum between captures)
558
572
  */
559
573
  async captureFullPageScreenshot() {
574
+ const now = Date.now();
575
+ if (now - this.lastCaptureTime < this.CAPTURE_THROTTLE_MS) {
576
+ console.log("[BuilderSelection] Screenshot throttled");
577
+ return;
578
+ }
579
+ this.lastCaptureTime = now;
560
580
  try {
561
- console.log("[BuilderSelection] Capturing full-page screenshot");
562
581
  const html2canvas = (await import("html2canvas-pro")).default;
563
582
  const overlays = document.querySelectorAll(".builder-selection-container, #builder-hover-overlay");
564
583
  overlays.forEach((el) => {
@@ -571,14 +590,14 @@ var BuilderSelectionManager = class {
571
590
  logging: false,
572
591
  useCORS: true,
573
592
  allowTaint: true,
574
- backgroundColor: null
593
+ backgroundColor: "#ffffff"
594
+ // White background for JPEG (null would render as black)
575
595
  });
576
596
  overlays.forEach((el) => {
577
597
  ;
578
598
  el.style.display = "";
579
599
  });
580
600
  const dataUrl = canvas.toDataURL("image/jpeg", 0.6);
581
- console.log("[BuilderSelection] Full-page screenshot captured, size:", dataUrl.length);
582
601
  this.sendToParent({
583
602
  type: "SCREENSHOT_READY",
584
603
  dataUrl
@@ -698,12 +717,18 @@ var BuilderSelectionManager = class {
698
717
  this.selections.set(selectionId, { element, container, badge, border });
699
718
  }
700
719
  };
720
+ var instance = null;
701
721
  function initBuilderSelection() {
702
722
  if (typeof window !== "undefined" && window.parent !== window) {
723
+ if (instance) {
724
+ return;
725
+ }
703
726
  if (document.readyState === "loading") {
704
- document.addEventListener("DOMContentLoaded", () => new BuilderSelectionManager());
727
+ document.addEventListener("DOMContentLoaded", () => {
728
+ instance = new BuilderSelectionManager();
729
+ });
705
730
  } else {
706
- new BuilderSelectionManager();
731
+ instance = new BuilderSelectionManager();
707
732
  }
708
733
  }
709
734
  }
package/dist/plugin.js CHANGED
@@ -108,6 +108,12 @@ if (import.meta.hot) {
108
108
  outDir: "dist",
109
109
  emptyOutDir: true,
110
110
  rollupOptions: {
111
+ onwarn(warning, warn) {
112
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE" && warning.message.includes('"use client"')) {
113
+ return;
114
+ }
115
+ warn(warning);
116
+ },
111
117
  output: {
112
118
  // Output to build/ to avoid confusion with public/assets/ (source images)
113
119
  entryFileNames: "build/[name].[hash].js",
package/dist/prod.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { a as ContentStore, E as ContentStoreMode, C as ContentStoreProvider, d as MarkdownText, e as MarkdownTextProps, P as PageInfo, b as StaticImage, c as StaticImageProps, M as StaticText, S as StaticTextProps, b as YaImage, c as YaImageProps, M as YaText, S as YaTextProps, u as useContentStore } from './MarkdownText-BUTYfqXS.js';
1
+ export { a as ContentStore, E as ContentStoreMode, C as ContentStoreProvider, d as MarkdownText, e as MarkdownTextProps, P as PageInfo, b as StaticImage, c as StaticImageProps, M as StaticText, S as StaticTextProps, b as YaImage, c as YaImageProps, M as YaText, S as YaTextProps, p as parseEmbedUrl, u as useContentStore } from './MarkdownText-Nvkeyr1z.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import React from 'react';
3
+ import React, { CSSProperties, ReactNode } from 'react';
4
4
  export { Link, LinkProps, NavigateFunction, Router, RouterProps, useNavigate } from './router.js';
5
5
  export { Route, Switch, useParams } from 'wouter';
6
6
  export { A as AssetResolverFn, C as ContentRegistry, c as contentRegistry, a as getAllContent, g as getContent, h as hasContent, r as registerContent, b as resolveAssetUrl, s as setAssetResolver } from './asset-resolver-BnIvDkVv.js';
@@ -33,4 +33,137 @@ interface SafeHtmlProps {
33
33
  }
34
34
  declare function SafeHtml({ content, className }: SafeHtmlProps): react_jsx_runtime.JSX.Element;
35
35
 
36
- export { SafeHtml, type SafeHtmlProps, StaticLink, type StaticLinkProps, StaticLink as YaLink, type StaticLinkProps as YaLinkProps };
36
+ interface BackgroundImageConfig {
37
+ src: string;
38
+ objectFit?: 'cover' | 'contain' | 'fill';
39
+ objectPosition?: string;
40
+ focalPoint?: {
41
+ x: number;
42
+ y: number;
43
+ };
44
+ }
45
+ interface OverlayConfig {
46
+ color: string;
47
+ opacity: number;
48
+ }
49
+ interface BackgroundConfig {
50
+ type: 'none' | 'color' | 'image';
51
+ backgroundColor?: string;
52
+ backgroundImage?: BackgroundImageConfig;
53
+ overlay?: OverlayConfig;
54
+ }
55
+ interface StaticContainerProps {
56
+ fieldId: string;
57
+ className?: string;
58
+ style?: CSSProperties;
59
+ as?: 'section' | 'div' | 'article' | 'header' | 'footer' | 'main' | 'aside';
60
+ children: ReactNode;
61
+ /** Fallback background config if not in store */
62
+ defaultBackground?: BackgroundConfig;
63
+ }
64
+ /**
65
+ * Parse background config from content store
66
+ */
67
+ declare function parseBackgroundConfig(value: string): BackgroundConfig;
68
+ /**
69
+ * Serialize background config for storage
70
+ */
71
+ declare function serializeBackgroundConfig(config: BackgroundConfig): string;
72
+ declare function StaticContainer({ fieldId, className, style, as: Tag, children, defaultBackground, }: StaticContainerProps): react_jsx_runtime.JSX.Element;
73
+
74
+ /**
75
+ * StaticVideo Component - Production version of YaVideo
76
+ *
77
+ * Renders video statically (uploaded, YouTube, or Vimeo embeds).
78
+ * No editing capabilities - pure display.
79
+ */
80
+ interface VideoFieldValue {
81
+ /** Video source type */
82
+ type: 'upload' | 'youtube' | 'vimeo';
83
+ /** Video URL (for upload) or video ID (for embeds) */
84
+ src: string;
85
+ /** Poster image URL */
86
+ poster?: string;
87
+ /** Autoplay video (requires muted for browser policy) */
88
+ autoplay?: boolean;
89
+ /** Mute video audio */
90
+ muted?: boolean;
91
+ /** Loop video playback */
92
+ loop?: boolean;
93
+ /** Show video controls */
94
+ controls?: boolean;
95
+ /** Play inline on mobile (prevent fullscreen hijack) */
96
+ playsinline?: boolean;
97
+ /** Preload strategy */
98
+ preload?: 'none' | 'metadata' | 'auto';
99
+ /** CSS object-fit */
100
+ objectFit?: 'cover' | 'contain' | 'fill';
101
+ /** CSS aspect-ratio (e.g., "16/9") */
102
+ aspectRatio?: string;
103
+ /** Start playback at this time (seconds) */
104
+ startTime?: number;
105
+ /** End playback at this time (seconds) */
106
+ endTime?: number;
107
+ }
108
+ interface StaticVideoProps {
109
+ fieldId: string;
110
+ className?: string;
111
+ /** Default aspect ratio from props */
112
+ aspectRatio?: string;
113
+ /** Default object-fit */
114
+ objectFit?: 'cover' | 'contain' | 'fill';
115
+ /** Loading strategy */
116
+ loading?: 'lazy' | 'eager';
117
+ /** Default video value (used when nothing in content store) */
118
+ defaultValue?: VideoFieldValue;
119
+ /** Fallback for backward compatibility (deprecated: use defaultValue) */
120
+ fallbackSrc?: string;
121
+ /** Fallback poster image */
122
+ fallbackPoster?: string;
123
+ }
124
+ /**
125
+ * Serialize video field value for storage
126
+ */
127
+ declare function serializeVideoValue(value: VideoFieldValue): string;
128
+ declare function StaticVideo({ fieldId, className, aspectRatio: propAspectRatio, objectFit: propObjectFit, loading, defaultValue, fallbackSrc, fallbackPoster, }: StaticVideoProps): react_jsx_runtime.JSX.Element;
129
+
130
+ /**
131
+ * StaticEmbed Component - Production version of YaEmbed
132
+ *
133
+ * Renders embeds statically (Spotify, SoundCloud, Twitter, Instagram, custom).
134
+ * No editing capabilities - pure display.
135
+ */
136
+ type EmbedType = 'spotify' | 'soundcloud' | 'twitter' | 'instagram' | 'custom';
137
+ interface EmbedFieldValue {
138
+ /** Embed platform type */
139
+ type: EmbedType;
140
+ /** Embed URL or ID (platform-specific) */
141
+ src: string;
142
+ /** Original URL pasted by user (for editing) */
143
+ originalUrl?: string;
144
+ /** CSS aspect-ratio (e.g., "16/9", "1/1") */
145
+ aspectRatio?: string;
146
+ /** Fixed height in pixels (for audio players) */
147
+ height?: number;
148
+ /** Spotify-specific: content type */
149
+ spotifyType?: 'track' | 'album' | 'playlist' | 'episode' | 'show';
150
+ }
151
+ interface StaticEmbedProps {
152
+ fieldId: string;
153
+ className?: string;
154
+ /** Default aspect ratio from props */
155
+ aspectRatio?: string;
156
+ /** Max width constraint */
157
+ maxWidth?: number;
158
+ /** Loading strategy */
159
+ loading?: 'lazy' | 'eager';
160
+ /** Default embed value (used when nothing in content store) */
161
+ defaultValue?: EmbedFieldValue;
162
+ }
163
+ /**
164
+ * Serialize embed field value for storage
165
+ */
166
+ declare function serializeEmbedValue(value: EmbedFieldValue): string;
167
+ declare function StaticEmbed({ fieldId, className, aspectRatio: propAspectRatio, maxWidth, loading, defaultValue, }: StaticEmbedProps): react_jsx_runtime.JSX.Element;
168
+
169
+ export { type BackgroundConfig, type BackgroundImageConfig, type EmbedFieldValue, type EmbedType, type OverlayConfig, SafeHtml, type SafeHtmlProps, StaticContainer, type StaticContainerProps, StaticEmbed, type StaticEmbedProps, StaticLink, type StaticLinkProps, StaticVideo, type StaticVideoProps, type VideoFieldValue, StaticContainer as YaContainer, type StaticContainerProps as YaContainerProps, StaticEmbed as YaEmbed, type StaticEmbedProps as YaEmbedProps, StaticLink as YaLink, type StaticLinkProps as YaLinkProps, StaticVideo as YaVideo, type StaticVideoProps as YaVideoProps, parseBackgroundConfig, serializeBackgroundConfig, serializeEmbedValue, serializeVideoValue };