@yoamigo.com/core 0.4.8 → 1.0.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/index.js CHANGED
@@ -895,7 +895,7 @@ var BuilderSelectionManager = class {
895
895
  const navLinks = document.querySelectorAll("nav a[href]");
896
896
  navLinks.forEach((link) => {
897
897
  const href = link.getAttribute("href");
898
- if (href && href.startsWith("/")) {
898
+ if (href?.startsWith("/")) {
899
899
  const path = href.split("?")[0].replace(/\/$/, "") || "/";
900
900
  routes.add(path);
901
901
  }
@@ -907,7 +907,7 @@ var BuilderSelectionManager = class {
907
907
  * Non-blocking: uses requestIdleCallback between pages
908
908
  * Transfers ArrayBuffer directly (zero-copy) for performance
909
909
  */
910
- async captureAllPagesScreenshots(checkpointId, viewport) {
910
+ async captureAllPagesScreenshots(checkpointId, _viewport) {
911
911
  console.log("[BuilderSelection] Starting multi-page capture for checkpoint:", checkpointId);
912
912
  const routes = this.getAllRoutes();
913
913
  const originalPath = window.location.pathname;
@@ -923,7 +923,8 @@ var BuilderSelectionManager = class {
923
923
  try {
924
924
  await new Promise((resolve) => {
925
925
  if ("requestIdleCallback" in window) {
926
- requestIdleCallback(() => resolve(), { timeout: 1e3 });
926
+ ;
927
+ window.requestIdleCallback(() => resolve(), { timeout: 1e3 });
927
928
  } else {
928
929
  setTimeout(resolve, 50);
929
930
  }
@@ -1098,6 +1099,40 @@ function initBuilderSelection() {
1098
1099
  }
1099
1100
  }
1100
1101
 
1102
+ // src/lib/collection-context-registry.ts
1103
+ var registry = /* @__PURE__ */ new Map();
1104
+ function registerCollectionContext(prefix, context) {
1105
+ if (registry.has(prefix)) {
1106
+ console.warn(
1107
+ `[collection-registry] Overwriting existing context for prefix "${prefix}". This usually means multiple CollectionContentProviders with the same prefix are mounted.`
1108
+ );
1109
+ }
1110
+ registry.set(prefix, context);
1111
+ }
1112
+ function unregisterCollectionContext(prefix) {
1113
+ registry.delete(prefix);
1114
+ }
1115
+ function getCollectionContextForField(fieldId) {
1116
+ for (const [prefix, context] of registry) {
1117
+ if (fieldId === prefix || fieldId.startsWith(prefix + ".")) {
1118
+ return context;
1119
+ }
1120
+ }
1121
+ return null;
1122
+ }
1123
+ function getAllCollectionFields() {
1124
+ const result = [];
1125
+ for (const [prefix, context] of registry) {
1126
+ result.push({
1127
+ prefix,
1128
+ recordId: context.recordId,
1129
+ collectionSlug: context.collectionSlug,
1130
+ appId: context.appId
1131
+ });
1132
+ }
1133
+ return result;
1134
+ }
1135
+
1101
1136
  // src/components/ContentStoreProvider.tsx
1102
1137
  import { jsx } from "react/jsx-runtime";
1103
1138
  var ContentStoreContext = createContext(null);
@@ -1292,16 +1327,68 @@ function ContentStoreProvider({
1292
1327
  useEffect(() => {
1293
1328
  modeRef.current = mode;
1294
1329
  }, [mode]);
1330
+ const contentRef = useRef(content);
1331
+ useEffect(() => {
1332
+ contentRef.current = content;
1333
+ }, [content]);
1295
1334
  useEffect(() => {
1296
1335
  ;
1297
1336
  window.yaContentStore = {
1298
- getValue: (fieldId) => getValueRef.current(fieldId),
1299
- setValue: (fieldId, value2, source) => setValueRef.current(fieldId, value2, source),
1300
- getChangeSource: (fieldId) => getChangeSourceRef.current(fieldId),
1337
+ // getValue: Check collection context first, then static content
1338
+ getValue: (fieldId) => {
1339
+ const collectionCtx = getCollectionContextForField(fieldId);
1340
+ if (collectionCtx) {
1341
+ return collectionCtx.getValue(fieldId);
1342
+ }
1343
+ return getValueRef.current(fieldId);
1344
+ },
1345
+ // setValue: Route to collection context if field belongs to one
1346
+ setValue: (fieldId, value2, source) => {
1347
+ const collectionCtx = getCollectionContextForField(fieldId);
1348
+ if (collectionCtx?.setValue) {
1349
+ collectionCtx.setValue(fieldId, value2, source);
1350
+ collectionCtx.saveToBackend?.(fieldId, value2);
1351
+ return;
1352
+ }
1353
+ setValueRef.current(fieldId, value2, source);
1354
+ },
1355
+ // getChangeSource: Check collection context first
1356
+ getChangeSource: (fieldId) => {
1357
+ return getChangeSourceRef.current(fieldId);
1358
+ },
1301
1359
  getMode: () => modeRef.current,
1302
1360
  setMode: (mode2) => setModeRef.current(mode2),
1303
1361
  subscribe: (listener) => subscribeRef.current(listener),
1304
- saveToWorker: saveToWorkerRef.current ? (fieldId, value2) => saveToWorkerRef.current?.(fieldId, value2) : void 0
1362
+ saveToWorker: saveToWorkerRef.current ? (fieldId, value2) => saveToWorkerRef.current?.(fieldId, value2) : void 0,
1363
+ // NEW: Get info about a field (is it static or collection?)
1364
+ getFieldInfo: (fieldId) => {
1365
+ const collectionCtx = getCollectionContextForField(fieldId);
1366
+ if (collectionCtx) {
1367
+ return {
1368
+ isCollectionField: true,
1369
+ collectionSlug: collectionCtx.collectionSlug,
1370
+ recordId: collectionCtx.recordId,
1371
+ prefix: collectionCtx.prefix,
1372
+ appId: collectionCtx.appId
1373
+ };
1374
+ }
1375
+ return {
1376
+ isCollectionField: false,
1377
+ collectionSlug: void 0,
1378
+ recordId: void 0,
1379
+ prefix: void 0,
1380
+ appId: void 0
1381
+ };
1382
+ },
1383
+ // NEW: List all editable fields (for AI discovery)
1384
+ listEditableFields: () => {
1385
+ const staticFields = Array.from(contentRef.current.keys());
1386
+ const collectionFields = getAllCollectionFields();
1387
+ return {
1388
+ static: staticFields,
1389
+ collection: collectionFields
1390
+ };
1391
+ }
1305
1392
  };
1306
1393
  return () => {
1307
1394
  delete window.yaContentStore;
@@ -1389,7 +1476,7 @@ function ContentStoreProvider2({ children, initialContent }) {
1389
1476
  }
1390
1477
 
1391
1478
  // src/components/YaText.tsx
1392
- import { useEffect as useEffect7, useRef as useRef8, useState as useState7, useCallback as useCallback9 } from "react";
1479
+ import { useEffect as useEffect8, useRef as useRef9, useState as useState8, useCallback as useCallback10 } from "react";
1393
1480
  import { createPortal as createPortal4 } from "react-dom";
1394
1481
  import { useEditor, EditorContent } from "@tiptap/react";
1395
1482
 
@@ -1499,11 +1586,322 @@ import Link from "@tiptap/extension-link";
1499
1586
  import { TextStyle } from "@tiptap/extension-text-style";
1500
1587
  import { Extension } from "@tiptap/core";
1501
1588
 
1589
+ // src/hooks/useContent.ts
1590
+ import { useMemo as useMemo3 } from "react";
1591
+
1592
+ // src/components/CollectionContentProvider.tsx
1593
+ import {
1594
+ createContext as createContext3,
1595
+ useCallback as useCallback3,
1596
+ useContext as useContext3,
1597
+ useEffect as useEffect3,
1598
+ useMemo as useMemo2,
1599
+ useRef as useRef3,
1600
+ useState as useState3
1601
+ } from "react";
1602
+ import { jsx as jsx4 } from "react/jsx-runtime";
1603
+ var CollectionContentContext = createContext3(null);
1604
+ function useCollectionContent() {
1605
+ return useContext3(CollectionContentContext);
1606
+ }
1607
+ function extractSessionId2() {
1608
+ if (typeof window === "undefined") return null;
1609
+ const match = window.location.pathname.match(/\/session\/([^/]+)/);
1610
+ return match ? match[1] : null;
1611
+ }
1612
+ function isBuilderPreview2() {
1613
+ return typeof window !== "undefined" && (window.__YOAMIGO_EDIT_MODE__ === true || typeof import.meta !== "undefined" && import.meta.env?.YA_EDIT_MODE === "true");
1614
+ }
1615
+ function flattenObject(obj, prefix) {
1616
+ const result = {};
1617
+ function flatten(current, currentPath) {
1618
+ if (current === null || current === void 0) {
1619
+ result[currentPath] = "";
1620
+ return;
1621
+ }
1622
+ if (typeof current === "string") {
1623
+ result[currentPath] = current;
1624
+ return;
1625
+ }
1626
+ if (typeof current === "number" || typeof current === "boolean") {
1627
+ result[currentPath] = String(current);
1628
+ return;
1629
+ }
1630
+ if (Array.isArray(current)) {
1631
+ result[currentPath] = JSON.stringify(current);
1632
+ current.forEach((item, index) => {
1633
+ flatten(item, `${currentPath}.${index}`);
1634
+ });
1635
+ return;
1636
+ }
1637
+ if (typeof current === "object") {
1638
+ const record = current;
1639
+ if (record.src && typeof record.src === "string") {
1640
+ result[currentPath] = JSON.stringify(current);
1641
+ }
1642
+ for (const [key, value] of Object.entries(record)) {
1643
+ flatten(value, `${currentPath}.${key}`);
1644
+ }
1645
+ }
1646
+ }
1647
+ for (const [key, value] of Object.entries(obj)) {
1648
+ flatten(value, `${prefix}.${key}`);
1649
+ }
1650
+ return result;
1651
+ }
1652
+ function CollectionContentProvider({
1653
+ record,
1654
+ prefix,
1655
+ children,
1656
+ recordId,
1657
+ collectionSlug,
1658
+ appId,
1659
+ // changeType is auto-determined from recordId presence
1660
+ changeType: _changeType = "UPDATE"
1661
+ }) {
1662
+ const isEditable = Boolean(
1663
+ collectionSlug && appId && isBuilderPreview2()
1664
+ );
1665
+ const baseContentMap = useMemo2(() => {
1666
+ return flattenObject(record, prefix);
1667
+ }, [record, prefix]);
1668
+ const [localOverrides, setLocalOverrides] = useState3({});
1669
+ const [changeSourceMap, setChangeSourceMap] = useState3({});
1670
+ const isMountedRef = useRef3(true);
1671
+ useEffect3(() => {
1672
+ isMountedRef.current = true;
1673
+ return () => {
1674
+ isMountedRef.current = false;
1675
+ };
1676
+ }, []);
1677
+ const getValue = useCallback3(
1678
+ (fieldId) => {
1679
+ if (fieldId in localOverrides) {
1680
+ return localOverrides[fieldId];
1681
+ }
1682
+ if (fieldId in baseContentMap) {
1683
+ return baseContentMap[fieldId];
1684
+ }
1685
+ const prefixedFieldId = fieldId.startsWith(prefix + ".") ? fieldId : `${prefix}.${fieldId}`;
1686
+ if (prefixedFieldId in localOverrides) {
1687
+ return localOverrides[prefixedFieldId];
1688
+ }
1689
+ if (prefixedFieldId in baseContentMap) {
1690
+ return baseContentMap[prefixedFieldId];
1691
+ }
1692
+ return "";
1693
+ },
1694
+ [baseContentMap, localOverrides, prefix]
1695
+ );
1696
+ const setValue = useCallback3(
1697
+ (fieldId, value, source = "ai") => {
1698
+ if (!isEditable) {
1699
+ console.warn("[CollectionContentProvider] setValue called but editing is not enabled");
1700
+ return;
1701
+ }
1702
+ setLocalOverrides((prev) => ({ ...prev, [fieldId]: value }));
1703
+ setChangeSourceMap((prev) => ({ ...prev, [fieldId]: source }));
1704
+ },
1705
+ [isEditable]
1706
+ );
1707
+ const getChangeSource = useCallback3(
1708
+ (fieldId) => changeSourceMap[fieldId] || "initial",
1709
+ [changeSourceMap]
1710
+ );
1711
+ const clearChangeSource = useCallback3(
1712
+ (fieldId) => {
1713
+ setChangeSourceMap((prev) => {
1714
+ const next = { ...prev };
1715
+ delete next[fieldId];
1716
+ return next;
1717
+ });
1718
+ },
1719
+ []
1720
+ );
1721
+ const saveToBackend = useCallback3(
1722
+ async (fieldId, value) => {
1723
+ if (!isEditable) {
1724
+ console.warn("[CollectionContentProvider] saveToBackend called but editing is not enabled");
1725
+ return;
1726
+ }
1727
+ const sessionId = extractSessionId2();
1728
+ if (!sessionId) {
1729
+ console.warn("[CollectionContentProvider] saveToBackend: Not in builder preview mode, skipping");
1730
+ return;
1731
+ }
1732
+ try {
1733
+ const response = await fetch(`/api/session/${sessionId}/collection-edit`, {
1734
+ method: "POST",
1735
+ headers: { "Content-Type": "application/json" },
1736
+ credentials: "include",
1737
+ body: JSON.stringify({
1738
+ fieldId,
1739
+ value,
1740
+ recordId,
1741
+ collectionSlug,
1742
+ appId,
1743
+ changeType: recordId ? "UPDATE" : "CREATE"
1744
+ })
1745
+ });
1746
+ if (!response.ok) {
1747
+ const error = await response.json();
1748
+ console.error("[CollectionContentProvider] saveToBackend failed:", error);
1749
+ throw new Error(error.error || "Failed to save collection edit");
1750
+ }
1751
+ console.log(`[CollectionContentProvider] Saved ${fieldId} to staging`);
1752
+ } catch (error) {
1753
+ console.error("[CollectionContentProvider] saveToBackend error:", error);
1754
+ throw error;
1755
+ }
1756
+ },
1757
+ [isEditable, recordId, collectionSlug, appId]
1758
+ );
1759
+ const contextValue = useMemo2(() => ({
1760
+ getValue,
1761
+ setValue: isEditable ? setValue : void 0,
1762
+ saveToBackend: isEditable ? saveToBackend : void 0,
1763
+ getChangeSource: isEditable ? getChangeSource : void 0,
1764
+ clearChangeSource: isEditable ? clearChangeSource : void 0,
1765
+ isCollectionContent: true,
1766
+ prefix,
1767
+ recordId,
1768
+ collectionSlug,
1769
+ appId,
1770
+ isEditable
1771
+ }), [
1772
+ getValue,
1773
+ setValue,
1774
+ saveToBackend,
1775
+ getChangeSource,
1776
+ clearChangeSource,
1777
+ isEditable,
1778
+ prefix,
1779
+ recordId,
1780
+ collectionSlug,
1781
+ appId
1782
+ ]);
1783
+ const contextValueRef = useRef3(contextValue);
1784
+ useEffect3(() => {
1785
+ contextValueRef.current = contextValue;
1786
+ }, [contextValue]);
1787
+ useEffect3(() => {
1788
+ if (!isEditable) return;
1789
+ const registryContext = {
1790
+ getValue: (fid) => contextValueRef.current.getValue(fid),
1791
+ setValue: (fid, val, src) => {
1792
+ contextValueRef.current.setValue?.(fid, val, src);
1793
+ },
1794
+ saveToBackend: (fid, val) => {
1795
+ return contextValueRef.current.saveToBackend?.(fid, val) ?? Promise.resolve();
1796
+ },
1797
+ prefix,
1798
+ recordId,
1799
+ collectionSlug,
1800
+ appId
1801
+ };
1802
+ registerCollectionContext(prefix, registryContext);
1803
+ return () => {
1804
+ unregisterCollectionContext(prefix);
1805
+ };
1806
+ }, [isEditable, prefix, recordId, collectionSlug, appId]);
1807
+ return /* @__PURE__ */ jsx4(CollectionContentContext.Provider, { value: contextValue, children });
1808
+ }
1809
+
1810
+ // src/types/fields.ts
1811
+ function parseFieldValue(raw) {
1812
+ if (!raw) {
1813
+ return {};
1814
+ }
1815
+ if (typeof raw === "string") {
1816
+ if (raw.startsWith("{") || raw.startsWith("[")) {
1817
+ try {
1818
+ return JSON.parse(raw);
1819
+ } catch {
1820
+ return raw;
1821
+ }
1822
+ }
1823
+ return raw;
1824
+ }
1825
+ return raw;
1826
+ }
1827
+ function stringifyFieldValue(value) {
1828
+ if (typeof value === "string") {
1829
+ return value;
1830
+ }
1831
+ return JSON.stringify(value);
1832
+ }
1833
+
1834
+ // src/hooks/useContent.ts
1835
+ function useContent(fieldId) {
1836
+ const contentStore = useContentStore();
1837
+ const collectionContext = useCollectionContent();
1838
+ const isInCollection = Boolean(
1839
+ collectionContext?.isEditable && fieldId.startsWith(collectionContext.prefix + ".")
1840
+ );
1841
+ return useMemo3(() => {
1842
+ const getValueFn = () => {
1843
+ return isInCollection ? collectionContext.getValue(fieldId) : contentStore.getValue(fieldId);
1844
+ };
1845
+ const setValueFn = (value, source) => {
1846
+ if (isInCollection && collectionContext.setValue) {
1847
+ collectionContext.setValue(fieldId, value, source);
1848
+ } else {
1849
+ contentStore.setValue(fieldId, value, source);
1850
+ }
1851
+ };
1852
+ const saveFn = async () => {
1853
+ const value = getValueFn();
1854
+ if (isInCollection && collectionContext.saveToBackend) {
1855
+ await collectionContext.saveToBackend(fieldId, value);
1856
+ } else if (contentStore.saveToWorker) {
1857
+ await contentStore.saveToWorker(fieldId, value);
1858
+ }
1859
+ };
1860
+ const getChangeSourceFn = () => {
1861
+ if (isInCollection) {
1862
+ return collectionContext.getChangeSource?.(fieldId);
1863
+ }
1864
+ return contentStore.getChangeSource?.(fieldId);
1865
+ };
1866
+ const clearChangeSourceFn = () => {
1867
+ if (isInCollection) {
1868
+ collectionContext.clearChangeSource?.(fieldId);
1869
+ } else {
1870
+ contentStore.clearChangeSource?.(fieldId);
1871
+ }
1872
+ };
1873
+ return {
1874
+ get value() {
1875
+ const raw = getValueFn();
1876
+ return parseFieldValue(raw);
1877
+ },
1878
+ get() {
1879
+ return getValueFn();
1880
+ },
1881
+ set(value, source) {
1882
+ const stringValue = typeof value === "string" ? value : stringifyFieldValue(value);
1883
+ setValueFn(stringValue, source);
1884
+ },
1885
+ async save() {
1886
+ await saveFn();
1887
+ },
1888
+ get changeSource() {
1889
+ return getChangeSourceFn();
1890
+ },
1891
+ clearChangeSource() {
1892
+ clearChangeSourceFn();
1893
+ },
1894
+ mode: contentStore.mode,
1895
+ isCollectionField: isInCollection
1896
+ };
1897
+ }, [fieldId, isInCollection, collectionContext, contentStore]);
1898
+ }
1899
+
1502
1900
  // src/components/SafeHtml.tsx
1503
- import { useEffect as useEffect3, useRef as useRef3, useState as useState3, useCallback as useCallback3 } from "react";
1901
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState4, useCallback as useCallback4 } from "react";
1504
1902
  import { createPortal as createPortal2 } from "react-dom";
1505
1903
  import DOMPurify from "dompurify";
1506
- import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
1904
+ import { Fragment, jsx as jsx5, jsxs } from "react/jsx-runtime";
1507
1905
  var ALLOWED_TAGS = ["strong", "em", "a", "span", "br", "b", "i", "u"];
1508
1906
  var ALLOWED_ATTR = ["href", "style", "class", "target", "rel"];
1509
1907
  if (typeof window !== "undefined") {
@@ -1561,8 +1959,8 @@ function LinkIcon() {
1561
1959
  strokeLinecap: "round",
1562
1960
  strokeLinejoin: "round",
1563
1961
  children: [
1564
- /* @__PURE__ */ jsx4("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
1565
- /* @__PURE__ */ jsx4("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
1962
+ /* @__PURE__ */ jsx5("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
1963
+ /* @__PURE__ */ jsx5("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
1566
1964
  ]
1567
1965
  }
1568
1966
  );
@@ -1594,20 +1992,20 @@ function LinkPopover({
1594
1992
  }
1595
1993
  },
1596
1994
  children: [
1597
- /* @__PURE__ */ jsx4(LinkIcon, {}),
1995
+ /* @__PURE__ */ jsx5(LinkIcon, {}),
1598
1996
  /* @__PURE__ */ jsxs("span", { className: "ya-link-popover-text", children: [
1599
- /* @__PURE__ */ jsx4("span", { className: "ya-link-popover-prefix", children: "Go to " }),
1600
- /* @__PURE__ */ jsx4("span", { className: "ya-link-popover-name", children: displayText })
1997
+ /* @__PURE__ */ jsx5("span", { className: "ya-link-popover-prefix", children: "Go to " }),
1998
+ /* @__PURE__ */ jsx5("span", { className: "ya-link-popover-name", children: displayText })
1601
1999
  ] })
1602
2000
  ]
1603
2001
  }
1604
2002
  );
1605
2003
  }
1606
2004
  function SafeHtml({ content, className, mode = "read-only" }) {
1607
- const containerRef = useRef3(null);
1608
- const showTimerRef = useRef3(void 0);
1609
- const hideTimerRef = useRef3(void 0);
1610
- const [popoverState, setPopoverState] = useState3({
2005
+ const containerRef = useRef4(null);
2006
+ const showTimerRef = useRef4(void 0);
2007
+ const hideTimerRef = useRef4(void 0);
2008
+ const [popoverState, setPopoverState] = useState4({
1611
2009
  isVisible: false,
1612
2010
  href: "",
1613
2011
  displayText: "",
@@ -1618,20 +2016,20 @@ function SafeHtml({ content, className, mode = "read-only" }) {
1618
2016
  ALLOWED_TAGS,
1619
2017
  ALLOWED_ATTR
1620
2018
  });
1621
- const hidePopover = useCallback3(() => {
2019
+ const hidePopover = useCallback4(() => {
1622
2020
  clearTimeout(showTimerRef.current);
1623
2021
  setPopoverState((prev) => ({ ...prev, isVisible: false }));
1624
2022
  }, []);
1625
- const scheduleHide = useCallback3(() => {
2023
+ const scheduleHide = useCallback4(() => {
1626
2024
  clearTimeout(showTimerRef.current);
1627
2025
  hideTimerRef.current = window.setTimeout(() => {
1628
2026
  hidePopover();
1629
2027
  }, 100);
1630
2028
  }, [hidePopover]);
1631
- const cancelHide = useCallback3(() => {
2029
+ const cancelHide = useCallback4(() => {
1632
2030
  clearTimeout(hideTimerRef.current);
1633
2031
  }, []);
1634
- const handlePopoverClick = useCallback3(() => {
2032
+ const handlePopoverClick = useCallback4(() => {
1635
2033
  if (popoverState.isExternal) {
1636
2034
  window.open(popoverState.href, "_blank", "noopener,noreferrer");
1637
2035
  } else {
@@ -1639,7 +2037,7 @@ function SafeHtml({ content, className, mode = "read-only" }) {
1639
2037
  }
1640
2038
  hidePopover();
1641
2039
  }, [popoverState.href, popoverState.isExternal, hidePopover]);
1642
- useEffect3(() => {
2040
+ useEffect4(() => {
1643
2041
  if (mode !== "inline-edit" || !containerRef.current) return;
1644
2042
  const container = containerRef.current;
1645
2043
  const handleMouseOver = (e) => {
@@ -1697,7 +2095,7 @@ function SafeHtml({ content, className, mode = "read-only" }) {
1697
2095
  };
1698
2096
  }, [mode, scheduleHide]);
1699
2097
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1700
- /* @__PURE__ */ jsx4(
2098
+ /* @__PURE__ */ jsx5(
1701
2099
  "span",
1702
2100
  {
1703
2101
  ref: containerRef,
@@ -1706,7 +2104,7 @@ function SafeHtml({ content, className, mode = "read-only" }) {
1706
2104
  }
1707
2105
  ),
1708
2106
  mode === "inline-edit" && popoverState.isVisible && createPortal2(
1709
- /* @__PURE__ */ jsx4(
2107
+ /* @__PURE__ */ jsx5(
1710
2108
  LinkPopover,
1711
2109
  {
1712
2110
  displayText: popoverState.displayText,
@@ -1722,37 +2120,37 @@ function SafeHtml({ content, className, mode = "read-only" }) {
1722
2120
  }
1723
2121
 
1724
2122
  // src/hooks/useAnimatedText.ts
1725
- import { useMemo as useMemo4 } from "react";
2123
+ import { useMemo as useMemo6 } from "react";
1726
2124
 
1727
2125
  // src/hooks/useAIEditAnimation.ts
1728
- import { useState as useState4, useEffect as useEffect4, useRef as useRef5, useCallback as useCallback5, useMemo as useMemo3 } from "react";
2126
+ import { useState as useState5, useEffect as useEffect5, useRef as useRef6, useCallback as useCallback6, useMemo as useMemo5 } from "react";
1729
2127
 
1730
2128
  // src/contexts/AIEditContext.tsx
1731
- import { createContext as createContext3, useContext as useContext3, useCallback as useCallback4, useRef as useRef4, useMemo as useMemo2 } from "react";
1732
- import { jsx as jsx5 } from "react/jsx-runtime";
1733
- var AIEditContext = createContext3(null);
2129
+ import { createContext as createContext4, useContext as useContext4, useCallback as useCallback5, useRef as useRef5, useMemo as useMemo4 } from "react";
2130
+ import { jsx as jsx6 } from "react/jsx-runtime";
2131
+ var AIEditContext = createContext4(null);
1734
2132
  function useAIEditContext() {
1735
- const context = useContext3(AIEditContext);
2133
+ const context = useContext4(AIEditContext);
1736
2134
  if (!context) {
1737
2135
  throw new Error("useAIEditContext must be used within an AIEditProvider");
1738
2136
  }
1739
2137
  return context;
1740
2138
  }
1741
2139
  function useAIEditContextOptional() {
1742
- return useContext3(AIEditContext);
2140
+ return useContext4(AIEditContext);
1743
2141
  }
1744
2142
  function AIEditProvider({ children, staggerDelay = 100 }) {
1745
- const animationsRef = useRef4(/* @__PURE__ */ new Map());
1746
- const listenersRef = useRef4(/* @__PURE__ */ new Map());
1747
- const queueRef = useRef4([]);
1748
- const processingRef = useRef4(false);
1749
- const notifyListeners = useCallback4((fieldId) => {
2143
+ const animationsRef = useRef5(/* @__PURE__ */ new Map());
2144
+ const listenersRef = useRef5(/* @__PURE__ */ new Map());
2145
+ const queueRef = useRef5([]);
2146
+ const processingRef = useRef5(false);
2147
+ const notifyListeners = useCallback5((fieldId) => {
1750
2148
  const listeners = listenersRef.current.get(fieldId);
1751
2149
  if (listeners) {
1752
2150
  listeners.forEach((listener) => listener());
1753
2151
  }
1754
2152
  }, []);
1755
- const processQueue = useCallback4(() => {
2153
+ const processQueue = useCallback5(() => {
1756
2154
  if (processingRef.current || queueRef.current.length === 0) return;
1757
2155
  processingRef.current = true;
1758
2156
  const fieldId = queueRef.current.shift();
@@ -1767,7 +2165,7 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1767
2165
  processQueue();
1768
2166
  }, staggerDelay);
1769
2167
  }, [staggerDelay, notifyListeners]);
1770
- const queueAnimation = useCallback4(
2168
+ const queueAnimation = useCallback5(
1771
2169
  (fieldId, config) => {
1772
2170
  const existing = animationsRef.current.get(fieldId);
1773
2171
  if (existing?.status === "animating") {
@@ -1790,7 +2188,7 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1790
2188
  },
1791
2189
  [notifyListeners, processQueue]
1792
2190
  );
1793
- const cancelAnimation = useCallback4(
2191
+ const cancelAnimation = useCallback5(
1794
2192
  (fieldId) => {
1795
2193
  const state = animationsRef.current.get(fieldId);
1796
2194
  if (state) {
@@ -1804,14 +2202,14 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1804
2202
  },
1805
2203
  [notifyListeners]
1806
2204
  );
1807
- const isAnimating = useCallback4((fieldId) => {
2205
+ const isAnimating = useCallback5((fieldId) => {
1808
2206
  const state = animationsRef.current.get(fieldId);
1809
2207
  return state?.status === "animating" || state?.status === "pending";
1810
2208
  }, []);
1811
- const getAnimationState = useCallback4((fieldId) => {
2209
+ const getAnimationState = useCallback5((fieldId) => {
1812
2210
  return animationsRef.current.get(fieldId);
1813
2211
  }, []);
1814
- const subscribe = useCallback4((fieldId, listener) => {
2212
+ const subscribe = useCallback5((fieldId, listener) => {
1815
2213
  let listeners = listenersRef.current.get(fieldId);
1816
2214
  if (!listeners) {
1817
2215
  listeners = /* @__PURE__ */ new Set();
@@ -1825,7 +2223,7 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1825
2223
  }
1826
2224
  };
1827
2225
  }, []);
1828
- const completeAnimation = useCallback4(
2226
+ const completeAnimation = useCallback5(
1829
2227
  (fieldId) => {
1830
2228
  const state = animationsRef.current.get(fieldId);
1831
2229
  if (state) {
@@ -1840,7 +2238,7 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1840
2238
  },
1841
2239
  [notifyListeners]
1842
2240
  );
1843
- const value = useMemo2(
2241
+ const value = useMemo4(
1844
2242
  () => ({
1845
2243
  queueAnimation,
1846
2244
  cancelAnimation,
@@ -1851,7 +2249,7 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
1851
2249
  }),
1852
2250
  [queueAnimation, cancelAnimation, isAnimating, getAnimationState, subscribe, completeAnimation]
1853
2251
  );
1854
- return /* @__PURE__ */ jsx5(AIEditContext.Provider, { value, children });
2252
+ return /* @__PURE__ */ jsx6(AIEditContext.Provider, { value, children });
1855
2253
  }
1856
2254
 
1857
2255
  // src/hooks/useAIEditAnimation.ts
@@ -1859,15 +2257,15 @@ function useAIEditAnimation(fieldId, value, options) {
1859
2257
  const { enabled = true, strategy, maxDuration = 2e3, onStart, onComplete } = options;
1860
2258
  const context = useAIEditContextOptional();
1861
2259
  const { getChangeSource, clearChangeSource } = useContentStore();
1862
- const previousValueRef = useRef5(value);
1863
- const isFirstRender = useRef5(true);
1864
- const [phase, setPhase] = useState4("idle");
1865
- const [progress, setProgress] = useState4(0);
1866
- const [displayValue, setDisplayValue] = useState4(value);
1867
- const metadataRef = useRef5(null);
1868
- const animationFrameRef = useRef5(null);
1869
- const startTimeRef = useRef5(0);
1870
- const cancel = useCallback5(() => {
2260
+ const previousValueRef = useRef6(value);
2261
+ const isFirstRender = useRef6(true);
2262
+ const [phase, setPhase] = useState5("idle");
2263
+ const [progress, setProgress] = useState5(0);
2264
+ const [displayValue, setDisplayValue] = useState5(value);
2265
+ const metadataRef = useRef6(null);
2266
+ const animationFrameRef = useRef6(null);
2267
+ const startTimeRef = useRef6(0);
2268
+ const cancel = useCallback6(() => {
1871
2269
  if (animationFrameRef.current !== null) {
1872
2270
  cancelAnimationFrame(animationFrameRef.current);
1873
2271
  animationFrameRef.current = null;
@@ -1878,7 +2276,7 @@ function useAIEditAnimation(fieldId, value, options) {
1878
2276
  metadataRef.current = null;
1879
2277
  context?.cancelAnimation(fieldId);
1880
2278
  }, [value, context, fieldId]);
1881
- const runAnimation = useCallback5(() => {
2279
+ const runAnimation = useCallback6(() => {
1882
2280
  if (!metadataRef.current) return;
1883
2281
  const metadata = metadataRef.current;
1884
2282
  const elapsed = performance.now() - startTimeRef.current;
@@ -1903,7 +2301,7 @@ function useAIEditAnimation(fieldId, value, options) {
1903
2301
  setDisplayValue(interpolatedValue);
1904
2302
  animationFrameRef.current = requestAnimationFrame(runAnimation);
1905
2303
  }, [strategy, maxDuration, context, fieldId, onComplete, clearChangeSource]);
1906
- useEffect4(() => {
2304
+ useEffect5(() => {
1907
2305
  if (isFirstRender.current) {
1908
2306
  isFirstRender.current = false;
1909
2307
  previousValueRef.current = value;
@@ -1957,14 +2355,14 @@ function useAIEditAnimation(fieldId, value, options) {
1957
2355
  }
1958
2356
  };
1959
2357
  }, [value, enabled, strategy, context, fieldId, maxDuration, onStart, runAnimation, getChangeSource, clearChangeSource]);
1960
- useEffect4(() => {
2358
+ useEffect5(() => {
1961
2359
  return () => {
1962
2360
  if (animationFrameRef.current !== null) {
1963
2361
  cancelAnimationFrame(animationFrameRef.current);
1964
2362
  }
1965
2363
  };
1966
2364
  }, []);
1967
- const wrapperProps = useMemo3(
2365
+ const wrapperProps = useMemo5(
1968
2366
  () => ({
1969
2367
  className: phase === "animating" ? "ya-ai-editing" : phase === "complete" ? "ya-ai-complete" : "",
1970
2368
  "data-ai-editing": phase === "animating"
@@ -2186,7 +2584,7 @@ function useAnimatedText(fieldId, content, options = {}) {
2186
2584
  onStart,
2187
2585
  onComplete
2188
2586
  } = options;
2189
- const customStrategy = useMemo4(() => {
2587
+ const customStrategy = useMemo6(() => {
2190
2588
  if (charDelay === 50) {
2191
2589
  return textTypingStrategy;
2192
2590
  }
@@ -2225,7 +2623,7 @@ function useAnimatedText(fieldId, content, options = {}) {
2225
2623
  onStart,
2226
2624
  onComplete
2227
2625
  });
2228
- const cursorPosition = useMemo4(() => {
2626
+ const cursorPosition = useMemo6(() => {
2229
2627
  if (!isAnimating) return null;
2230
2628
  const diff = computeTextDiff(content, displayValue);
2231
2629
  const { deleteDuration, typeDuration } = calculateAnimationTiming(diff, {
@@ -2256,7 +2654,7 @@ function useAnimatedText(fieldId, content, options = {}) {
2256
2654
  }
2257
2655
 
2258
2656
  // src/components/BubbleIcons.tsx
2259
- import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
2657
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
2260
2658
  function BoldIcon({ size = 16, className }) {
2261
2659
  return /* @__PURE__ */ jsxs2(
2262
2660
  "svg",
@@ -2271,8 +2669,8 @@ function BoldIcon({ size = 16, className }) {
2271
2669
  strokeLinejoin: "round",
2272
2670
  className,
2273
2671
  children: [
2274
- /* @__PURE__ */ jsx6("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
2275
- /* @__PURE__ */ jsx6("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
2672
+ /* @__PURE__ */ jsx7("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
2673
+ /* @__PURE__ */ jsx7("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
2276
2674
  ]
2277
2675
  }
2278
2676
  );
@@ -2291,9 +2689,9 @@ function ItalicIcon({ size = 16, className }) {
2291
2689
  strokeLinejoin: "round",
2292
2690
  className,
2293
2691
  children: [
2294
- /* @__PURE__ */ jsx6("line", { x1: "19", y1: "4", x2: "10", y2: "4" }),
2295
- /* @__PURE__ */ jsx6("line", { x1: "14", y1: "20", x2: "5", y2: "20" }),
2296
- /* @__PURE__ */ jsx6("line", { x1: "15", y1: "4", x2: "9", y2: "20" })
2692
+ /* @__PURE__ */ jsx7("line", { x1: "19", y1: "4", x2: "10", y2: "4" }),
2693
+ /* @__PURE__ */ jsx7("line", { x1: "14", y1: "20", x2: "5", y2: "20" }),
2694
+ /* @__PURE__ */ jsx7("line", { x1: "15", y1: "4", x2: "9", y2: "20" })
2297
2695
  ]
2298
2696
  }
2299
2697
  );
@@ -2312,14 +2710,14 @@ function LinkIcon2({ size = 16, className }) {
2312
2710
  strokeLinejoin: "round",
2313
2711
  className,
2314
2712
  children: [
2315
- /* @__PURE__ */ jsx6("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
2316
- /* @__PURE__ */ jsx6("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
2713
+ /* @__PURE__ */ jsx7("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
2714
+ /* @__PURE__ */ jsx7("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
2317
2715
  ]
2318
2716
  }
2319
2717
  );
2320
2718
  }
2321
2719
  function ChevronDownIcon({ size = 12, className }) {
2322
- return /* @__PURE__ */ jsx6(
2720
+ return /* @__PURE__ */ jsx7(
2323
2721
  "svg",
2324
2722
  {
2325
2723
  width: size,
@@ -2331,15 +2729,15 @@ function ChevronDownIcon({ size = 12, className }) {
2331
2729
  strokeLinecap: "round",
2332
2730
  strokeLinejoin: "round",
2333
2731
  className,
2334
- children: /* @__PURE__ */ jsx6("polyline", { points: "6 9 12 15 18 9" })
2732
+ children: /* @__PURE__ */ jsx7("polyline", { points: "6 9 12 15 18 9" })
2335
2733
  }
2336
2734
  );
2337
2735
  }
2338
2736
 
2339
2737
  // src/components/BubbleDropdown.tsx
2340
- import { useEffect as useEffect5, useLayoutEffect as useLayoutEffect2, useState as useState5, useRef as useRef6, useCallback as useCallback6 } from "react";
2738
+ import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useState as useState6, useRef as useRef7, useCallback as useCallback7 } from "react";
2341
2739
  import { createPortal as createPortal3 } from "react-dom";
2342
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
2740
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
2343
2741
  function BubbleDropdown({
2344
2742
  label,
2345
2743
  open,
@@ -2348,14 +2746,14 @@ function BubbleDropdown({
2348
2746
  triggerClassName = "",
2349
2747
  panelClassName = ""
2350
2748
  }) {
2351
- const triggerRef = useRef6(null);
2352
- const panelRef = useRef6(null);
2353
- const [position, setPosition] = useState5(null);
2354
- const [isMounted, setIsMounted] = useState5(false);
2355
- useEffect5(() => {
2749
+ const triggerRef = useRef7(null);
2750
+ const panelRef = useRef7(null);
2751
+ const [position, setPosition] = useState6(null);
2752
+ const [isMounted, setIsMounted] = useState6(false);
2753
+ useEffect6(() => {
2356
2754
  setIsMounted(true);
2357
2755
  }, []);
2358
- const calculatePosition = useCallback6(() => {
2756
+ const calculatePosition = useCallback7(() => {
2359
2757
  if (!triggerRef.current) return null;
2360
2758
  const triggerRect = triggerRef.current.getBoundingClientRect();
2361
2759
  const gap = 4;
@@ -2371,7 +2769,7 @@ function BubbleDropdown({
2371
2769
  }
2372
2770
  return { top, left, adjusted: false };
2373
2771
  }, []);
2374
- useEffect5(() => {
2772
+ useEffect6(() => {
2375
2773
  if (open) {
2376
2774
  const pos = calculatePosition();
2377
2775
  setPosition(pos);
@@ -2400,7 +2798,7 @@ function BubbleDropdown({
2400
2798
  setPosition((prev) => prev ? { ...prev, adjusted: true } : null);
2401
2799
  }
2402
2800
  }, [open, position]);
2403
- useEffect5(() => {
2801
+ useEffect6(() => {
2404
2802
  if (!open) return;
2405
2803
  const handleClickOutside = (e) => {
2406
2804
  if (triggerRef.current?.contains(e.target) || panelRef.current?.contains(e.target)) {
@@ -2453,13 +2851,13 @@ function BubbleDropdown({
2453
2851
  onClick: handleTriggerClick,
2454
2852
  onMouseDown: handleTriggerMouseDown,
2455
2853
  children: [
2456
- /* @__PURE__ */ jsx7("span", { className: "ya-bubble-dropdown-label", children: label }),
2457
- /* @__PURE__ */ jsx7(ChevronDownIcon, { size: 10, className: `ya-bubble-dropdown-arrow ${open ? "is-open" : ""}` })
2854
+ /* @__PURE__ */ jsx8("span", { className: "ya-bubble-dropdown-label", children: label }),
2855
+ /* @__PURE__ */ jsx8(ChevronDownIcon, { size: 10, className: `ya-bubble-dropdown-arrow ${open ? "is-open" : ""}` })
2458
2856
  ]
2459
2857
  }
2460
2858
  ),
2461
2859
  isMounted && open && position && createPortal3(
2462
- /* @__PURE__ */ jsx7(
2860
+ /* @__PURE__ */ jsx8(
2463
2861
  "div",
2464
2862
  {
2465
2863
  ref: panelRef,
@@ -2475,8 +2873,8 @@ function BubbleDropdown({
2475
2873
  }
2476
2874
 
2477
2875
  // src/components/FontSizePicker.tsx
2478
- import { useState as useState6, useEffect as useEffect6, useCallback as useCallback7, useRef as useRef7 } from "react";
2479
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
2876
+ import { useState as useState7, useEffect as useEffect7, useCallback as useCallback8, useRef as useRef8 } from "react";
2877
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
2480
2878
  var SIZE_PRESETS = [
2481
2879
  { name: "S", value: "0.875rem" },
2482
2880
  { name: "M", value: "1rem" },
@@ -2533,28 +2931,28 @@ function normalizeValue(input) {
2533
2931
  return `${num}${unit}`;
2534
2932
  }
2535
2933
  function FontSizePicker({ value, onChange, onClose }) {
2536
- const [inputValue, setInputValue] = useState6(value || "");
2537
- const inputRef = useRef7(null);
2538
- useEffect6(() => {
2934
+ const [inputValue, setInputValue] = useState7(value || "");
2935
+ const inputRef = useRef8(null);
2936
+ useEffect7(() => {
2539
2937
  inputRef.current?.focus();
2540
2938
  inputRef.current?.select();
2541
2939
  }, []);
2542
- useEffect6(() => {
2940
+ useEffect7(() => {
2543
2941
  setInputValue(value || "");
2544
2942
  }, [value]);
2545
- const handlePresetClick = useCallback7((e, presetValue) => {
2943
+ const handlePresetClick = useCallback8((e, presetValue) => {
2546
2944
  e.stopPropagation();
2547
2945
  onChange(presetValue);
2548
2946
  onClose();
2549
2947
  }, [onChange, onClose]);
2550
- const handlePresetMouseDown = useCallback7((e) => {
2948
+ const handlePresetMouseDown = useCallback8((e) => {
2551
2949
  e.preventDefault();
2552
2950
  e.stopPropagation();
2553
2951
  }, []);
2554
- const handleInputChange = useCallback7((e) => {
2952
+ const handleInputChange = useCallback8((e) => {
2555
2953
  setInputValue(e.target.value);
2556
2954
  }, []);
2557
- const handleInputKeyDown = useCallback7((e) => {
2955
+ const handleInputKeyDown = useCallback8((e) => {
2558
2956
  if (e.key === "ArrowUp" || e.key === "ArrowDown") {
2559
2957
  e.preventDefault();
2560
2958
  e.stopPropagation();
@@ -2596,7 +2994,7 @@ function FontSizePicker({ value, onChange, onClose }) {
2596
2994
  }, [inputValue, value, onChange, onClose]);
2597
2995
  const activePreset = getPresetName(value);
2598
2996
  return /* @__PURE__ */ jsxs4("div", { className: "ya-font-size-picker", children: [
2599
- /* @__PURE__ */ jsx8("div", { className: "ya-size-presets", children: SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsxs4(
2997
+ /* @__PURE__ */ jsx9("div", { className: "ya-size-presets", children: SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsxs4(
2600
2998
  "button",
2601
2999
  {
2602
3000
  type: "button",
@@ -2604,13 +3002,13 @@ function FontSizePicker({ value, onChange, onClose }) {
2604
3002
  onClick: (e) => handlePresetClick(e, preset.value),
2605
3003
  onMouseDown: handlePresetMouseDown,
2606
3004
  children: [
2607
- /* @__PURE__ */ jsx8("span", { className: "ya-size-preset-name", children: preset.name }),
2608
- /* @__PURE__ */ jsx8("span", { className: "ya-size-preset-value", children: preset.value })
3005
+ /* @__PURE__ */ jsx9("span", { className: "ya-size-preset-name", children: preset.name }),
3006
+ /* @__PURE__ */ jsx9("span", { className: "ya-size-preset-value", children: preset.value })
2609
3007
  ]
2610
3008
  },
2611
3009
  preset.name
2612
3010
  )) }),
2613
- /* @__PURE__ */ jsx8("div", { className: "ya-size-combobox", children: /* @__PURE__ */ jsx8(
3011
+ /* @__PURE__ */ jsx9("div", { className: "ya-size-combobox", children: /* @__PURE__ */ jsx9(
2614
3012
  "input",
2615
3013
  {
2616
3014
  ref: inputRef,
@@ -2630,8 +3028,8 @@ function FontSizePicker({ value, onChange, onClose }) {
2630
3028
  }
2631
3029
 
2632
3030
  // src/components/FontWeightPicker.tsx
2633
- import { useCallback as useCallback8 } from "react";
2634
- import { jsx as jsx9 } from "react/jsx-runtime";
3031
+ import { useCallback as useCallback9 } from "react";
3032
+ import { jsx as jsx10 } from "react/jsx-runtime";
2635
3033
  var WEIGHT_PRESETS = [
2636
3034
  { name: "Regular", value: "400" },
2637
3035
  { name: "Semi-bold", value: "600" },
@@ -2645,16 +3043,16 @@ function getFontWeightLabel(value) {
2645
3043
  return value;
2646
3044
  }
2647
3045
  function FontWeightPicker({ value, onChange, onClose }) {
2648
- const handleClick = useCallback8((e, weightValue) => {
3046
+ const handleClick = useCallback9((e, weightValue) => {
2649
3047
  e.stopPropagation();
2650
3048
  onChange(weightValue);
2651
3049
  onClose();
2652
3050
  }, [onChange, onClose]);
2653
- const handleMouseDown = useCallback8((e) => {
3051
+ const handleMouseDown = useCallback9((e) => {
2654
3052
  e.preventDefault();
2655
3053
  e.stopPropagation();
2656
3054
  }, []);
2657
- return /* @__PURE__ */ jsx9("div", { className: "ya-font-weight-picker", children: WEIGHT_PRESETS.map((preset) => /* @__PURE__ */ jsx9(
3055
+ return /* @__PURE__ */ jsx10("div", { className: "ya-font-weight-picker", children: WEIGHT_PRESETS.map((preset) => /* @__PURE__ */ jsx10(
2658
3056
  "button",
2659
3057
  {
2660
3058
  type: "button",
@@ -3017,7 +3415,7 @@ body.builder-selector-active .ya-text-editable:not(.ya-text-editing) *::-moz-sel
3017
3415
  styleInject('.ya-ai-editing {\n position: relative;\n}\n.ya-ai-editing::before {\n content: "";\n position: absolute;\n inset: -4px;\n border: 2px solid;\n border-radius: 6px;\n animation: ya-ai-focus-pulse 1.5s ease-in-out infinite;\n pointer-events: none;\n z-index: 10;\n}\n@keyframes ya-ai-focus-pulse {\n 0%, 100% {\n border-color: rgba(239, 68, 68, 0.6);\n box-shadow: 0 0 15px rgba(239, 68, 68, 0.2);\n }\n 50% {\n border-color: rgba(249, 115, 22, 0.8);\n box-shadow: 0 0 25px rgba(249, 115, 22, 0.3);\n }\n}\n.ya-typing-cursor {\n display: inline-block;\n width: 2px;\n height: 1.1em;\n background:\n linear-gradient(\n 180deg,\n #EF4444,\n #F97316);\n animation: ya-cursor-blink 0.5s step-end infinite;\n margin-left: 1px;\n vertical-align: text-bottom;\n border-radius: 1px;\n}\n@keyframes ya-cursor-blink {\n 50% {\n opacity: 0;\n }\n}\n.ya-ai-complete {\n animation: ya-complete-glow 0.4s ease-out forwards;\n}\n@keyframes ya-complete-glow {\n 0% {\n box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5);\n }\n 50% {\n box-shadow: 0 0 20px 5px rgba(16, 185, 129, 0.3);\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .ya-ai-editing::before {\n animation: none;\n border-color: rgba(239, 68, 68, 0.6);\n box-shadow: 0 0 15px rgba(239, 68, 68, 0.2);\n }\n .ya-typing-cursor {\n animation: none;\n opacity: 1;\n }\n .ya-ai-complete {\n animation: ya-complete-glow-reduced 0.2s ease-out forwards;\n }\n @keyframes ya-complete-glow-reduced {\n 0% {\n background-color: rgba(16, 185, 129, 0.1);\n }\n 100% {\n background-color: transparent;\n }\n }\n}\n.ya-ai-hidden {\n opacity: 0;\n visibility: hidden;\n}\n.ya-ai-fade-in {\n animation: ya-fade-in 0.3s ease-out forwards;\n}\n@keyframes ya-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-ai-pulse {\n animation: ya-scale-pulse 0.3s ease-out forwards;\n}\n@keyframes ya-scale-pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.02);\n }\n 100% {\n transform: scale(1);\n }\n}\n');
3018
3416
 
3019
3417
  // src/components/YaText.tsx
3020
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
3418
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
3021
3419
  var FontSize = Extension.create({
3022
3420
  name: "fontSize",
3023
3421
  addOptions() {
@@ -3097,13 +3495,15 @@ var FontWeight = Extension.create({
3097
3495
  }
3098
3496
  });
3099
3497
  function YaText({ fieldId, className, as: Component = "span", children }) {
3100
- const { getValue, setValue, mode, saveToWorker, activeFieldId, setActiveField } = useContentStore();
3101
- const storeContent = getValue(fieldId);
3498
+ const contentHandle = useContent(fieldId);
3499
+ const { mode } = contentHandle;
3500
+ const { activeFieldId, setActiveField } = useContentStore();
3501
+ const storeContent = contentHandle.get();
3102
3502
  const content = storeContent || (typeof children === "string" ? children : "");
3103
- const [isEditing, setIsEditing] = useState7(false);
3104
- const [showBubbleMenu, setShowBubbleMenu] = useState7(false);
3105
- const [fontSizeOpen, setFontSizeOpen] = useState7(false);
3106
- const [fontWeightOpen, setFontWeightOpen] = useState7(false);
3503
+ const [isEditing, setIsEditing] = useState8(false);
3504
+ const [showBubbleMenu, setShowBubbleMenu] = useState8(false);
3505
+ const [fontSizeOpen, setFontSizeOpen] = useState8(false);
3506
+ const [fontWeightOpen, setFontWeightOpen] = useState8(false);
3107
3507
  const {
3108
3508
  displayContent,
3109
3509
  isAnimating,
@@ -3111,16 +3511,16 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3111
3511
  } = useAnimatedText(fieldId, content, {
3112
3512
  enabled: mode === "inline-edit" && !isEditing
3113
3513
  });
3114
- const [originalContent, setOriginalContent] = useState7(content);
3115
- const containerRef = useRef8(null);
3116
- const originalContentRef = useRef8(content);
3117
- const originalHadLineBreaksRef = useRef8(false);
3118
- const [actionButtonsPos, setActionButtonsPos] = useState7(null);
3119
- const handleSaveRef = useRef8(() => {
3514
+ const [originalContent, setOriginalContent] = useState8(content);
3515
+ const containerRef = useRef9(null);
3516
+ const originalContentRef = useRef9(content);
3517
+ const originalHadLineBreaksRef = useRef9(false);
3518
+ const [actionButtonsPos, setActionButtonsPos] = useState8(null);
3519
+ const handleSaveRef = useRef9(() => {
3120
3520
  });
3121
- const handleCancelRef = useRef8(() => {
3521
+ const handleCancelRef = useRef9(() => {
3122
3522
  });
3123
- const handleCloseRef = useRef8(() => {
3523
+ const handleCloseRef = useRef9(() => {
3124
3524
  });
3125
3525
  const editor = useEditor({
3126
3526
  extensions: [
@@ -3176,19 +3576,19 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3176
3576
  },
3177
3577
  parseOptions: { preserveWhitespace: "full" }
3178
3578
  });
3179
- useEffect7(() => {
3579
+ useEffect8(() => {
3180
3580
  if (editor && !isEditing) {
3181
3581
  if (editor.getHTML() !== content) {
3182
3582
  editor.commands.setContent(content, { parseOptions: { preserveWhitespace: "full" } });
3183
3583
  }
3184
3584
  }
3185
3585
  }, [content, editor, isEditing]);
3186
- useEffect7(() => {
3586
+ useEffect8(() => {
3187
3587
  if (isEditing && activeFieldId !== null && activeFieldId !== fieldId) {
3188
3588
  setIsEditing(false);
3189
3589
  }
3190
3590
  }, [activeFieldId, fieldId, isEditing]);
3191
- useEffect7(() => {
3591
+ useEffect8(() => {
3192
3592
  if (!isEditing || !containerRef.current || !editor) {
3193
3593
  setActionButtonsPos(null);
3194
3594
  return;
@@ -3213,31 +3613,31 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3213
3613
  window.removeEventListener("resize", updatePosition);
3214
3614
  };
3215
3615
  }, [isEditing, editor]);
3216
- const handleSave = useCallback9(() => {
3616
+ const handleSave = useCallback10(() => {
3217
3617
  if (!editor) return;
3218
3618
  let html = editor.getHTML();
3219
3619
  const separator = originalHadLineBreaksRef.current ? "<br><br>" : " ";
3220
3620
  html = html.replace(/<\/p><p>/g, separator).replace(/^<p>/, "").replace(/<\/p>$/, "");
3221
3621
  if (html !== originalContentRef.current) {
3222
- setValue(fieldId, html, "user");
3223
- saveToWorker?.(fieldId, html);
3622
+ contentHandle.set(html, "user");
3623
+ contentHandle.save();
3224
3624
  originalContentRef.current = html;
3225
3625
  }
3226
3626
  setShowBubbleMenu(false);
3227
3627
  setIsEditing(false);
3228
- }, [editor, fieldId, setValue, saveToWorker]);
3229
- const handleCancel = useCallback9(() => {
3628
+ }, [editor, contentHandle]);
3629
+ const handleCancel = useCallback10(() => {
3230
3630
  if (editor) {
3231
3631
  editor.commands.setContent(originalContent, { parseOptions: { preserveWhitespace: "full" } });
3232
3632
  }
3233
3633
  setShowBubbleMenu(false);
3234
3634
  setIsEditing(false);
3235
3635
  }, [editor, originalContent]);
3236
- useEffect7(() => {
3636
+ useEffect8(() => {
3237
3637
  handleSaveRef.current = handleSave;
3238
3638
  handleCancelRef.current = handleCancel;
3239
3639
  }, [handleSave, handleCancel]);
3240
- useEffect7(() => {
3640
+ useEffect8(() => {
3241
3641
  if (mode !== "inline-edit") return;
3242
3642
  const handleEditRequest = (event) => {
3243
3643
  const customEvent = event;
@@ -3260,7 +3660,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3260
3660
  window.addEventListener("yatext:edit-mode", handleEditRequest);
3261
3661
  return () => window.removeEventListener("yatext:edit-mode", handleEditRequest);
3262
3662
  }, [mode, fieldId, content, editor, setActiveField]);
3263
- const handleClose = useCallback9(() => {
3663
+ const handleClose = useCallback10(() => {
3264
3664
  if (!editor) {
3265
3665
  setShowBubbleMenu(false);
3266
3666
  setIsEditing(false);
@@ -3270,16 +3670,16 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3270
3670
  const separator = originalHadLineBreaksRef.current ? "<br><br>" : " ";
3271
3671
  currentHtml = currentHtml.replace(/<\/p><p>/g, separator).replace(/^<p>/, "").replace(/<\/p>$/, "");
3272
3672
  if (currentHtml !== originalContentRef.current) {
3273
- setValue(fieldId, currentHtml, "user");
3274
- saveToWorker?.(fieldId, currentHtml);
3673
+ contentHandle.set(currentHtml, "user");
3674
+ contentHandle.save();
3275
3675
  }
3276
3676
  setShowBubbleMenu(false);
3277
3677
  setIsEditing(false);
3278
- }, [editor, fieldId, setValue, saveToWorker]);
3279
- useEffect7(() => {
3678
+ }, [editor, contentHandle]);
3679
+ useEffect8(() => {
3280
3680
  handleCloseRef.current = handleClose;
3281
3681
  }, [handleClose]);
3282
- const handleClick = useCallback9((e) => {
3682
+ const handleClick = useCallback10((e) => {
3283
3683
  if (isEditing) {
3284
3684
  e.preventDefault();
3285
3685
  e.stopPropagation();
@@ -3310,7 +3710,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3310
3710
  }, 20);
3311
3711
  }
3312
3712
  }, [mode, isEditing, content, editor, fieldId, setActiveField, handleClose]);
3313
- const handleKeyDown = useCallback9(
3713
+ const handleKeyDown = useCallback10(
3314
3714
  (event) => {
3315
3715
  if (!isEditing) return;
3316
3716
  if (event.key === "Enter" && !event.shiftKey) {
@@ -3331,7 +3731,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3331
3731
  },
3332
3732
  [isEditing, handleSave, handleCancel]
3333
3733
  );
3334
- const handleLink = useCallback9(() => {
3734
+ const handleLink = useCallback10(() => {
3335
3735
  if (!editor) return;
3336
3736
  const previousUrl = editor.getAttributes("link").href;
3337
3737
  const url = window.prompt("Enter URL:", previousUrl || "https://");
@@ -3342,7 +3742,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3342
3742
  editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
3343
3743
  }
3344
3744
  }, [editor]);
3345
- const handleFontSizeChange = useCallback9(
3745
+ const handleFontSizeChange = useCallback10(
3346
3746
  (size) => {
3347
3747
  if (!editor) return;
3348
3748
  if (size === "") {
@@ -3353,7 +3753,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3353
3753
  },
3354
3754
  [editor]
3355
3755
  );
3356
- const handleFontWeightChange = useCallback9(
3756
+ const handleFontWeightChange = useCallback10(
3357
3757
  (weight) => {
3358
3758
  if (!editor) return;
3359
3759
  if (weight === "") {
@@ -3398,14 +3798,14 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3398
3798
  return "";
3399
3799
  };
3400
3800
  if (mode === "read-only") {
3401
- return /* @__PURE__ */ jsx10(
3801
+ return /* @__PURE__ */ jsx11(
3402
3802
  Component,
3403
3803
  {
3404
3804
  ref: containerRef,
3405
3805
  className,
3406
3806
  "data-ya-restricted": "true",
3407
3807
  "data-field-id": fieldId,
3408
- children: /* @__PURE__ */ jsx10(SafeHtml, { content, mode })
3808
+ children: /* @__PURE__ */ jsx11(SafeHtml, { content, mode })
3409
3809
  }
3410
3810
  );
3411
3811
  }
@@ -3418,7 +3818,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3418
3818
  wrapperClassName
3419
3819
  ].filter(Boolean).join(" ");
3420
3820
  const EditSafeComponent = isEditing && Component === "p" ? "div" : Component;
3421
- return /* @__PURE__ */ jsx10(
3821
+ return /* @__PURE__ */ jsx11(
3422
3822
  EditSafeComponent,
3423
3823
  {
3424
3824
  ref: containerRef,
@@ -3436,7 +3836,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3436
3836
  open: showBubbleMenu,
3437
3837
  className: "ya-bubble-menu",
3438
3838
  children: [
3439
- /* @__PURE__ */ jsx10(
3839
+ /* @__PURE__ */ jsx11(
3440
3840
  "button",
3441
3841
  {
3442
3842
  type: "button",
@@ -3444,10 +3844,10 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3444
3844
  onMouseDown: (e) => e.preventDefault(),
3445
3845
  className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
3446
3846
  title: "Bold",
3447
- children: /* @__PURE__ */ jsx10(BoldIcon, { size: 16 })
3847
+ children: /* @__PURE__ */ jsx11(BoldIcon, { size: 16 })
3448
3848
  }
3449
3849
  ),
3450
- /* @__PURE__ */ jsx10(
3850
+ /* @__PURE__ */ jsx11(
3451
3851
  "button",
3452
3852
  {
3453
3853
  type: "button",
@@ -3455,10 +3855,10 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3455
3855
  onMouseDown: (e) => e.preventDefault(),
3456
3856
  className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
3457
3857
  title: "Italic",
3458
- children: /* @__PURE__ */ jsx10(ItalicIcon, { size: 16 })
3858
+ children: /* @__PURE__ */ jsx11(ItalicIcon, { size: 16 })
3459
3859
  }
3460
3860
  ),
3461
- /* @__PURE__ */ jsx10(
3861
+ /* @__PURE__ */ jsx11(
3462
3862
  "button",
3463
3863
  {
3464
3864
  type: "button",
@@ -3466,17 +3866,17 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3466
3866
  onMouseDown: (e) => e.preventDefault(),
3467
3867
  className: `ya-bubble-btn ${editor.isActive("link") ? "is-active" : ""}`,
3468
3868
  title: "Link",
3469
- children: /* @__PURE__ */ jsx10(LinkIcon2, { size: 16 })
3869
+ children: /* @__PURE__ */ jsx11(LinkIcon2, { size: 16 })
3470
3870
  }
3471
3871
  ),
3472
- /* @__PURE__ */ jsx10("span", { className: "ya-bubble-divider" }),
3473
- /* @__PURE__ */ jsx10(
3872
+ /* @__PURE__ */ jsx11("span", { className: "ya-bubble-divider" }),
3873
+ /* @__PURE__ */ jsx11(
3474
3874
  BubbleDropdown,
3475
3875
  {
3476
3876
  label: getFontSizeLabel(getCurrentFontSize()),
3477
3877
  open: fontSizeOpen,
3478
3878
  onOpenChange: setFontSizeOpen,
3479
- children: /* @__PURE__ */ jsx10(
3879
+ children: /* @__PURE__ */ jsx11(
3480
3880
  FontSizePicker,
3481
3881
  {
3482
3882
  value: getCurrentFontSize(),
@@ -3486,13 +3886,13 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3486
3886
  )
3487
3887
  }
3488
3888
  ),
3489
- /* @__PURE__ */ jsx10(
3889
+ /* @__PURE__ */ jsx11(
3490
3890
  BubbleDropdown,
3491
3891
  {
3492
3892
  label: getFontWeightLabel(getCurrentFontWeight()),
3493
3893
  open: fontWeightOpen,
3494
3894
  onOpenChange: setFontWeightOpen,
3495
- children: /* @__PURE__ */ jsx10(
3895
+ children: /* @__PURE__ */ jsx11(
3496
3896
  FontWeightPicker,
3497
3897
  {
3498
3898
  value: getCurrentFontWeight(),
@@ -3506,7 +3906,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3506
3906
  }
3507
3907
  ),
3508
3908
  isEditing ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3509
- /* @__PURE__ */ jsx10(EditorContent, { editor }),
3909
+ /* @__PURE__ */ jsx11(EditorContent, { editor }),
3510
3910
  actionButtonsPos && createPortal4(
3511
3911
  /* @__PURE__ */ jsxs5(
3512
3912
  "div",
@@ -3520,7 +3920,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3520
3920
  // Right edge aligns with text end
3521
3921
  },
3522
3922
  children: [
3523
- /* @__PURE__ */ jsx10(
3923
+ /* @__PURE__ */ jsx11(
3524
3924
  "button",
3525
3925
  {
3526
3926
  type: "button",
@@ -3529,7 +3929,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3529
3929
  children: "Cancel"
3530
3930
  }
3531
3931
  ),
3532
- /* @__PURE__ */ jsx10(
3932
+ /* @__PURE__ */ jsx11(
3533
3933
  "button",
3534
3934
  {
3535
3935
  type: "button",
@@ -3544,19 +3944,19 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
3544
3944
  document.body
3545
3945
  )
3546
3946
  ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3547
- /* @__PURE__ */ jsx10(SafeHtml, { content: displayContent, mode }),
3548
- isAnimating && /* @__PURE__ */ jsx10("span", { className: "ya-typing-cursor" })
3947
+ /* @__PURE__ */ jsx11(SafeHtml, { content: displayContent, mode }),
3948
+ isAnimating && /* @__PURE__ */ jsx11("span", { className: "ya-typing-cursor" })
3549
3949
  ] })
3550
3950
  ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
3551
- /* @__PURE__ */ jsx10(SafeHtml, { content: displayContent, mode }),
3552
- isAnimating && /* @__PURE__ */ jsx10("span", { className: "ya-typing-cursor" })
3951
+ /* @__PURE__ */ jsx11(SafeHtml, { content: displayContent, mode }),
3952
+ isAnimating && /* @__PURE__ */ jsx11("span", { className: "ya-typing-cursor" })
3553
3953
  ] })
3554
3954
  }
3555
3955
  );
3556
3956
  }
3557
3957
 
3558
3958
  // src/components/YaImage.tsx
3559
- import { useCallback as useCallback12, useEffect as useEffect10, useRef as useRef11, useState as useState10 } from "react";
3959
+ import { useCallback as useCallback13, useEffect as useEffect11, useRef as useRef12, useState as useState11 } from "react";
3560
3960
 
3561
3961
  // src/lib/asset-resolver.ts
3562
3962
  var assetResolver = (path) => path;
@@ -3572,25 +3972,25 @@ function resolveAssetUrl(path) {
3572
3972
  }
3573
3973
 
3574
3974
  // src/components/YaTooltip.tsx
3575
- import { useEffect as useEffect8, useRef as useRef9, useState as useState8, useCallback as useCallback10 } from "react";
3975
+ import { useEffect as useEffect9, useRef as useRef10, useState as useState9, useCallback as useCallback11 } from "react";
3576
3976
  import { createPortal as createPortal5 } from "react-dom";
3577
3977
 
3578
3978
  // src/components/ya-tooltip.css
3579
3979
  styleInject('.ya-tooltip {\n position: fixed;\n z-index: 9999;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: #1a1a1a;\n color: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n animation: ya-tooltip-fade-in 0.15s ease;\n pointer-events: none;\n}\n@keyframes ya-tooltip-fade-in {\n from {\n transform: scale(0.95);\n }\n to {\n transform: scale(1);\n }\n}\n.ya-tooltip svg {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.ya-tooltip-bottom {\n transform: translateX(-50%);\n}\n.ya-tooltip-bottom::before {\n content: "";\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-bottom-color: #1a1a1a;\n}\n.ya-tooltip-top {\n transform: translateX(-50%);\n}\n.ya-tooltip-top::before {\n content: "";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-top-color: #1a1a1a;\n}\n.ya-tooltip-right {\n transform: translateY(-50%);\n}\n.ya-tooltip-right::before {\n content: "";\n position: absolute;\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-right-color: #1a1a1a;\n}\n.ya-tooltip-left {\n transform: translateY(-50%);\n}\n.ya-tooltip-left::before {\n content: "";\n position: absolute;\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-left-color: #1a1a1a;\n}\n');
3580
3980
 
3581
3981
  // src/components/YaTooltip.tsx
3582
- import { jsx as jsx11 } from "react/jsx-runtime";
3982
+ import { jsx as jsx12 } from "react/jsx-runtime";
3583
3983
  function YaTooltip({
3584
3984
  anchorRef,
3585
3985
  children,
3586
3986
  show,
3587
3987
  preferredPosition = "bottom"
3588
3988
  }) {
3589
- const [position, setPosition] = useState8(preferredPosition);
3590
- const [coords, setCoords] = useState8({ top: 0, left: 0 });
3591
- const [isPositioned, setIsPositioned] = useState8(false);
3592
- const tooltipRef = useRef9(null);
3593
- const calculatePosition = useCallback10(() => {
3989
+ const [position, setPosition] = useState9(preferredPosition);
3990
+ const [coords, setCoords] = useState9({ top: 0, left: 0 });
3991
+ const [isPositioned, setIsPositioned] = useState9(false);
3992
+ const tooltipRef = useRef10(null);
3993
+ const calculatePosition = useCallback11(() => {
3594
3994
  if (!anchorRef.current) return;
3595
3995
  const anchor = anchorRef.current.getBoundingClientRect();
3596
3996
  const tooltip = tooltipRef.current?.getBoundingClientRect();
@@ -3665,7 +4065,7 @@ function YaTooltip({
3665
4065
  setCoords({ top, left });
3666
4066
  setIsPositioned(true);
3667
4067
  }, [anchorRef, preferredPosition]);
3668
- useEffect8(() => {
4068
+ useEffect9(() => {
3669
4069
  if (!show) {
3670
4070
  setIsPositioned(false);
3671
4071
  return;
@@ -3678,14 +4078,14 @@ function YaTooltip({
3678
4078
  window.removeEventListener("resize", calculatePosition);
3679
4079
  };
3680
4080
  }, [show, calculatePosition]);
3681
- useEffect8(() => {
4081
+ useEffect9(() => {
3682
4082
  if (show && tooltipRef.current) {
3683
4083
  calculatePosition();
3684
4084
  }
3685
4085
  }, [show, children, calculatePosition]);
3686
4086
  if (!show) return null;
3687
4087
  return createPortal5(
3688
- /* @__PURE__ */ jsx11(
4088
+ /* @__PURE__ */ jsx12(
3689
4089
  "div",
3690
4090
  {
3691
4091
  ref: tooltipRef,
@@ -3704,7 +4104,7 @@ function YaTooltip({
3704
4104
  }
3705
4105
 
3706
4106
  // src/hooks/useImageShaderTransition.ts
3707
- import { useCallback as useCallback11, useEffect as useEffect9, useRef as useRef10, useState as useState9 } from "react";
4107
+ import { useCallback as useCallback12, useEffect as useEffect10, useRef as useRef11, useState as useState10 } from "react";
3708
4108
 
3709
4109
  // src/lib/image-shader-transition.ts
3710
4110
  var VERTEX_SHADER = `
@@ -3964,14 +4364,14 @@ function preloadImage(src) {
3964
4364
  var TRANSITION_DURATION = 500;
3965
4365
  function useImageShaderTransition(options = {}) {
3966
4366
  const { duration = TRANSITION_DURATION, onComplete } = options;
3967
- const canvasRef = useRef10(null);
3968
- const rendererRef = useRef10(null);
3969
- const rafRef = useRef10(null);
3970
- const startTimeRef = useRef10(0);
3971
- const newSrcRef = useRef10("");
3972
- const [isTransitioning, setIsTransitioning] = useState9(false);
3973
- const [webglAvailable] = useState9(() => isWebGLAvailable());
3974
- useEffect9(() => {
4367
+ const canvasRef = useRef11(null);
4368
+ const rendererRef = useRef11(null);
4369
+ const rafRef = useRef11(null);
4370
+ const startTimeRef = useRef11(0);
4371
+ const newSrcRef = useRef11("");
4372
+ const [isTransitioning, setIsTransitioning] = useState10(false);
4373
+ const [webglAvailable] = useState10(() => isWebGLAvailable());
4374
+ useEffect10(() => {
3975
4375
  return () => {
3976
4376
  if (rafRef.current) {
3977
4377
  cancelAnimationFrame(rafRef.current);
@@ -3979,7 +4379,7 @@ function useImageShaderTransition(options = {}) {
3979
4379
  rendererRef.current?.destroy();
3980
4380
  };
3981
4381
  }, []);
3982
- const animate = useCallback11(() => {
4382
+ const animate = useCallback12(() => {
3983
4383
  const renderer = rendererRef.current;
3984
4384
  if (!renderer) return;
3985
4385
  const elapsed = performance.now() - startTimeRef.current;
@@ -3994,7 +4394,7 @@ function useImageShaderTransition(options = {}) {
3994
4394
  });
3995
4395
  }
3996
4396
  }, [duration, onComplete]);
3997
- const startTransition = useCallback11(
4397
+ const startTransition = useCallback12(
3998
4398
  (oldSrc, newSrc) => {
3999
4399
  if (!webglAvailable) {
4000
4400
  return;
@@ -4026,7 +4426,7 @@ function useImageShaderTransition(options = {}) {
4026
4426
  },
4027
4427
  [webglAvailable, animate]
4028
4428
  );
4029
- const cancelTransition = useCallback11(() => {
4429
+ const cancelTransition = useCallback12(() => {
4030
4430
  if (rafRef.current) {
4031
4431
  cancelAnimationFrame(rafRef.current);
4032
4432
  rafRef.current = null;
@@ -4046,7 +4446,7 @@ function useImageShaderTransition(options = {}) {
4046
4446
  styleInject('.ya-image-container {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 45px;\n min-height: 45px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-image-container img {\n display: block;\n}\n.ya-image-editable {\n cursor: pointer;\n}\n.ya-image-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-image-editable:hover .ya-image-overlay {\n opacity: 1;\n}\n.ya-image-selected .ya-image-overlay {\n opacity: 0;\n}\n.ya-image-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-image-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-image-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n@keyframes ya-image-success {\n 0% {\n outline-color: var(--color-primary, #D4A574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #D4A574);\n outline-width: 2px;\n }\n}\n.ya-image-success {\n animation: ya-image-success 0.4s ease;\n}\n.ya-image-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-image-shimmer 1.5s infinite;\n}\n@keyframes ya-image-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-image-container:focus {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-image-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-small .ya-image-overlay {\n display: none;\n}\n.ya-image-drop-target {\n outline: 2px dashed var(--ya-drop-color, #3b82f6) !important;\n outline-offset: 4px;\n}\n.ya-image-drop-target .ya-image-overlay {\n display: none !important;\n}\n.ya-image-drop-hover {\n outline: 3px solid var(--ya-drop-color, #3b82f6) !important;\n outline-offset: 4px;\n background-color: rgba(59, 130, 246, 0.1);\n}\n.ya-image-drop-hover::before {\n content: "";\n position: absolute;\n inset: -4px;\n border: 2px solid var(--ya-drop-color, #3b82f6);\n border-radius: inherit;\n animation: ya-drop-pulse 1s ease-in-out infinite;\n pointer-events: none;\n}\n@keyframes ya-drop-pulse {\n 0%, 100% {\n opacity: 0.4;\n transform: scale(1);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.02);\n }\n}\n');
4047
4447
 
4048
4448
  // src/components/YaImage.tsx
4049
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
4449
+ import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
4050
4450
  function parseImageValue(value) {
4051
4451
  if (!value) {
4052
4452
  return { src: "" };
@@ -4090,17 +4490,18 @@ function YaImage({
4090
4490
  fallbackSrc,
4091
4491
  fallbackAlt
4092
4492
  }) {
4093
- const { getValue, setValue, mode, getChangeSource, clearChangeSource } = useContentStore();
4094
- const containerRef = useRef11(null);
4095
- const imgRef = useRef11(null);
4096
- const [isSelected, setIsSelected] = useState10(false);
4097
- const [isHovered, setIsHovered] = useState10(false);
4098
- const [isSmallImage, setIsSmallImage] = useState10(false);
4099
- const [isDropMode, setIsDropMode] = useState10(false);
4100
- const [isDropHover, setIsDropHover] = useState10(false);
4101
- const [previewOverride, setPreviewOverride] = useState10(null);
4102
- const prevSrcRef = useRef11(null);
4103
- const rawValue = getValue(fieldId);
4493
+ const content = useContent(fieldId);
4494
+ const { mode } = content;
4495
+ const containerRef = useRef12(null);
4496
+ const imgRef = useRef12(null);
4497
+ const [isSelected, setIsSelected] = useState11(false);
4498
+ const [isHovered, setIsHovered] = useState11(false);
4499
+ const [isSmallImage, setIsSmallImage] = useState11(false);
4500
+ const [isDropMode, setIsDropMode] = useState11(false);
4501
+ const [isDropHover, setIsDropHover] = useState11(false);
4502
+ const [previewOverride, setPreviewOverride] = useState11(null);
4503
+ const prevSrcRef = useRef12(null);
4504
+ const rawValue = content.get();
4104
4505
  const imageData = parseImageValue(rawValue);
4105
4506
  const displayData = previewOverride || imageData;
4106
4507
  const src = displayData.src || fallbackSrc || PLACEHOLDER_SVG;
@@ -4116,36 +4517,34 @@ function YaImage({
4116
4517
  } = useImageShaderTransition({
4117
4518
  duration: 500,
4118
4519
  onComplete: () => {
4119
- clearChangeSource(fieldId);
4520
+ content.clearChangeSource();
4120
4521
  }
4121
4522
  });
4122
- useEffect10(() => {
4123
- const changeSource = getChangeSource(fieldId);
4523
+ useEffect11(() => {
4524
+ const changeSource = content.changeSource;
4124
4525
  const resolvedSrc = resolveAssetUrl(src);
4125
4526
  const prevResolvedSrc = prevSrcRef.current;
4126
4527
  if (changeSource === "ai") {
4127
4528
  if (prevResolvedSrc !== null && prevResolvedSrc !== resolvedSrc && webglAvailable) {
4128
4529
  startTransition(prevResolvedSrc, resolvedSrc);
4129
4530
  } else {
4130
- clearChangeSource(fieldId);
4531
+ content.clearChangeSource();
4131
4532
  }
4132
4533
  }
4133
4534
  prevSrcRef.current = resolvedSrc;
4134
4535
  }, [
4135
4536
  rawValue,
4136
4537
  src,
4137
- fieldId,
4138
- getChangeSource,
4139
- clearChangeSource,
4538
+ content,
4140
4539
  startTransition,
4141
4540
  webglAvailable
4142
4541
  ]);
4143
- useEffect10(() => {
4542
+ useEffect11(() => {
4144
4543
  return () => {
4145
4544
  cancelTransition();
4146
4545
  };
4147
4546
  }, [cancelTransition]);
4148
- const handleClick = useCallback12(() => {
4547
+ const handleClick = useCallback13(() => {
4149
4548
  if (mode !== "inline-edit") return;
4150
4549
  if (document.body.classList.contains("builder-selector-active")) return;
4151
4550
  setIsSelected(true);
@@ -4173,12 +4572,14 @@ function YaImage({
4173
4572
  "*"
4174
4573
  );
4175
4574
  }, [mode, fieldId, imageData, src, altText, objectFit, objectPosition]);
4176
- useEffect10(() => {
4575
+ useEffect11(() => {
4177
4576
  if (mode !== "inline-edit") return;
4178
4577
  const handleMessage2 = (event) => {
4179
4578
  if (event.data?.type === "YA_IMAGE_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
4180
4579
  const value = event.data.value;
4181
- setValue(fieldId, serializeImageValue(value), "user");
4580
+ const serializedValue = serializeImageValue(value);
4581
+ content.set(serializedValue, "user");
4582
+ content.save();
4182
4583
  setPreviewOverride(null);
4183
4584
  setIsSelected(false);
4184
4585
  }
@@ -4193,8 +4594,8 @@ function YaImage({
4193
4594
  };
4194
4595
  window.addEventListener("message", handleMessage2);
4195
4596
  return () => window.removeEventListener("message", handleMessage2);
4196
- }, [mode, fieldId, setValue]);
4197
- useEffect10(() => {
4597
+ }, [mode, fieldId, content]);
4598
+ useEffect11(() => {
4198
4599
  if (mode !== "inline-edit") return;
4199
4600
  const handleDropModeMessage = (event) => {
4200
4601
  if (event.data?.type === "DROP_MODE_START") {
@@ -4208,7 +4609,7 @@ function YaImage({
4208
4609
  window.addEventListener("message", handleDropModeMessage);
4209
4610
  return () => window.removeEventListener("message", handleDropModeMessage);
4210
4611
  }, [mode]);
4211
- const handleDragEnter = useCallback12(
4612
+ const handleDragEnter = useCallback13(
4212
4613
  (e) => {
4213
4614
  if (!isDropMode) return;
4214
4615
  e.preventDefault();
@@ -4232,7 +4633,7 @@ function YaImage({
4232
4633
  },
4233
4634
  [isDropMode, fieldId]
4234
4635
  );
4235
- const handleDragOver = useCallback12(
4636
+ const handleDragOver = useCallback13(
4236
4637
  (e) => {
4237
4638
  if (!isDropMode) return;
4238
4639
  e.preventDefault();
@@ -4240,7 +4641,7 @@ function YaImage({
4240
4641
  },
4241
4642
  [isDropMode]
4242
4643
  );
4243
- const handleDragLeave = useCallback12(
4644
+ const handleDragLeave = useCallback13(
4244
4645
  (e) => {
4245
4646
  if (!isDropMode) return;
4246
4647
  e.preventDefault();
@@ -4254,7 +4655,7 @@ function YaImage({
4254
4655
  },
4255
4656
  [isDropMode]
4256
4657
  );
4257
- const handleDrop = useCallback12(
4658
+ const handleDrop = useCallback13(
4258
4659
  (e) => {
4259
4660
  if (!isDropMode) return;
4260
4661
  e.preventDefault();
@@ -4272,7 +4673,7 @@ function YaImage({
4272
4673
  },
4273
4674
  [isDropMode, fieldId]
4274
4675
  );
4275
- useEffect10(() => {
4676
+ useEffect11(() => {
4276
4677
  if (mode !== "inline-edit") return;
4277
4678
  const checkSize = () => {
4278
4679
  if (imgRef.current) {
@@ -4294,7 +4695,7 @@ function YaImage({
4294
4695
  window.removeEventListener("resize", checkSize);
4295
4696
  };
4296
4697
  }, [mode]);
4297
- useEffect10(() => {
4698
+ useEffect11(() => {
4298
4699
  if (!isSelected || mode !== "inline-edit") return;
4299
4700
  let lastRectKey = "";
4300
4701
  let lastTime = 0;
@@ -4336,7 +4737,7 @@ function YaImage({
4336
4737
  "data-ya-restricted": "true",
4337
4738
  "data-field-id": fieldId,
4338
4739
  children: [
4339
- /* @__PURE__ */ jsx12(
4740
+ /* @__PURE__ */ jsx13(
4340
4741
  "img",
4341
4742
  {
4342
4743
  src: resolveAssetUrl(src),
@@ -4352,7 +4753,7 @@ function YaImage({
4352
4753
  loading
4353
4754
  }
4354
4755
  ),
4355
- /* @__PURE__ */ jsx12(
4756
+ /* @__PURE__ */ jsx13(
4356
4757
  "canvas",
4357
4758
  {
4358
4759
  ref: canvasRef,
@@ -4386,9 +4787,9 @@ function YaImage({
4386
4787
  strokeLinecap: "round",
4387
4788
  strokeLinejoin: "round",
4388
4789
  children: [
4389
- /* @__PURE__ */ jsx12("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
4390
- /* @__PURE__ */ jsx12("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
4391
- /* @__PURE__ */ jsx12("polyline", { points: "21 15 16 10 5 21" })
4790
+ /* @__PURE__ */ jsx13("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
4791
+ /* @__PURE__ */ jsx13("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
4792
+ /* @__PURE__ */ jsx13("polyline", { points: "21 15 16 10 5 21" })
4392
4793
  ]
4393
4794
  }
4394
4795
  );
@@ -4424,7 +4825,7 @@ function YaImage({
4424
4825
  }
4425
4826
  },
4426
4827
  children: [
4427
- /* @__PURE__ */ jsx12(
4828
+ /* @__PURE__ */ jsx13(
4428
4829
  "img",
4429
4830
  {
4430
4831
  ref: imgRef,
@@ -4441,7 +4842,7 @@ function YaImage({
4441
4842
  loading
4442
4843
  }
4443
4844
  ),
4444
- /* @__PURE__ */ jsx12(
4845
+ /* @__PURE__ */ jsx13(
4445
4846
  "canvas",
4446
4847
  {
4447
4848
  ref: canvasRef,
@@ -4461,12 +4862,12 @@ function YaImage({
4461
4862
  ),
4462
4863
  isSmallImage ? /* @__PURE__ */ jsxs6(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
4463
4864
  editIcon,
4464
- /* @__PURE__ */ jsx12("span", { children: "Click to edit" })
4865
+ /* @__PURE__ */ jsx13("span", { children: "Click to edit" })
4465
4866
  ] }) : (
4466
4867
  /* For large images: show overlay inside the image */
4467
4868
  /* @__PURE__ */ jsxs6("div", { className: "ya-image-overlay", children: [
4468
- /* @__PURE__ */ jsx12("div", { className: "ya-image-edit-icon", children: editIcon }),
4469
- /* @__PURE__ */ jsx12("span", { className: "ya-image-edit-label", children: "Click to edit" })
4869
+ /* @__PURE__ */ jsx13("div", { className: "ya-image-edit-icon", children: editIcon }),
4870
+ /* @__PURE__ */ jsx13("span", { className: "ya-image-edit-label", children: "Click to edit" })
4470
4871
  ] })
4471
4872
  )
4472
4873
  ]
@@ -4475,13 +4876,13 @@ function YaImage({
4475
4876
  }
4476
4877
 
4477
4878
  // src/components/YaVideo.tsx
4478
- import { useCallback as useCallback13, useEffect as useEffect11, useRef as useRef12, useState as useState11 } from "react";
4879
+ import { useCallback as useCallback14, useEffect as useEffect12, useRef as useRef13, useState as useState12 } from "react";
4479
4880
 
4480
4881
  // src/components/ya-video.css
4481
4882
  styleInject('.ya-video-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n.ya-video-wrapper video,\n.ya-video-wrapper iframe {\n display: block;\n width: 100%;\n height: 100%;\n}\n.ya-video-container {\n position: relative;\n display: block;\n width: 100%;\n min-width: 80px;\n min-height: 45px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-video-container video,\n.ya-video-container iframe {\n display: block;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n.ya-video-editable {\n cursor: pointer;\n}\n.ya-video-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-video-editable:hover .ya-video-overlay {\n opacity: 1;\n}\n.ya-video-selected .ya-video-overlay {\n opacity: 0;\n}\n.ya-video-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-video-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-video-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n.ya-video-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n min-height: 120px;\n background: #f3f4f6;\n border: 2px dashed #d1d5db;\n border-radius: 8px;\n color: #6b7280;\n font-size: 14px;\n}\n.ya-video-placeholder img {\n width: 64px;\n height: auto;\n opacity: 0.5;\n}\n@keyframes ya-video-success {\n 0% {\n outline-color: var(--color-primary, #D4A574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #D4A574);\n outline-width: 2px;\n }\n}\n.ya-video-success {\n animation: ya-video-success 0.4s ease;\n}\n.ya-video-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-video-shimmer 1.5s infinite;\n}\n@keyframes ya-video-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-video-container:focus {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-video-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-small .ya-video-overlay {\n display: none;\n}\n.ya-video-background {\n position: absolute;\n inset: 0;\n z-index: -1;\n}\n.ya-video-background video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n');
4482
4883
 
4483
4884
  // src/components/YaVideo.tsx
4484
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4885
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
4485
4886
  function parseVideoValue(value) {
4486
4887
  if (!value) {
4487
4888
  return { type: "upload", src: "" };
@@ -4553,14 +4954,15 @@ function YaVideo({
4553
4954
  fallbackSrc,
4554
4955
  fallbackPoster
4555
4956
  }) {
4556
- const { getValue, mode } = useContentStore();
4557
- const containerRef = useRef12(null);
4558
- const videoRef = useRef12(null);
4559
- const [isSelected, setIsSelected] = useState11(false);
4560
- const [isHovered, setIsHovered] = useState11(false);
4561
- const [isSmallVideo, setIsSmallVideo] = useState11(false);
4562
- const [isInView, setIsInView] = useState11(loading === "eager");
4563
- const rawValue = getValue(fieldId);
4957
+ const content = useContent(fieldId);
4958
+ const { mode } = content;
4959
+ const containerRef = useRef13(null);
4960
+ const videoRef = useRef13(null);
4961
+ const [isSelected, setIsSelected] = useState12(false);
4962
+ const [isHovered, setIsHovered] = useState12(false);
4963
+ const [isSmallVideo, setIsSmallVideo] = useState12(false);
4964
+ const [isInView, setIsInView] = useState12(loading === "eager");
4965
+ const rawValue = content.get();
4564
4966
  const parsedValue = parseVideoValue(rawValue);
4565
4967
  const videoData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
4566
4968
  const src = videoData.src || fallbackSrc || "";
@@ -4573,8 +4975,8 @@ function YaVideo({
4573
4975
  const controls = videoData.controls ?? true;
4574
4976
  const playsinline = videoData.playsinline ?? true;
4575
4977
  const preload = videoData.preload ?? "metadata";
4576
- const [prefersReducedMotion, setPrefersReducedMotion] = useState11(false);
4577
- useEffect11(() => {
4978
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState12(false);
4979
+ useEffect12(() => {
4578
4980
  const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
4579
4981
  setPrefersReducedMotion(mediaQuery.matches);
4580
4982
  const handleChange = (e) => {
@@ -4584,7 +4986,7 @@ function YaVideo({
4584
4986
  return () => mediaQuery.removeEventListener("change", handleChange);
4585
4987
  }, []);
4586
4988
  const effectiveAutoplay = autoplay && !prefersReducedMotion;
4587
- useEffect11(() => {
4989
+ useEffect12(() => {
4588
4990
  if (loading === "eager" || isInView) return;
4589
4991
  const observer = new IntersectionObserver(
4590
4992
  (entries) => {
@@ -4601,7 +5003,7 @@ function YaVideo({
4601
5003
  }
4602
5004
  return () => observer.disconnect();
4603
5005
  }, [loading, isInView]);
4604
- const handleKeyDown = useCallback13(
5006
+ const handleKeyDown = useCallback14(
4605
5007
  (e) => {
4606
5008
  if ((e.key === " " || e.key === "Enter") && videoData.type === "upload" && controls) {
4607
5009
  e.preventDefault();
@@ -4617,7 +5019,7 @@ function YaVideo({
4617
5019
  },
4618
5020
  [videoData.type, controls]
4619
5021
  );
4620
- const handleClick = useCallback13(() => {
5022
+ const handleClick = useCallback14(() => {
4621
5023
  if (mode !== "inline-edit") return;
4622
5024
  if (document.body.classList.contains("builder-selector-active")) return;
4623
5025
  setIsSelected(true);
@@ -4637,7 +5039,7 @@ function YaVideo({
4637
5039
  "*"
4638
5040
  );
4639
5041
  }, [mode, fieldId, videoData]);
4640
- useEffect11(() => {
5042
+ useEffect12(() => {
4641
5043
  if (mode !== "inline-edit") return;
4642
5044
  const handleMessage2 = (event) => {
4643
5045
  if (event.data?.type === "YA_VIDEO_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
@@ -4650,7 +5052,7 @@ function YaVideo({
4650
5052
  window.addEventListener("message", handleMessage2);
4651
5053
  return () => window.removeEventListener("message", handleMessage2);
4652
5054
  }, [mode, fieldId]);
4653
- useEffect11(() => {
5055
+ useEffect12(() => {
4654
5056
  if (mode !== "inline-edit") return;
4655
5057
  const checkSize = () => {
4656
5058
  if (containerRef.current) {
@@ -4662,7 +5064,7 @@ function YaVideo({
4662
5064
  window.addEventListener("resize", checkSize);
4663
5065
  return () => window.removeEventListener("resize", checkSize);
4664
5066
  }, [mode]);
4665
- useEffect11(() => {
5067
+ useEffect12(() => {
4666
5068
  if (!isSelected || mode !== "inline-edit") return;
4667
5069
  let lastRectKey = "";
4668
5070
  let lastTime = 0;
@@ -4699,23 +5101,23 @@ function YaVideo({
4699
5101
  const renderVideo = (isReadOnly) => {
4700
5102
  if (!src && !isReadOnly) {
4701
5103
  return /* @__PURE__ */ jsxs7("div", { className: "ya-video-placeholder", children: [
4702
- /* @__PURE__ */ jsx13("img", { src: PLACEHOLDER_SVG2, alt: "" }),
4703
- /* @__PURE__ */ jsx13("span", { children: "No video selected" })
5104
+ /* @__PURE__ */ jsx14("img", { src: PLACEHOLDER_SVG2, alt: "" }),
5105
+ /* @__PURE__ */ jsx14("span", { children: "No video selected" })
4704
5106
  ] });
4705
5107
  }
4706
5108
  if (!isInView && loading === "lazy" && !isReadOnly) {
4707
- return /* @__PURE__ */ jsx13(
5109
+ return /* @__PURE__ */ jsx14(
4708
5110
  "div",
4709
5111
  {
4710
5112
  className: "ya-video-placeholder",
4711
5113
  style: { aspectRatio },
4712
- children: /* @__PURE__ */ jsx13("img", { src: PLACEHOLDER_SVG2, alt: "" })
5114
+ children: /* @__PURE__ */ jsx14("img", { src: PLACEHOLDER_SVG2, alt: "" })
4713
5115
  }
4714
5116
  );
4715
5117
  }
4716
5118
  if (videoData.type === "youtube" && src) {
4717
5119
  const embedUrl = buildYouTubeEmbedUrl(src, videoData);
4718
- return /* @__PURE__ */ jsx13(
5120
+ return /* @__PURE__ */ jsx14(
4719
5121
  "iframe",
4720
5122
  {
4721
5123
  src: embedUrl,
@@ -4735,7 +5137,7 @@ function YaVideo({
4735
5137
  }
4736
5138
  if (videoData.type === "vimeo" && src) {
4737
5139
  const embedUrl = buildVimeoEmbedUrl(src, videoData);
4738
- return /* @__PURE__ */ jsx13(
5140
+ return /* @__PURE__ */ jsx14(
4739
5141
  "iframe",
4740
5142
  {
4741
5143
  src: embedUrl,
@@ -4755,7 +5157,7 @@ function YaVideo({
4755
5157
  }
4756
5158
  const resolvedSrc = resolveAssetUrl(src);
4757
5159
  const resolvedPoster = poster ? resolveAssetUrl(poster) : void 0;
4758
- return /* @__PURE__ */ jsx13(
5160
+ return /* @__PURE__ */ jsx14(
4759
5161
  "video",
4760
5162
  {
4761
5163
  ref: videoRef,
@@ -4790,7 +5192,7 @@ function YaVideo({
4790
5192
  );
4791
5193
  };
4792
5194
  if (mode === "read-only") {
4793
- return /* @__PURE__ */ jsx13(
5195
+ return /* @__PURE__ */ jsx14(
4794
5196
  "div",
4795
5197
  {
4796
5198
  ref: containerRef,
@@ -4818,8 +5220,8 @@ function YaVideo({
4818
5220
  strokeLinecap: "round",
4819
5221
  strokeLinejoin: "round",
4820
5222
  children: [
4821
- /* @__PURE__ */ jsx13("rect", { x: "2", y: "4", width: "15", height: "13", rx: "2", ry: "2" }),
4822
- /* @__PURE__ */ jsx13("polygon", { points: "22 7 15 12 22 17 22 7", fill: "currentColor" })
5223
+ /* @__PURE__ */ jsx14("rect", { x: "2", y: "4", width: "15", height: "13", rx: "2", ry: "2" }),
5224
+ /* @__PURE__ */ jsx14("polygon", { points: "22 7 15 12 22 17 22 7", fill: "currentColor" })
4823
5225
  ]
4824
5226
  }
4825
5227
  );
@@ -4848,12 +5250,12 @@ function YaVideo({
4848
5250
  renderVideo(false),
4849
5251
  isSmallVideo ? /* @__PURE__ */ jsxs7(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
4850
5252
  videoIcon,
4851
- /* @__PURE__ */ jsx13("span", { children: "Click to edit" })
5253
+ /* @__PURE__ */ jsx14("span", { children: "Click to edit" })
4852
5254
  ] }) : (
4853
5255
  /* For large videos: show overlay inside the container */
4854
5256
  /* @__PURE__ */ jsxs7("div", { className: "ya-video-overlay", children: [
4855
- /* @__PURE__ */ jsx13("div", { className: "ya-video-edit-icon", children: videoIcon }),
4856
- /* @__PURE__ */ jsx13("span", { className: "ya-video-edit-label", children: "Click to edit" })
5257
+ /* @__PURE__ */ jsx14("div", { className: "ya-video-edit-icon", children: videoIcon }),
5258
+ /* @__PURE__ */ jsx14("span", { className: "ya-video-edit-label", children: "Click to edit" })
4857
5259
  ] })
4858
5260
  )
4859
5261
  ]
@@ -4862,13 +5264,13 @@ function YaVideo({
4862
5264
  }
4863
5265
 
4864
5266
  // src/components/YaEmbed.tsx
4865
- import { useCallback as useCallback14, useEffect as useEffect12, useRef as useRef13, useState as useState12 } from "react";
5267
+ import { useCallback as useCallback15, useEffect as useEffect13, useRef as useRef14, useState as useState13 } from "react";
4866
5268
 
4867
5269
  // src/components/ya-embed.css
4868
5270
  styleInject('.ya-embed-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n.ya-embed-wrapper iframe {\n display: block;\n width: 100%;\n height: 100%;\n}\n.ya-embed-container {\n position: relative;\n display: block;\n width: 100%;\n min-width: 80px;\n min-height: 80px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-embed-container iframe {\n display: block;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n.ya-embed-editable {\n cursor: pointer;\n}\n.ya-embed-editable:hover {\n outline: 2px dashed var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-selected {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-embed-editable:hover .ya-embed-overlay {\n opacity: 1;\n}\n.ya-embed-selected .ya-embed-overlay {\n opacity: 0;\n}\n.ya-embed-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-embed-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-embed-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n.ya-embed-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n min-height: 120px;\n background: #f3f4f6;\n border: 2px dashed #d1d5db;\n border-radius: 8px;\n color: #6b7280;\n font-size: 14px;\n}\n.ya-embed-placeholder img {\n width: 64px;\n height: auto;\n opacity: 0.5;\n}\n@keyframes ya-embed-success {\n 0% {\n outline-color: var(--color-primary, #d4a574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #d4a574);\n outline-width: 2px;\n }\n}\n.ya-embed-success {\n animation: ya-embed-success 0.4s ease;\n}\n.ya-embed-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-embed-shimmer 1.5s infinite;\n}\n@keyframes ya-embed-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-embed-container:focus {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-embed-container:focus-visible {\n outline: 3px solid var(--color-primary, #d4a574);\n outline-offset: 4px;\n}\n.ya-embed-small .ya-embed-overlay {\n display: none;\n}\n.ya-embed-twitter {\n min-height: 200px;\n}\n.ya-embed-twitter .twitter-tweet {\n margin: 0 auto !important;\n}\n.ya-embed-wrapper[data-embed-type=spotify],\n.ya-embed-container[data-embed-type=spotify] {\n min-height: 80px;\n}\n.ya-embed-wrapper[data-embed-type=soundcloud],\n.ya-embed-container[data-embed-type=soundcloud] {\n min-height: 166px;\n}\n.ya-embed-wrapper[data-embed-type=instagram] iframe,\n.ya-embed-container[data-embed-type=instagram] iframe {\n min-height: 400px;\n}\n');
4869
5271
 
4870
5272
  // src/components/YaEmbed.tsx
4871
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5273
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
4872
5274
  function parseEmbedUrl(url) {
4873
5275
  if (!url) return null;
4874
5276
  const trimmedUrl = url.trim();
@@ -4981,20 +5383,21 @@ function YaEmbed({
4981
5383
  loading = "lazy",
4982
5384
  defaultValue
4983
5385
  }) {
4984
- const { getValue, mode } = useContentStore();
4985
- const containerRef = useRef13(null);
4986
- const [isSelected, setIsSelected] = useState12(false);
4987
- const [isHovered, setIsHovered] = useState12(false);
4988
- const [isSmallEmbed, setIsSmallEmbed] = useState12(false);
4989
- const [isInView, setIsInView] = useState12(loading === "eager");
4990
- const rawValue = getValue(fieldId);
5386
+ const content = useContent(fieldId);
5387
+ const { mode } = content;
5388
+ const containerRef = useRef14(null);
5389
+ const [isSelected, setIsSelected] = useState13(false);
5390
+ const [isHovered, setIsHovered] = useState13(false);
5391
+ const [isSmallEmbed, setIsSmallEmbed] = useState13(false);
5392
+ const [isInView, setIsInView] = useState13(loading === "eager");
5393
+ const rawValue = content.get();
4991
5394
  const parsedValue = parseEmbedValue(rawValue);
4992
5395
  const embedData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
4993
5396
  const src = embedData.src || "";
4994
5397
  const embedType = embedData.type || "custom";
4995
5398
  const height = embedData.height;
4996
5399
  const aspectRatio = embedData.aspectRatio || propAspectRatio || "16/9";
4997
- useEffect12(() => {
5400
+ useEffect13(() => {
4998
5401
  if (loading === "eager" || isInView) return;
4999
5402
  const observer = new IntersectionObserver(
5000
5403
  (entries) => {
@@ -5011,7 +5414,7 @@ function YaEmbed({
5011
5414
  }
5012
5415
  return () => observer.disconnect();
5013
5416
  }, [loading, isInView]);
5014
- const handleClick = useCallback14(() => {
5417
+ const handleClick = useCallback15(() => {
5015
5418
  if (mode !== "inline-edit") return;
5016
5419
  if (document.body.classList.contains("builder-selector-active")) return;
5017
5420
  setIsSelected(true);
@@ -5031,7 +5434,7 @@ function YaEmbed({
5031
5434
  "*"
5032
5435
  );
5033
5436
  }, [mode, fieldId, embedData]);
5034
- useEffect12(() => {
5437
+ useEffect13(() => {
5035
5438
  if (mode !== "inline-edit") return;
5036
5439
  const handleMessage2 = (event) => {
5037
5440
  if (event.data?.type === "YA_EMBED_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
@@ -5044,7 +5447,7 @@ function YaEmbed({
5044
5447
  window.addEventListener("message", handleMessage2);
5045
5448
  return () => window.removeEventListener("message", handleMessage2);
5046
5449
  }, [mode, fieldId]);
5047
- useEffect12(() => {
5450
+ useEffect13(() => {
5048
5451
  if (mode !== "inline-edit") return;
5049
5452
  const checkSize = () => {
5050
5453
  if (containerRef.current) {
@@ -5056,7 +5459,7 @@ function YaEmbed({
5056
5459
  window.addEventListener("resize", checkSize);
5057
5460
  return () => window.removeEventListener("resize", checkSize);
5058
5461
  }, [mode]);
5059
- useEffect12(() => {
5462
+ useEffect13(() => {
5060
5463
  if (!isSelected || mode !== "inline-edit") return;
5061
5464
  let lastRectKey = "";
5062
5465
  let lastTime = 0;
@@ -5093,16 +5496,16 @@ function YaEmbed({
5093
5496
  const renderEmbed = (isReadOnly) => {
5094
5497
  if (!src && !isReadOnly) {
5095
5498
  return /* @__PURE__ */ jsxs8("div", { className: "ya-embed-placeholder", children: [
5096
- /* @__PURE__ */ jsx14("img", { src: PLACEHOLDER_SVG3, alt: "" }),
5097
- /* @__PURE__ */ jsx14("span", { children: "No embed selected" })
5499
+ /* @__PURE__ */ jsx15("img", { src: PLACEHOLDER_SVG3, alt: "" }),
5500
+ /* @__PURE__ */ jsx15("span", { children: "No embed selected" })
5098
5501
  ] });
5099
5502
  }
5100
5503
  if (!isInView && loading === "lazy" && !isReadOnly) {
5101
- return /* @__PURE__ */ jsx14("div", { className: "ya-embed-placeholder", style: { aspectRatio }, children: /* @__PURE__ */ jsx14("img", { src: PLACEHOLDER_SVG3, alt: "" }) });
5504
+ return /* @__PURE__ */ jsx15("div", { className: "ya-embed-placeholder", style: { aspectRatio }, children: /* @__PURE__ */ jsx15("img", { src: PLACEHOLDER_SVG3, alt: "" }) });
5102
5505
  }
5103
5506
  if (embedType === "spotify" && src) {
5104
5507
  const embedUrl = buildSpotifyEmbedUrl(src);
5105
- return /* @__PURE__ */ jsx14(
5508
+ return /* @__PURE__ */ jsx15(
5106
5509
  "iframe",
5107
5510
  {
5108
5511
  src: embedUrl,
@@ -5120,7 +5523,7 @@ function YaEmbed({
5120
5523
  }
5121
5524
  if (embedType === "soundcloud" && src) {
5122
5525
  const embedUrl = buildSoundCloudEmbedUrl(src);
5123
- return /* @__PURE__ */ jsx14(
5526
+ return /* @__PURE__ */ jsx15(
5124
5527
  "iframe",
5125
5528
  {
5126
5529
  src: embedUrl,
@@ -5137,13 +5540,13 @@ function YaEmbed({
5137
5540
  }
5138
5541
  if (embedType === "twitter" && src) {
5139
5542
  return /* @__PURE__ */ jsxs8("div", { className: "ya-embed-twitter", children: [
5140
- /* @__PURE__ */ jsx14("blockquote", { className: "twitter-tweet", "data-dnt": "true", children: /* @__PURE__ */ jsx14("a", { href: embedData.originalUrl || `https://twitter.com/i/status/${src}`, children: "Loading tweet..." }) }),
5141
- /* @__PURE__ */ jsx14(TwitterWidgetLoader, {})
5543
+ /* @__PURE__ */ jsx15("blockquote", { className: "twitter-tweet", "data-dnt": "true", children: /* @__PURE__ */ jsx15("a", { href: embedData.originalUrl || `https://twitter.com/i/status/${src}`, children: "Loading tweet..." }) }),
5544
+ /* @__PURE__ */ jsx15(TwitterWidgetLoader, {})
5142
5545
  ] });
5143
5546
  }
5144
5547
  if (embedType === "instagram" && src) {
5145
5548
  const embedUrl = buildInstagramEmbedUrl(src);
5146
- return /* @__PURE__ */ jsx14(
5549
+ return /* @__PURE__ */ jsx15(
5147
5550
  "iframe",
5148
5551
  {
5149
5552
  src: embedUrl,
@@ -5161,7 +5564,7 @@ function YaEmbed({
5161
5564
  );
5162
5565
  }
5163
5566
  if (embedType === "custom" && src) {
5164
- return /* @__PURE__ */ jsx14(
5567
+ return /* @__PURE__ */ jsx15(
5165
5568
  "iframe",
5166
5569
  {
5167
5570
  src,
@@ -5185,7 +5588,7 @@ function YaEmbed({
5185
5588
  maxWidth: maxWidth ? `${maxWidth}px` : void 0
5186
5589
  };
5187
5590
  if (mode === "read-only") {
5188
- return /* @__PURE__ */ jsx14(
5591
+ return /* @__PURE__ */ jsx15(
5189
5592
  "div",
5190
5593
  {
5191
5594
  ref: containerRef,
@@ -5209,8 +5612,8 @@ function YaEmbed({
5209
5612
  strokeLinecap: "round",
5210
5613
  strokeLinejoin: "round",
5211
5614
  children: [
5212
- /* @__PURE__ */ jsx14("polyline", { points: "16 18 22 12 16 6" }),
5213
- /* @__PURE__ */ jsx14("polyline", { points: "8 6 2 12 8 18" })
5615
+ /* @__PURE__ */ jsx15("polyline", { points: "16 18 22 12 16 6" }),
5616
+ /* @__PURE__ */ jsx15("polyline", { points: "8 6 2 12 8 18" })
5214
5617
  ]
5215
5618
  }
5216
5619
  );
@@ -5239,12 +5642,12 @@ function YaEmbed({
5239
5642
  renderEmbed(false),
5240
5643
  isSmallEmbed ? /* @__PURE__ */ jsxs8(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
5241
5644
  embedIcon,
5242
- /* @__PURE__ */ jsx14("span", { children: "Click to edit" })
5645
+ /* @__PURE__ */ jsx15("span", { children: "Click to edit" })
5243
5646
  ] }) : (
5244
5647
  /* For large embeds: show overlay inside the container */
5245
5648
  /* @__PURE__ */ jsxs8("div", { className: "ya-embed-overlay", children: [
5246
- /* @__PURE__ */ jsx14("div", { className: "ya-embed-edit-icon", children: embedIcon }),
5247
- /* @__PURE__ */ jsx14("span", { className: "ya-embed-edit-label", children: "Click to edit" })
5649
+ /* @__PURE__ */ jsx15("div", { className: "ya-embed-edit-icon", children: embedIcon }),
5650
+ /* @__PURE__ */ jsx15("span", { className: "ya-embed-edit-label", children: "Click to edit" })
5248
5651
  ] })
5249
5652
  )
5250
5653
  ]
@@ -5252,7 +5655,7 @@ function YaEmbed({
5252
5655
  );
5253
5656
  }
5254
5657
  function TwitterWidgetLoader() {
5255
- useEffect12(() => {
5658
+ useEffect13(() => {
5256
5659
  if (window.twttr?.widgets) {
5257
5660
  ;
5258
5661
  window.twttr.widgets.load();
@@ -5273,7 +5676,7 @@ function TwitterWidgetLoader() {
5273
5676
  }
5274
5677
 
5275
5678
  // src/components/YaLink.tsx
5276
- import { useEffect as useEffect15, useLayoutEffect as useLayoutEffect3, useRef as useRef16, useState as useState15, useCallback as useCallback17, useId } from "react";
5679
+ import { useEffect as useEffect16, useLayoutEffect as useLayoutEffect3, useRef as useRef17, useState as useState16, useCallback as useCallback18, useId } from "react";
5277
5680
  import { createPortal as createPortal6 } from "react-dom";
5278
5681
  import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
5279
5682
  import { BubbleMenu } from "@tiptap/react/menus";
@@ -5283,7 +5686,7 @@ import { Extension as Extension2 } from "@tiptap/core";
5283
5686
  import { Link as WouterLink, useLocation } from "wouter";
5284
5687
 
5285
5688
  // src/components/SafeTriangleBelow.tsx
5286
- import { useEffect as useEffect13, useState as useState13, useRef as useRef14, useCallback as useCallback15 } from "react";
5689
+ import { useEffect as useEffect14, useState as useState14, useRef as useRef15, useCallback as useCallback16 } from "react";
5287
5690
  function SafeTriangleBelow({
5288
5691
  triggerRef,
5289
5692
  popoverRef,
@@ -5291,10 +5694,10 @@ function SafeTriangleBelow({
5291
5694
  onLeave,
5292
5695
  onStayInside
5293
5696
  }) {
5294
- const [bounds, setBounds] = useState13(null);
5295
- const boundsRef = useRef14(bounds);
5697
+ const [bounds, setBounds] = useState14(null);
5698
+ const boundsRef = useRef15(bounds);
5296
5699
  boundsRef.current = bounds;
5297
- useEffect13(() => {
5700
+ useEffect14(() => {
5298
5701
  if (!isVisible || !triggerRef.current || !popoverRef.current) {
5299
5702
  setBounds(null);
5300
5703
  return;
@@ -5312,7 +5715,7 @@ function SafeTriangleBelow({
5312
5715
  }, 10);
5313
5716
  return () => clearTimeout(timer);
5314
5717
  }, [isVisible, triggerRef, popoverRef]);
5315
- const checkMousePosition = useCallback15((e) => {
5718
+ const checkMousePosition = useCallback16((e) => {
5316
5719
  const b = boundsRef.current;
5317
5720
  if (!b) return;
5318
5721
  const { clientX: x, clientY: y } = e;
@@ -5324,7 +5727,7 @@ function SafeTriangleBelow({
5324
5727
  onStayInside?.();
5325
5728
  }
5326
5729
  }, [onLeave, onStayInside]);
5327
- useEffect13(() => {
5730
+ useEffect14(() => {
5328
5731
  if (!isVisible || !bounds) return;
5329
5732
  document.addEventListener("mousemove", checkMousePosition);
5330
5733
  return () => document.removeEventListener("mousemove", checkMousePosition);
@@ -5333,22 +5736,22 @@ function SafeTriangleBelow({
5333
5736
  }
5334
5737
 
5335
5738
  // src/hooks/useSafeTriangle.ts
5336
- import { useState as useState14, useRef as useRef15, useCallback as useCallback16, useEffect as useEffect14 } from "react";
5739
+ import { useState as useState15, useRef as useRef16, useCallback as useCallback17, useEffect as useEffect15 } from "react";
5337
5740
  function useSafeTriangle(options = {}) {
5338
5741
  const { showDelay = 0, hideDelay = 150, enabled = true } = options;
5339
- const [isVisible, setIsVisible] = useState14(false);
5340
- const [isHovering, setIsHovering] = useState14(false);
5341
- const triggerRef = useRef15(null);
5342
- const popoverRef = useRef15(null);
5343
- const showTimeoutRef = useRef15(null);
5344
- const hideTimeoutRef = useRef15(null);
5345
- useEffect14(() => {
5742
+ const [isVisible, setIsVisible] = useState15(false);
5743
+ const [isHovering, setIsHovering] = useState15(false);
5744
+ const triggerRef = useRef16(null);
5745
+ const popoverRef = useRef16(null);
5746
+ const showTimeoutRef = useRef16(null);
5747
+ const hideTimeoutRef = useRef16(null);
5748
+ useEffect15(() => {
5346
5749
  return () => {
5347
5750
  if (showTimeoutRef.current) clearTimeout(showTimeoutRef.current);
5348
5751
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
5349
5752
  };
5350
5753
  }, []);
5351
- const show = useCallback16(() => {
5754
+ const show = useCallback17(() => {
5352
5755
  if (!enabled) return;
5353
5756
  if (hideTimeoutRef.current) {
5354
5757
  clearTimeout(hideTimeoutRef.current);
@@ -5356,7 +5759,7 @@ function useSafeTriangle(options = {}) {
5356
5759
  }
5357
5760
  setIsVisible(true);
5358
5761
  }, [enabled]);
5359
- const hide = useCallback16(() => {
5762
+ const hide = useCallback17(() => {
5360
5763
  if (showTimeoutRef.current) {
5361
5764
  clearTimeout(showTimeoutRef.current);
5362
5765
  showTimeoutRef.current = null;
@@ -5364,7 +5767,7 @@ function useSafeTriangle(options = {}) {
5364
5767
  setIsVisible(false);
5365
5768
  setIsHovering(false);
5366
5769
  }, []);
5367
- const handleMouseEnter = useCallback16(() => {
5770
+ const handleMouseEnter = useCallback17(() => {
5368
5771
  if (!enabled) return;
5369
5772
  setIsHovering(true);
5370
5773
  if (hideTimeoutRef.current) {
@@ -5379,7 +5782,7 @@ function useSafeTriangle(options = {}) {
5379
5782
  setIsVisible(true);
5380
5783
  }
5381
5784
  }, [showDelay, enabled]);
5382
- const handleMouseLeave = useCallback16(() => {
5785
+ const handleMouseLeave = useCallback17(() => {
5383
5786
  setIsHovering(false);
5384
5787
  if (showTimeoutRef.current) {
5385
5788
  clearTimeout(showTimeoutRef.current);
@@ -5389,16 +5792,16 @@ function useSafeTriangle(options = {}) {
5389
5792
  setIsVisible(false);
5390
5793
  }, hideDelay);
5391
5794
  }, [hideDelay]);
5392
- const handleFocus = useCallback16(() => {
5795
+ const handleFocus = useCallback17(() => {
5393
5796
  if (!enabled) return;
5394
5797
  setIsVisible(true);
5395
5798
  }, [enabled]);
5396
- const handleTriangleLeave = useCallback16(() => {
5799
+ const handleTriangleLeave = useCallback17(() => {
5397
5800
  if (!isHovering) {
5398
5801
  setIsVisible(false);
5399
5802
  }
5400
5803
  }, [isHovering]);
5401
- const handleStayInside = useCallback16(() => {
5804
+ const handleStayInside = useCallback17(() => {
5402
5805
  if (hideTimeoutRef.current) {
5403
5806
  clearTimeout(hideTimeoutRef.current);
5404
5807
  hideTimeoutRef.current = null;
@@ -5429,7 +5832,7 @@ function useSafeTriangle(options = {}) {
5429
5832
  styleInject('.ya-link-wrapper {\n position: relative;\n display: inline;\n}\n.ya-link-editable {\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-link-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n}\nbody.builder-selector-active .ya-link-editable:hover {\n outline: none;\n cursor: inherit;\n}\n.ya-link-editing {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n position: relative;\n}\n.ya-link-editing .ProseMirror {\n color: #1a1a1a !important;\n caret-color: #1a1a1a;\n}\n.ya-link-editing .ProseMirror p::selection,\n.ya-link-editing .ProseMirror::selection {\n background-color: rgba(212, 165, 116, 0.4);\n color: inherit;\n}\n.ya-link-editing .ProseMirror p::-moz-selection,\n.ya-link-editing .ProseMirror::-moz-selection {\n background-color: rgba(212, 165, 116, 0.4);\n color: inherit;\n}\n.ProseMirror-gapcursor {\n display: none !important;\n}\n.ProseMirror .ProseMirror-dropcursor {\n display: none !important;\n}\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing)::selection,\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing) *::selection {\n color: inherit;\n}\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing)::-moz-selection,\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing) *::-moz-selection {\n color: inherit;\n}\n.ya-link-actions {\n display: flex;\n gap: 8px;\n z-index: 9999;\n background: rgba(26, 26, 26, 0.95);\n padding: 8px 10px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.ya-link-btn {\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n border: none;\n}\n.ya-link-btn-cancel {\n background: #333333;\n color: #ffffff;\n border: 1px solid #555555;\n}\n.ya-link-btn-cancel:hover {\n background: #444444;\n color: #ffffff;\n border-color: #666666;\n}\n.ya-link-btn-save {\n background: #D4A574;\n color: #1a1a1a;\n}\n.ya-link-btn-save:hover {\n background: #c4956a;\n}\n.ya-href-popover {\n position: fixed;\n z-index: 10000;\n min-width: 280px;\n max-width: 320px;\n background: #1a1a1a;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);\n animation: ya-href-popover-fade-in 0.15s ease;\n overflow: hidden;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n@keyframes ya-href-popover-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-href-popover::before {\n content: "";\n position: absolute;\n top: -6px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #1a1a1a;\n}\n.ya-href-popover-header {\n padding: 12px 16px;\n font-size: 13px;\n font-weight: 600;\n color: #ffffff;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-href-popover-section {\n padding: 12px 16px;\n}\n.ya-href-popover-label {\n display: block;\n font-size: 11px;\n font-weight: 500;\n color: rgba(255, 255, 255, 0.6);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n.ya-href-collapsible-header {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 0;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: color 0.15s ease;\n}\n.ya-href-collapsible-header:hover {\n color: rgba(255, 255, 255, 0.8);\n}\n.ya-href-chevron {\n font-size: 8px;\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-href-popover-pages {\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-height: 200px;\n overflow-y: auto;\n}\n.ya-href-page-btn {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n width: 100%;\n padding: 10px 12px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid transparent;\n border-radius: 8px;\n color: #e0e0e0;\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.ya-href-page-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.2);\n}\n.ya-href-page-btn.is-selected {\n background: #D4A574;\n color: #1a1a1a;\n}\n.ya-href-page-btn.is-selected .ya-href-page-path {\n color: rgba(26, 26, 26, 0.6);\n}\n.ya-href-page-path {\n font-size: 11px;\n color: rgba(255, 255, 255, 0.4);\n font-family: monospace;\n word-break: break-all;\n}\n.ya-href-external-toggle {\n display: block;\n width: 100%;\n padding: 10px 16px;\n background: transparent;\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n color: #D4A574;\n font-size: 12px;\n font-weight: 500;\n text-align: center;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n.ya-href-external-toggle:hover {\n background: rgba(255, 255, 255, 0.05);\n}\n.ya-href-url-input {\n width: 100%;\n padding: 10px 12px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n color: #ffffff;\n font-size: 13px;\n outline: none;\n transition: border-color 0.15s ease;\n}\n.ya-href-url-input::placeholder {\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-href-url-input:focus {\n border-color: var(--color-primary, #D4A574);\n}\n.ya-href-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-href-popover--above {\n animation: ya-href-popover-fade-in-above 0.15s ease;\n}\n@keyframes ya-href-popover-fade-in-above {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-href-popover--above::before {\n top: auto;\n bottom: -6px;\n border-bottom: none;\n border-top: 8px solid #1a1a1a;\n}\n.ya-link-edit-popover {\n position: fixed;\n z-index: 10000;\n background: #2a2a2a;\n border-radius: 6px;\n padding: 4px;\n display: flex;\n gap: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n transition: opacity 100ms ease;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n}\n.ya-link-edit-popover::before {\n content: "";\n position: absolute;\n top: -5px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #2a2a2a;\n}\n.ya-link-edit-popover button {\n background: #3a3a3a;\n border: none;\n color: #fff;\n padding: 6px 12px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: background 0.15s ease;\n}\n.ya-link-edit-popover button:hover {\n background: #4a4a4a;\n}\n');
5430
5833
 
5431
5834
  // src/components/YaLink.tsx
5432
- import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
5835
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5433
5836
  function isInternalPath(path) {
5434
5837
  if (!path) return false;
5435
5838
  if (path.startsWith("#")) return false;
@@ -5527,37 +5930,40 @@ function discoverSectionsFromDOM() {
5527
5930
  return sections;
5528
5931
  }
5529
5932
  function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName, style, as: Component = "a", children, availablePages, onClick, target, rel }) {
5530
- const { getValue, setValue, mode, saveToWorker, getPages } = useContentStore();
5531
- const [, navigate] = useLocation();
5532
- const pages = availablePages ?? getPages();
5533
- const [sections, setSections] = useState15([]);
5534
- const [sectionsExpanded, setSectionsExpanded] = useState15(false);
5535
5933
  const textFieldId = `${fieldId}.text`;
5536
5934
  const hrefFieldId = `${fieldId}.href`;
5537
- const storeText = getValue(textFieldId);
5538
- const storeHref = getValue(hrefFieldId);
5935
+ const textContent = useContent(textFieldId);
5936
+ const hrefContent = useContent(hrefFieldId);
5937
+ const { mode } = textContent;
5938
+ const { getPages } = useContentStore();
5939
+ const [, navigate] = useLocation();
5940
+ const pages = availablePages ?? getPages();
5941
+ const [sections, setSections] = useState16([]);
5942
+ const [sectionsExpanded, setSectionsExpanded] = useState16(false);
5943
+ const storeText = textContent.get();
5944
+ const storeHref = hrefContent.get();
5539
5945
  const isIconMode = children != null && typeof children !== "string";
5540
5946
  const text2 = storeText || (typeof children === "string" ? children : "");
5541
5947
  const href = storeHref || defaultHref;
5542
5948
  const isExternal = isExternalHref(href);
5543
5949
  const effectiveTarget = target ?? (isExternal ? "_blank" : void 0);
5544
5950
  const effectiveRel = rel ?? (isExternal ? "noopener noreferrer" : void 0);
5545
- const [editingMode, setEditingMode] = useState15(null);
5546
- const [originalText, setOriginalText] = useState15(text2);
5547
- const [originalHref, setOriginalHref] = useState15(href);
5548
- const [currentHref, setCurrentHref] = useState15(href);
5549
- const [isExternalUrl, setIsExternalUrl] = useState15(false);
5550
- const [externalUrl, setExternalUrl] = useState15("");
5551
- const containerRef = useRef16(null);
5552
- const hrefPopoverRef = useRef16(null);
5553
- const [actionButtonsPos, setActionButtonsPos] = useState15(null);
5554
- const [editPopoverPos, setEditPopoverPos] = useState15(null);
5555
- const [editPopoverVisible, setEditPopoverVisible] = useState15(false);
5556
- const [editPopoverMounted, setEditPopoverMounted] = useState15(false);
5557
- const [hrefPopoverPos, setHrefPopoverPos] = useState15(null);
5558
- const handleSaveTextRef = useRef16(() => {
5951
+ const [editingMode, setEditingMode] = useState16(null);
5952
+ const [originalText, setOriginalText] = useState16(text2);
5953
+ const [originalHref, setOriginalHref] = useState16(href);
5954
+ const [currentHref, setCurrentHref] = useState16(href);
5955
+ const [isExternalUrl, setIsExternalUrl] = useState16(false);
5956
+ const [externalUrl, setExternalUrl] = useState16("");
5957
+ const containerRef = useRef17(null);
5958
+ const hrefPopoverRef = useRef17(null);
5959
+ const [actionButtonsPos, setActionButtonsPos] = useState16(null);
5960
+ const [editPopoverPos, setEditPopoverPos] = useState16(null);
5961
+ const [editPopoverVisible, setEditPopoverVisible] = useState16(false);
5962
+ const [editPopoverMounted, setEditPopoverMounted] = useState16(false);
5963
+ const [hrefPopoverPos, setHrefPopoverPos] = useState16(null);
5964
+ const handleSaveTextRef = useRef17(() => {
5559
5965
  });
5560
- const handleCancelTextRef = useRef16(() => {
5966
+ const handleCancelTextRef = useRef17(() => {
5561
5967
  });
5562
5968
  const {
5563
5969
  popoverRef: editPopoverRef,
@@ -5571,12 +5977,12 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5571
5977
  });
5572
5978
  const triggerRef = containerRef;
5573
5979
  const instanceId = useId();
5574
- useEffect15(() => {
5980
+ useEffect16(() => {
5575
5981
  if (showEditPopover && mode === "inline-edit" && !editingMode) {
5576
5982
  window.dispatchEvent(new CustomEvent("yalink:popover-open", { detail: { id: instanceId } }));
5577
5983
  }
5578
5984
  }, [showEditPopover, mode, editingMode, instanceId]);
5579
- useEffect15(() => {
5985
+ useEffect16(() => {
5580
5986
  const handleOtherPopoverOpen = (event) => {
5581
5987
  const customEvent = event;
5582
5988
  if (customEvent.detail.id !== instanceId && showEditPopover) {
@@ -5630,19 +6036,19 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5630
6036
  }
5631
6037
  }
5632
6038
  });
5633
- useEffect15(() => {
6039
+ useEffect16(() => {
5634
6040
  if (editor && editingMode !== "text") {
5635
6041
  if (editor.getHTML() !== text2) {
5636
6042
  editor.commands.setContent(text2);
5637
6043
  }
5638
6044
  }
5639
6045
  }, [text2, editor, editingMode]);
5640
- useEffect15(() => {
6046
+ useEffect16(() => {
5641
6047
  if (editingMode !== "link") {
5642
6048
  setCurrentHref(href);
5643
6049
  }
5644
6050
  }, [href, editingMode]);
5645
- useEffect15(() => {
6051
+ useEffect16(() => {
5646
6052
  if (editingMode !== "text" || !containerRef.current) {
5647
6053
  setActionButtonsPos(null);
5648
6054
  return;
@@ -5663,7 +6069,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5663
6069
  window.removeEventListener("resize", updatePosition);
5664
6070
  };
5665
6071
  }, [editingMode]);
5666
- useEffect15(() => {
6072
+ useEffect16(() => {
5667
6073
  const shouldShow = showEditPopover && !editingMode && mode === "inline-edit";
5668
6074
  if (shouldShow) {
5669
6075
  setEditPopoverMounted(true);
@@ -5725,7 +6131,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5725
6131
  window.removeEventListener("resize", updatePosition);
5726
6132
  };
5727
6133
  }, [editingMode]);
5728
- useEffect15(() => {
6134
+ useEffect16(() => {
5729
6135
  if (editingMode !== "link") return;
5730
6136
  const handleClickOutside = (event) => {
5731
6137
  const target2 = event.target;
@@ -5739,38 +6145,38 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5739
6145
  document.addEventListener("mousedown", handleClickOutside);
5740
6146
  return () => document.removeEventListener("mousedown", handleClickOutside);
5741
6147
  }, [editingMode, originalHref]);
5742
- const handleSaveText = useCallback17(() => {
6148
+ const handleSaveText = useCallback18(() => {
5743
6149
  if (!editor) return;
5744
6150
  let html = editor.getHTML();
5745
6151
  html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
5746
- setValue(textFieldId, html, "user");
5747
- saveToWorker?.(textFieldId, html);
6152
+ textContent.set(html, "user");
6153
+ textContent.save();
5748
6154
  setEditingMode(null);
5749
- }, [editor, textFieldId, setValue, saveToWorker]);
5750
- const handleSaveLink = useCallback17(() => {
5751
- setValue(hrefFieldId, currentHref, "user");
5752
- saveToWorker?.(hrefFieldId, currentHref);
6155
+ }, [editor, textContent]);
6156
+ const handleSaveLink = useCallback18(() => {
6157
+ hrefContent.set(currentHref, "user");
6158
+ hrefContent.save();
5753
6159
  setEditingMode(null);
5754
6160
  setIsExternalUrl(false);
5755
6161
  setExternalUrl("");
5756
- }, [hrefFieldId, currentHref, setValue, saveToWorker]);
5757
- const handleCancelText = useCallback17(() => {
6162
+ }, [currentHref, hrefContent]);
6163
+ const handleCancelText = useCallback18(() => {
5758
6164
  if (editor) {
5759
6165
  editor.commands.setContent(originalText);
5760
6166
  }
5761
6167
  setEditingMode(null);
5762
6168
  }, [editor, originalText]);
5763
- const handleCancelLink = useCallback17(() => {
6169
+ const handleCancelLink = useCallback18(() => {
5764
6170
  setCurrentHref(originalHref);
5765
6171
  setEditingMode(null);
5766
6172
  setIsExternalUrl(false);
5767
6173
  setExternalUrl("");
5768
6174
  }, [originalHref]);
5769
- useEffect15(() => {
6175
+ useEffect16(() => {
5770
6176
  handleSaveTextRef.current = handleSaveText;
5771
6177
  handleCancelTextRef.current = handleCancelText;
5772
6178
  }, [handleSaveText, handleCancelText]);
5773
- const handleClick = useCallback17(
6179
+ const handleClick = useCallback18(
5774
6180
  (e) => {
5775
6181
  const selectModeEnabled = window.__builderSelectModeEnabled;
5776
6182
  if (selectModeEnabled) {
@@ -5802,7 +6208,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5802
6208
  },
5803
6209
  [href, navigate, onClick]
5804
6210
  );
5805
- const startEditText = useCallback17(() => {
6211
+ const startEditText = useCallback18(() => {
5806
6212
  hideEditPopover();
5807
6213
  if (isIconMode) {
5808
6214
  window.dispatchEvent(new CustomEvent("yatext:edit-mode", {
@@ -5816,14 +6222,14 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5816
6222
  }, 20);
5817
6223
  }
5818
6224
  }, [text2, editor, hideEditPopover, isIconMode, fieldId]);
5819
- const startEditLink = useCallback17(() => {
6225
+ const startEditLink = useCallback18(() => {
5820
6226
  hideEditPopover();
5821
6227
  setEditingMode("link");
5822
6228
  setOriginalHref(href);
5823
6229
  setCurrentHref(href);
5824
6230
  setSections(discoverSectionsFromDOM());
5825
6231
  }, [href, hideEditPopover]);
5826
- const handleKeyDown = useCallback17(
6232
+ const handleKeyDown = useCallback18(
5827
6233
  (event) => {
5828
6234
  if (editingMode !== "text") return;
5829
6235
  if (event.key === "Enter" && !event.shiftKey) {
@@ -5844,7 +6250,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5844
6250
  },
5845
6251
  [editingMode, handleSaveText, handleCancelText]
5846
6252
  );
5847
- const handleFontSizeChange = useCallback17(
6253
+ const handleFontSizeChange = useCallback18(
5848
6254
  (e) => {
5849
6255
  if (!editor) return;
5850
6256
  const size = e.target.value;
@@ -5856,7 +6262,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5856
6262
  },
5857
6263
  [editor]
5858
6264
  );
5859
- const handleFontWeightChange = useCallback17(
6265
+ const handleFontWeightChange = useCallback18(
5860
6266
  (e) => {
5861
6267
  if (!editor) return;
5862
6268
  const weight = e.target.value;
@@ -5868,11 +6274,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5868
6274
  },
5869
6275
  [editor]
5870
6276
  );
5871
- const handlePageSelect = useCallback17((path) => {
6277
+ const handlePageSelect = useCallback18((path) => {
5872
6278
  setCurrentHref(path);
5873
6279
  setIsExternalUrl(false);
5874
6280
  }, []);
5875
- const handleExternalUrlApply = useCallback17(() => {
6281
+ const handleExternalUrlApply = useCallback18(() => {
5876
6282
  if (externalUrl) {
5877
6283
  setCurrentHref(externalUrl);
5878
6284
  }
@@ -5888,9 +6294,9 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5888
6294
  return attrs.fontWeight || "";
5889
6295
  };
5890
6296
  if (mode === "read-only") {
5891
- const content = isIconMode ? children : /* @__PURE__ */ jsx15(SafeHtml, { content: text2, mode });
6297
+ const content = isIconMode ? children : /* @__PURE__ */ jsx16(SafeHtml, { content: text2, mode });
5892
6298
  if (isInternalPath(href)) {
5893
- return /* @__PURE__ */ jsx15(
6299
+ return /* @__PURE__ */ jsx16(
5894
6300
  WouterLink,
5895
6301
  {
5896
6302
  href,
@@ -5902,7 +6308,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5902
6308
  }
5903
6309
  );
5904
6310
  }
5905
- return /* @__PURE__ */ jsx15(
6311
+ return /* @__PURE__ */ jsx16(
5906
6312
  Component,
5907
6313
  {
5908
6314
  ref: containerRef,
@@ -5918,7 +6324,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5918
6324
  );
5919
6325
  }
5920
6326
  return /* @__PURE__ */ jsxs9("span", { className: `ya-link-wrapper ${wrapperClassName || ""}`, children: [
5921
- /* @__PURE__ */ jsx15(
6327
+ /* @__PURE__ */ jsx16(
5922
6328
  Component,
5923
6329
  {
5924
6330
  ref: containerRef,
@@ -5947,27 +6353,27 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5947
6353
  options: { offset: 6, placement: "top" },
5948
6354
  className: "ya-bubble-menu",
5949
6355
  children: [
5950
- /* @__PURE__ */ jsx15(
6356
+ /* @__PURE__ */ jsx16(
5951
6357
  "button",
5952
6358
  {
5953
6359
  type: "button",
5954
6360
  onClick: () => editor.chain().focus().toggleBold().run(),
5955
6361
  className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
5956
6362
  title: "Bold",
5957
- children: /* @__PURE__ */ jsx15("strong", { children: "B" })
6363
+ children: /* @__PURE__ */ jsx16("strong", { children: "B" })
5958
6364
  }
5959
6365
  ),
5960
- /* @__PURE__ */ jsx15(
6366
+ /* @__PURE__ */ jsx16(
5961
6367
  "button",
5962
6368
  {
5963
6369
  type: "button",
5964
6370
  onClick: () => editor.chain().focus().toggleItalic().run(),
5965
6371
  className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
5966
6372
  title: "Italic",
5967
- children: /* @__PURE__ */ jsx15("em", { children: "I" })
6373
+ children: /* @__PURE__ */ jsx16("em", { children: "I" })
5968
6374
  }
5969
6375
  ),
5970
- /* @__PURE__ */ jsx15("span", { className: "ya-bubble-divider" }),
6376
+ /* @__PURE__ */ jsx16("span", { className: "ya-bubble-divider" }),
5971
6377
  /* @__PURE__ */ jsxs9(
5972
6378
  "select",
5973
6379
  {
@@ -5976,8 +6382,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5976
6382
  className: "ya-bubble-select",
5977
6383
  title: "Font Size",
5978
6384
  children: [
5979
- /* @__PURE__ */ jsx15("option", { value: "", children: "Size" }),
5980
- Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */ jsx15("option", { value: size, children: name }, name))
6385
+ /* @__PURE__ */ jsx16("option", { value: "", children: "Size" }),
6386
+ Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */ jsx16("option", { value: size, children: name }, name))
5981
6387
  ]
5982
6388
  }
5983
6389
  ),
@@ -5989,8 +6395,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
5989
6395
  className: "ya-bubble-select",
5990
6396
  title: "Font Weight",
5991
6397
  children: [
5992
- /* @__PURE__ */ jsx15("option", { value: "", children: "Weight" }),
5993
- Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */ jsx15("option", { value: weight, children: name }, name))
6398
+ /* @__PURE__ */ jsx16("option", { value: "", children: "Weight" }),
6399
+ Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */ jsx16("option", { value: weight, children: name }, name))
5994
6400
  ]
5995
6401
  }
5996
6402
  )
@@ -6000,7 +6406,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6000
6406
  document.body
6001
6407
  ),
6002
6408
  editingMode === "text" ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
6003
- /* @__PURE__ */ jsx15(EditorContent2, { editor }),
6409
+ /* @__PURE__ */ jsx16(EditorContent2, { editor }),
6004
6410
  actionButtonsPos && createPortal6(
6005
6411
  /* @__PURE__ */ jsxs9(
6006
6412
  "div",
@@ -6012,15 +6418,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6012
6418
  right: actionButtonsPos.right
6013
6419
  },
6014
6420
  children: [
6015
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: handleCancelText, className: "ya-link-btn ya-link-btn-cancel", children: "Cancel" }),
6016
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: handleSaveText, className: "ya-link-btn ya-link-btn-save", children: "Save" })
6421
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: handleCancelText, className: "ya-link-btn ya-link-btn-cancel", children: "Cancel" }),
6422
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: handleSaveText, className: "ya-link-btn ya-link-btn-save", children: "Save" })
6017
6423
  ]
6018
6424
  }
6019
6425
  ),
6020
6426
  document.body
6021
6427
  )
6022
- ] }) : /* @__PURE__ */ jsx15(SafeHtml, { content: text2, mode })
6023
- ] }) : /* @__PURE__ */ jsx15(SafeHtml, { content: text2, mode })
6428
+ ] }) : /* @__PURE__ */ jsx16(SafeHtml, { content: text2, mode })
6429
+ ] }) : /* @__PURE__ */ jsx16(SafeHtml, { content: text2, mode })
6024
6430
  }
6025
6431
  ),
6026
6432
  editPopoverMounted && editPopoverPos && createPortal6(
@@ -6038,14 +6444,14 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6038
6444
  onMouseEnter: safeTriangleHandlers.onMouseEnter,
6039
6445
  onMouseLeave: safeTriangleHandlers.onMouseLeave,
6040
6446
  children: [
6041
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: startEditText, children: "Edit text" }),
6042
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: startEditLink, children: "Edit link" })
6447
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: startEditText, children: "Edit text" }),
6448
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: startEditLink, children: "Edit link" })
6043
6449
  ]
6044
6450
  }
6045
6451
  ),
6046
6452
  document.body
6047
6453
  ),
6048
- /* @__PURE__ */ jsx15(
6454
+ /* @__PURE__ */ jsx16(
6049
6455
  SafeTriangleBelow,
6050
6456
  {
6051
6457
  triggerRef,
@@ -6068,7 +6474,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6068
6474
  transform: "translateX(-50%)"
6069
6475
  },
6070
6476
  children: [
6071
- /* @__PURE__ */ jsx15("div", { className: "ya-href-popover-header", children: "Link destination" }),
6477
+ /* @__PURE__ */ jsx16("div", { className: "ya-href-popover-header", children: "Link destination" }),
6072
6478
  !isExternalUrl ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
6073
6479
  sections.length > 0 && /* @__PURE__ */ jsxs9("div", { className: "ya-href-popover-section", children: [
6074
6480
  /* @__PURE__ */ jsxs9(
@@ -6078,14 +6484,14 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6078
6484
  className: "ya-href-popover-label ya-href-collapsible-header",
6079
6485
  onClick: () => setSectionsExpanded(!sectionsExpanded),
6080
6486
  children: [
6081
- /* @__PURE__ */ jsx15("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
6487
+ /* @__PURE__ */ jsx16("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
6082
6488
  "Scroll to section (",
6083
6489
  sections.length,
6084
6490
  ")"
6085
6491
  ]
6086
6492
  }
6087
6493
  ),
6088
- sectionsExpanded && /* @__PURE__ */ jsx15("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs9(
6494
+ sectionsExpanded && /* @__PURE__ */ jsx16("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs9(
6089
6495
  "button",
6090
6496
  {
6091
6497
  type: "button",
@@ -6093,15 +6499,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6093
6499
  onClick: () => handlePageSelect(section.path),
6094
6500
  children: [
6095
6501
  section.label,
6096
- /* @__PURE__ */ jsx15("span", { className: "ya-href-page-path", children: section.path })
6502
+ /* @__PURE__ */ jsx16("span", { className: "ya-href-page-path", children: section.path })
6097
6503
  ]
6098
6504
  },
6099
6505
  section.path
6100
6506
  )) })
6101
6507
  ] }),
6102
6508
  pages.length > 0 && /* @__PURE__ */ jsxs9("div", { className: "ya-href-popover-section", children: [
6103
- /* @__PURE__ */ jsx15("label", { className: "ya-href-popover-label", children: "Navigate to page" }),
6104
- /* @__PURE__ */ jsx15("div", { className: "ya-href-popover-pages", children: pages.map((page) => /* @__PURE__ */ jsxs9(
6509
+ /* @__PURE__ */ jsx16("label", { className: "ya-href-popover-label", children: "Navigate to page" }),
6510
+ /* @__PURE__ */ jsx16("div", { className: "ya-href-popover-pages", children: pages.map((page) => /* @__PURE__ */ jsxs9(
6105
6511
  "button",
6106
6512
  {
6107
6513
  type: "button",
@@ -6109,13 +6515,13 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6109
6515
  onClick: () => handlePageSelect(page.path),
6110
6516
  children: [
6111
6517
  page.label,
6112
- /* @__PURE__ */ jsx15("span", { className: "ya-href-page-path", children: page.path })
6518
+ /* @__PURE__ */ jsx16("span", { className: "ya-href-page-path", children: page.path })
6113
6519
  ]
6114
6520
  },
6115
6521
  page.path
6116
6522
  )) })
6117
6523
  ] }),
6118
- /* @__PURE__ */ jsx15(
6524
+ /* @__PURE__ */ jsx16(
6119
6525
  "button",
6120
6526
  {
6121
6527
  type: "button",
@@ -6129,8 +6535,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6129
6535
  )
6130
6536
  ] }) : /* @__PURE__ */ jsxs9(Fragment4, { children: [
6131
6537
  /* @__PURE__ */ jsxs9("div", { className: "ya-href-popover-section", children: [
6132
- /* @__PURE__ */ jsx15("label", { className: "ya-href-popover-label", children: "External URL" }),
6133
- /* @__PURE__ */ jsx15(
6538
+ /* @__PURE__ */ jsx16("label", { className: "ya-href-popover-label", children: "External URL" }),
6539
+ /* @__PURE__ */ jsx16(
6134
6540
  "input",
6135
6541
  {
6136
6542
  type: "url",
@@ -6142,11 +6548,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6142
6548
  }
6143
6549
  )
6144
6550
  ] }),
6145
- /* @__PURE__ */ jsx15("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
6551
+ /* @__PURE__ */ jsx16("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
6146
6552
  ] }),
6147
6553
  /* @__PURE__ */ jsxs9("div", { className: "ya-href-popover-actions", children: [
6148
- /* @__PURE__ */ jsx15("button", { type: "button", className: "ya-link-btn ya-link-btn-cancel", onClick: handleCancelLink, children: "Cancel" }),
6149
- isExternalUrl ? /* @__PURE__ */ jsx15("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleExternalUrlApply, children: "Apply" }) : /* @__PURE__ */ jsx15("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleSaveLink, children: "Save" })
6554
+ /* @__PURE__ */ jsx16("button", { type: "button", className: "ya-link-btn ya-link-btn-cancel", onClick: handleCancelLink, children: "Cancel" }),
6555
+ isExternalUrl ? /* @__PURE__ */ jsx16("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleExternalUrlApply, children: "Apply" }) : /* @__PURE__ */ jsx16("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleSaveLink, children: "Save" })
6150
6556
  ] })
6151
6557
  ]
6152
6558
  }
@@ -6157,34 +6563,34 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
6157
6563
  }
6158
6564
 
6159
6565
  // src/components/YaContainer.tsx
6160
- import { useCallback as useCallback19, useEffect as useEffect17, useRef as useRef18, useState as useState17 } from "react";
6566
+ import { useCallback as useCallback20, useEffect as useEffect18, useRef as useRef19, useState as useState18 } from "react";
6161
6567
  import { createPortal as createPortal8 } from "react-dom";
6162
6568
 
6163
6569
  // src/components/Tooltip.tsx
6164
- import { useState as useState16, useRef as useRef17, useEffect as useEffect16, useLayoutEffect as useLayoutEffect4, useCallback as useCallback18 } from "react";
6570
+ import { useState as useState17, useRef as useRef18, useEffect as useEffect17, useLayoutEffect as useLayoutEffect4, useCallback as useCallback19 } from "react";
6165
6571
  import { createPortal as createPortal7 } from "react-dom";
6166
6572
 
6167
6573
  // src/components/tooltip.css
6168
6574
  styleInject('.ya-tooltip-trigger {\n display: inline-flex;\n}\n.ya-tooltip-v2 {\n position: fixed;\n z-index: 10000;\n padding: 8px 12px;\n background: #1a1a1a;\n color: white;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n border-radius: 6px;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n animation: ya-tooltip-v2-fade-in 0.15s ease-out;\n}\n@keyframes ya-tooltip-v2-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-tooltip-v2-arrow {\n position: absolute;\n width: 0;\n height: 0;\n left: 50%;\n transform: translateX(-50%);\n}\n.ya-tooltip-v2-bottom .ya-tooltip-v2-arrow {\n top: -6px;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #1a1a1a;\n}\n.ya-tooltip-v2-top .ya-tooltip-v2-arrow {\n bottom: -6px;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-top: 6px solid #1a1a1a;\n}\n.ya-tooltip-v2-left .ya-tooltip-v2-arrow {\n right: -6px;\n left: auto;\n top: 50%;\n transform: translateY(-50%);\n border-top: 6px solid transparent;\n border-bottom: 6px solid transparent;\n border-left: 6px solid #1a1a1a;\n}\n.ya-tooltip-v2-right .ya-tooltip-v2-arrow {\n left: -6px;\n top: 50%;\n transform: translateY(-50%);\n border-top: 6px solid transparent;\n border-bottom: 6px solid transparent;\n border-right: 6px solid #1a1a1a;\n}\n');
6169
6575
 
6170
6576
  // src/components/Tooltip.tsx
6171
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
6577
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
6172
6578
  function Tooltip({
6173
6579
  content,
6174
6580
  children,
6175
6581
  position = "bottom",
6176
6582
  delay = 0
6177
6583
  }) {
6178
- const [isVisible, setIsVisible] = useState16(false);
6179
- const [tooltipPosition, setTooltipPosition] = useState16(null);
6180
- const [isMounted, setIsMounted] = useState16(false);
6181
- const triggerRef = useRef17(null);
6182
- const tooltipRef = useRef17(null);
6183
- const timeoutRef = useRef17(null);
6184
- useEffect16(() => {
6584
+ const [isVisible, setIsVisible] = useState17(false);
6585
+ const [tooltipPosition, setTooltipPosition] = useState17(null);
6586
+ const [isMounted, setIsMounted] = useState17(false);
6587
+ const triggerRef = useRef18(null);
6588
+ const tooltipRef = useRef18(null);
6589
+ const timeoutRef = useRef18(null);
6590
+ useEffect17(() => {
6185
6591
  setIsMounted(true);
6186
6592
  }, []);
6187
- const calculatePosition = useCallback18(() => {
6593
+ const calculatePosition = useCallback19(() => {
6188
6594
  if (!triggerRef.current) return null;
6189
6595
  const triggerRect = triggerRef.current.getBoundingClientRect();
6190
6596
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
@@ -6269,7 +6675,7 @@ function Tooltip({
6269
6675
  setIsVisible(false);
6270
6676
  setTooltipPosition(null);
6271
6677
  };
6272
- useEffect16(() => {
6678
+ useEffect17(() => {
6273
6679
  return () => {
6274
6680
  if (timeoutRef.current) {
6275
6681
  clearTimeout(timeoutRef.current);
@@ -6342,7 +6748,7 @@ function Tooltip({
6342
6748
  role: "tooltip",
6343
6749
  children: [
6344
6750
  content,
6345
- /* @__PURE__ */ jsx16(
6751
+ /* @__PURE__ */ jsx17(
6346
6752
  "div",
6347
6753
  {
6348
6754
  className: "ya-tooltip-v2-arrow",
@@ -6355,7 +6761,7 @@ function Tooltip({
6355
6761
  document.body
6356
6762
  ) : null;
6357
6763
  return /* @__PURE__ */ jsxs10(Fragment5, { children: [
6358
- /* @__PURE__ */ jsx16(
6764
+ /* @__PURE__ */ jsx17(
6359
6765
  "div",
6360
6766
  {
6361
6767
  ref: triggerRef,
@@ -6373,7 +6779,7 @@ function Tooltip({
6373
6779
  styleInject('.ya-container {\n position: relative;\n}\n.ya-container-has-overlay::after {\n content: "";\n position: absolute;\n inset: 0;\n background: var(--ya-overlay-color, transparent);\n opacity: var(--ya-overlay-opacity, 0);\n pointer-events: none;\n z-index: 0;\n}\n.ya-container > *:not(.ya-container-toolbar) {\n position: relative;\n z-index: 1;\n}\n.ya-container-editable {\n transition: outline 0.15s ease;\n pointer-events: none;\n}\n.ya-container-editable > * {\n pointer-events: auto;\n}\n.ya-container-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: -2px;\n}\nbody.builder-selector-active .ya-container-editable:hover {\n outline: none;\n}\n.ya-container-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: -3px;\n}\n.ya-container-toolbar {\n display: flex;\n gap: 4px;\n background: rgba(26, 26, 26, 0.95);\n padding: 6px 8px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: ya-container-toolbar-fade-in 0.15s ease;\n}\n@keyframes ya-container-toolbar-fade-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ya-container-toolbar button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: #3a3a3a;\n border: none;\n border-radius: 6px;\n color: #ffffff;\n cursor: pointer;\n transition: background 0.15s ease, transform 0.1s ease;\n}\n.ya-container-toolbar button:hover {\n background: #4a4a4a;\n transform: scale(1.05);\n}\n.ya-container-toolbar button:active {\n transform: scale(0.98);\n}\n.ya-container-toolbar button.active {\n background: var(--color-primary, #D4A574);\n color: #1a1a1a;\n}\n.ya-container-toolbar button svg {\n width: 18px;\n height: 18px;\n}\n.ya-container-toolbar button[aria-label="Clear background"] {\n background: #3a2a2a;\n}\n.ya-container-toolbar button[aria-label="Clear background"]:hover {\n background: #5a3a3a;\n}\n.ya-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: -3px;\n}\n.ya-container-toolbar button:focus-visible {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: 2px;\n}\n.ya-container-drop-target {\n outline: 2px dashed var(--ya-drop-color, #3b82f6) !important;\n outline-offset: -2px;\n pointer-events: auto !important;\n}\n.ya-container-drop-target .ya-container-toolbar {\n display: none !important;\n}\n.ya-container-drop-hover {\n outline: 3px solid var(--ya-drop-color, #3b82f6) !important;\n outline-offset: -3px;\n}\n.ya-container-drop-hover::before {\n content: "";\n position: absolute;\n inset: 0;\n background: rgba(59, 130, 246, 0.08);\n pointer-events: none;\n z-index: 10;\n animation: ya-container-drop-pulse 1s ease-in-out infinite;\n}\n@keyframes ya-container-drop-pulse {\n 0%, 100% {\n background: rgba(59, 130, 246, 0.05);\n }\n 50% {\n background: rgba(59, 130, 246, 0.12);\n }\n}\n.ya-container-tooltip {\n background: #1a1a1a;\n color: white;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n pointer-events: none;\n animation: ya-container-tooltip-fade-in 0.1s ease;\n}\n@keyframes ya-container-tooltip-fade-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n');
6374
6780
 
6375
6781
  // src/components/YaContainer.tsx
6376
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
6782
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
6377
6783
  function parseBackgroundConfig(value) {
6378
6784
  if (!value) {
6379
6785
  return { type: "none" };
@@ -6415,8 +6821,8 @@ function deriveContainerLabel(element) {
6415
6821
  return tagLabels[tagName] || "Section";
6416
6822
  }
6417
6823
  function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick: _onAIClick, onClearClick, hasBackground }) {
6418
- const [position, setPosition] = useState17(null);
6419
- useEffect17(() => {
6824
+ const [position, setPosition] = useState18(null);
6825
+ useEffect18(() => {
6420
6826
  const updatePosition = () => {
6421
6827
  if (containerRef.current) {
6422
6828
  const rect = containerRef.current.getBoundingClientRect();
@@ -6447,40 +6853,40 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick: _onAICli
6447
6853
  },
6448
6854
  onClick: (e) => e.stopPropagation(),
6449
6855
  children: [
6450
- /* @__PURE__ */ jsx17(Tooltip, { content: "Background Image", position: "bottom", children: /* @__PURE__ */ jsx17(
6856
+ /* @__PURE__ */ jsx18(Tooltip, { content: "Background Image", position: "bottom", children: /* @__PURE__ */ jsx18(
6451
6857
  "button",
6452
6858
  {
6453
6859
  type: "button",
6454
6860
  onClick: onImageClick,
6455
6861
  "aria-label": "Edit background image",
6456
6862
  children: /* @__PURE__ */ jsxs11("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
6457
- /* @__PURE__ */ jsx17("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
6458
- /* @__PURE__ */ jsx17("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
6459
- /* @__PURE__ */ jsx17("polyline", { points: "21 15 16 10 5 21" })
6863
+ /* @__PURE__ */ jsx18("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
6864
+ /* @__PURE__ */ jsx18("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
6865
+ /* @__PURE__ */ jsx18("polyline", { points: "21 15 16 10 5 21" })
6460
6866
  ] })
6461
6867
  }
6462
6868
  ) }),
6463
- /* @__PURE__ */ jsx17(Tooltip, { content: "Background Color", position: "bottom", children: /* @__PURE__ */ jsx17(
6869
+ /* @__PURE__ */ jsx18(Tooltip, { content: "Background Color", position: "bottom", children: /* @__PURE__ */ jsx18(
6464
6870
  "button",
6465
6871
  {
6466
6872
  type: "button",
6467
6873
  onClick: onColorClick,
6468
6874
  "aria-label": "Edit background color",
6469
6875
  children: /* @__PURE__ */ jsxs11("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
6470
- /* @__PURE__ */ jsx17("circle", { cx: "12", cy: "12", r: "10" }),
6471
- /* @__PURE__ */ jsx17("path", { d: "M12 2a10 10 0 0 1 0 20", fill: "currentColor" })
6876
+ /* @__PURE__ */ jsx18("circle", { cx: "12", cy: "12", r: "10" }),
6877
+ /* @__PURE__ */ jsx18("path", { d: "M12 2a10 10 0 0 1 0 20", fill: "currentColor" })
6472
6878
  ] })
6473
6879
  }
6474
6880
  ) }),
6475
- hasBackground && /* @__PURE__ */ jsx17(Tooltip, { content: "Remove Background", position: "bottom", children: /* @__PURE__ */ jsx17(
6881
+ hasBackground && /* @__PURE__ */ jsx18(Tooltip, { content: "Remove Background", position: "bottom", children: /* @__PURE__ */ jsx18(
6476
6882
  "button",
6477
6883
  {
6478
6884
  type: "button",
6479
6885
  onClick: onClearClick,
6480
6886
  "aria-label": "Clear background",
6481
6887
  children: /* @__PURE__ */ jsxs11("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
6482
- /* @__PURE__ */ jsx17("circle", { cx: "12", cy: "12", r: "10" }),
6483
- /* @__PURE__ */ jsx17("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
6888
+ /* @__PURE__ */ jsx18("circle", { cx: "12", cy: "12", r: "10" }),
6889
+ /* @__PURE__ */ jsx18("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
6484
6890
  ] })
6485
6891
  }
6486
6892
  ) })
@@ -6499,13 +6905,13 @@ function YaContainer({
6499
6905
  defaultBackground
6500
6906
  }) {
6501
6907
  const { getValue, setValue, saveToWorker, mode } = useContentStore();
6502
- const containerRef = useRef18(null);
6503
- const [isHovered, setIsHovered] = useState17(false);
6504
- const [isSelected, setIsSelected] = useState17(false);
6505
- const [isDropMode, setIsDropMode] = useState17(false);
6506
- const [isDropHover, setIsDropHover] = useState17(false);
6507
- const [previewConfig, setPreviewConfig] = useState17(null);
6508
- useEffect17(() => {
6908
+ const containerRef = useRef19(null);
6909
+ const [isHovered, setIsHovered] = useState18(false);
6910
+ const [isSelected, setIsSelected] = useState18(false);
6911
+ const [isDropMode, setIsDropMode] = useState18(false);
6912
+ const [isDropHover, setIsDropHover] = useState18(false);
6913
+ const [previewConfig, setPreviewConfig] = useState18(null);
6914
+ useEffect18(() => {
6509
6915
  if (mode !== "inline-edit") return;
6510
6916
  const containerEl = containerRef.current;
6511
6917
  if (!containerEl) return;
@@ -6548,7 +6954,7 @@ function YaContainer({
6548
6954
  overlayCustomProps["--ya-overlay-color"] = displayConfig.overlay.color;
6549
6955
  overlayCustomProps["--ya-overlay-opacity"] = displayConfig.overlay.opacity;
6550
6956
  }
6551
- const handleImageClick = useCallback19(() => {
6957
+ const handleImageClick = useCallback20(() => {
6552
6958
  if (mode !== "inline-edit") return;
6553
6959
  setIsSelected(true);
6554
6960
  const rect = containerRef.current?.getBoundingClientRect();
@@ -6568,7 +6974,7 @@ function YaContainer({
6568
6974
  "*"
6569
6975
  );
6570
6976
  }, [mode, fieldId, backgroundConfig]);
6571
- const handleColorClick = useCallback19(() => {
6977
+ const handleColorClick = useCallback20(() => {
6572
6978
  if (mode !== "inline-edit") return;
6573
6979
  setIsSelected(true);
6574
6980
  const rect = containerRef.current?.getBoundingClientRect();
@@ -6588,7 +6994,7 @@ function YaContainer({
6588
6994
  "*"
6589
6995
  );
6590
6996
  }, [mode, fieldId, backgroundConfig]);
6591
- const handleAIClick = useCallback19(() => {
6997
+ const handleAIClick = useCallback20(() => {
6592
6998
  if (mode !== "inline-edit") return;
6593
6999
  const label = deriveContainerLabel(containerRef.current);
6594
7000
  window.parent.postMessage(
@@ -6601,14 +7007,14 @@ function YaContainer({
6601
7007
  "*"
6602
7008
  );
6603
7009
  }, [mode, fieldId, backgroundConfig]);
6604
- const handleClearClick = useCallback19(() => {
7010
+ const handleClearClick = useCallback20(() => {
6605
7011
  if (mode !== "inline-edit") return;
6606
7012
  const clearedConfig = { type: "none" };
6607
7013
  const serialized = serializeBackgroundConfig(clearedConfig);
6608
7014
  setValue(fieldId, serialized);
6609
7015
  saveToWorker?.(fieldId, serialized);
6610
7016
  }, [mode, fieldId, setValue, saveToWorker]);
6611
- useEffect17(() => {
7017
+ useEffect18(() => {
6612
7018
  if (mode !== "inline-edit") return;
6613
7019
  const handleMessage2 = (event) => {
6614
7020
  if (event.data?.type === "YA_CONTAINER_UPDATE_PREVIEW" && event.data.fieldId === fieldId) {
@@ -6629,7 +7035,7 @@ function YaContainer({
6629
7035
  window.addEventListener("message", handleMessage2);
6630
7036
  return () => window.removeEventListener("message", handleMessage2);
6631
7037
  }, [mode, fieldId]);
6632
- useEffect17(() => {
7038
+ useEffect18(() => {
6633
7039
  if (mode !== "inline-edit") return;
6634
7040
  const handleDropModeMessage = (event) => {
6635
7041
  if (event.data?.type === "DROP_MODE_START") {
@@ -6643,7 +7049,7 @@ function YaContainer({
6643
7049
  window.addEventListener("message", handleDropModeMessage);
6644
7050
  return () => window.removeEventListener("message", handleDropModeMessage);
6645
7051
  }, [mode]);
6646
- const handleDragEnter = useCallback19(
7052
+ const handleDragEnter = useCallback20(
6647
7053
  (e) => {
6648
7054
  if (!isDropMode) return;
6649
7055
  e.preventDefault();
@@ -6667,7 +7073,7 @@ function YaContainer({
6667
7073
  },
6668
7074
  [isDropMode, fieldId]
6669
7075
  );
6670
- const handleDragOver = useCallback19(
7076
+ const handleDragOver = useCallback20(
6671
7077
  (e) => {
6672
7078
  if (!isDropMode) return;
6673
7079
  e.preventDefault();
@@ -6675,7 +7081,7 @@ function YaContainer({
6675
7081
  },
6676
7082
  [isDropMode]
6677
7083
  );
6678
- const handleDragLeave = useCallback19(
7084
+ const handleDragLeave = useCallback20(
6679
7085
  (e) => {
6680
7086
  if (!isDropMode) return;
6681
7087
  e.preventDefault();
@@ -6689,7 +7095,7 @@ function YaContainer({
6689
7095
  },
6690
7096
  [isDropMode]
6691
7097
  );
6692
- const handleDrop = useCallback19(
7098
+ const handleDrop = useCallback20(
6693
7099
  (e) => {
6694
7100
  if (!isDropMode) return;
6695
7101
  e.preventDefault();
@@ -6707,7 +7113,7 @@ function YaContainer({
6707
7113
  },
6708
7114
  [isDropMode, fieldId]
6709
7115
  );
6710
- useEffect17(() => {
7116
+ useEffect18(() => {
6711
7117
  if (!isSelected || mode !== "inline-edit") return;
6712
7118
  let lastRectKey = "";
6713
7119
  let lastTime = 0;
@@ -6742,7 +7148,7 @@ function YaContainer({
6742
7148
  return () => cancelAnimationFrame(rafId);
6743
7149
  }, [isSelected, fieldId, mode]);
6744
7150
  if (mode === "read-only") {
6745
- return /* @__PURE__ */ jsx17(
7151
+ return /* @__PURE__ */ jsx18(
6746
7152
  Tag,
6747
7153
  {
6748
7154
  className: `ya-container ${className || ""}`,
@@ -6785,7 +7191,7 @@ function YaContainer({
6785
7191
  onDrop: handleDrop,
6786
7192
  children: [
6787
7193
  children,
6788
- mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */ jsx17(
7194
+ mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */ jsx18(
6789
7195
  Toolbar,
6790
7196
  {
6791
7197
  containerRef,
@@ -6802,10 +7208,10 @@ function YaContainer({
6802
7208
  }
6803
7209
 
6804
7210
  // src/components/StaticText.tsx
6805
- import { jsx as jsx18 } from "react/jsx-runtime";
7211
+ import { jsx as jsx19 } from "react/jsx-runtime";
6806
7212
  function MpText({ fieldId, className, as: Component = "span", children }) {
6807
7213
  const content = getContent(fieldId) || (typeof children === "string" ? children : "");
6808
- return /* @__PURE__ */ jsx18(
7214
+ return /* @__PURE__ */ jsx19(
6809
7215
  Component,
6810
7216
  {
6811
7217
  className,
@@ -6816,7 +7222,7 @@ function MpText({ fieldId, className, as: Component = "span", children }) {
6816
7222
  }
6817
7223
 
6818
7224
  // src/components/StaticImage.tsx
6819
- import { jsx as jsx19 } from "react/jsx-runtime";
7225
+ import { jsx as jsx20 } from "react/jsx-runtime";
6820
7226
  function parseImageValue2(value) {
6821
7227
  if (!value) {
6822
7228
  return { src: "" };
@@ -6852,7 +7258,7 @@ function MpImage({
6852
7258
  const altText = imageData.alt || alt || fallbackAlt || "";
6853
7259
  const objectFit = imageData.objectFit || propObjectFit || "cover";
6854
7260
  const objectPosition = getObjectPosition3(imageData) || propObjectPosition || "50% 50%";
6855
- return /* @__PURE__ */ jsx19(
7261
+ return /* @__PURE__ */ jsx20(
6856
7262
  "img",
6857
7263
  {
6858
7264
  src: resolveAssetUrl(src),
@@ -6870,7 +7276,7 @@ function MpImage({
6870
7276
 
6871
7277
  // src/components/MarkdownText.tsx
6872
7278
  import { Fragment as Fragment6 } from "react";
6873
- import { jsx as jsx20 } from "react/jsx-runtime";
7279
+ import { jsx as jsx21 } from "react/jsx-runtime";
6874
7280
  function tokenize(text2) {
6875
7281
  const tokens = [];
6876
7282
  let remaining = text2;
@@ -6932,13 +7338,13 @@ function tokensToElements(tokens) {
6932
7338
  return tokens.map((token, index) => {
6933
7339
  switch (token.type) {
6934
7340
  case "text":
6935
- return /* @__PURE__ */ jsx20(Fragment6, { children: token.content }, index);
7341
+ return /* @__PURE__ */ jsx21(Fragment6, { children: token.content }, index);
6936
7342
  case "bold":
6937
- return /* @__PURE__ */ jsx20("strong", { children: token.content }, index);
7343
+ return /* @__PURE__ */ jsx21("strong", { children: token.content }, index);
6938
7344
  case "italic":
6939
- return /* @__PURE__ */ jsx20("em", { children: token.content }, index);
7345
+ return /* @__PURE__ */ jsx21("em", { children: token.content }, index);
6940
7346
  case "link":
6941
- return /* @__PURE__ */ jsx20(
7347
+ return /* @__PURE__ */ jsx21(
6942
7348
  "a",
6943
7349
  {
6944
7350
  href: token.url,
@@ -6950,7 +7356,7 @@ function tokensToElements(tokens) {
6950
7356
  index
6951
7357
  );
6952
7358
  case "newline":
6953
- return /* @__PURE__ */ jsx20("br", {}, index);
7359
+ return /* @__PURE__ */ jsx21("br", {}, index);
6954
7360
  default:
6955
7361
  return null;
6956
7362
  }
@@ -6962,15 +7368,480 @@ function parseMarkdownToElements(content) {
6962
7368
  }
6963
7369
  function MarkdownText({ content, className }) {
6964
7370
  const elements = parseMarkdownToElements(content);
6965
- return /* @__PURE__ */ jsx20("span", { className, children: elements });
7371
+ return /* @__PURE__ */ jsx21("span", { className, children: elements });
7372
+ }
7373
+
7374
+ // src/components/CollectionPage.tsx
7375
+ import { useParams } from "wouter";
7376
+
7377
+ // src/hooks/useCollection.ts
7378
+ import { useState as useState19, useEffect as useEffect19, useCallback as useCallback21, useRef as useRef20 } from "react";
7379
+
7380
+ // src/lib/collection-client.ts
7381
+ function getEnvVar(key) {
7382
+ try {
7383
+ const env = import.meta.env;
7384
+ return env?.[key];
7385
+ } catch {
7386
+ return void 0;
7387
+ }
7388
+ }
7389
+ function getConfig() {
7390
+ if (typeof window === "undefined") {
7391
+ throw new Error("CollectionClient requires browser environment");
7392
+ }
7393
+ const runtimeConfig = window.YOAMIGO_CONFIG;
7394
+ const appId = runtimeConfig?.appId || runtimeConfig?.siteId || getEnvVar("YA_APP_ID") || getEnvVar("YA_SITE_ID");
7395
+ const apiUrl = runtimeConfig?.apiUrl || getEnvVar("YA_API_URL");
7396
+ if (!appId) {
7397
+ throw new Error("App ID not configured (check YOAMIGO_CONFIG.appId or YA_APP_ID)");
7398
+ }
7399
+ if (!apiUrl) {
7400
+ throw new Error("API URL not configured (check YOAMIGO_CONFIG.apiUrl or YA_API_URL)");
7401
+ }
7402
+ return { apiUrl, appId };
7403
+ }
7404
+ var CollectionClient = class {
7405
+ apiUrl;
7406
+ appId;
7407
+ constructor(config) {
7408
+ this.apiUrl = config.apiUrl;
7409
+ this.appId = config.appId;
7410
+ }
7411
+ /**
7412
+ * List records from a collection with optional filtering, pagination, and sorting.
7413
+ */
7414
+ async list(collection, options = {}) {
7415
+ const { filters, limit, offset, orderBy, orderDir } = options;
7416
+ const url = new URL(`${this.apiUrl}/api/apps/${this.appId}/collections/${collection}/records`);
7417
+ if (filters && filters.length > 0) {
7418
+ url.searchParams.set("filters", JSON.stringify(filters));
7419
+ }
7420
+ if (limit !== void 0) {
7421
+ url.searchParams.set("limit", String(limit));
7422
+ }
7423
+ if (offset !== void 0) {
7424
+ url.searchParams.set("offset", String(offset));
7425
+ }
7426
+ if (orderBy) {
7427
+ url.searchParams.set("orderBy", orderBy);
7428
+ }
7429
+ if (orderDir) {
7430
+ url.searchParams.set("orderDir", orderDir);
7431
+ }
7432
+ try {
7433
+ const response = await fetch(url.toString(), {
7434
+ method: "GET",
7435
+ headers: {
7436
+ "Content-Type": "application/json"
7437
+ }
7438
+ });
7439
+ const result = await response.json();
7440
+ if (!response.ok) {
7441
+ return {
7442
+ success: false,
7443
+ error: result.error || `HTTP ${response.status}`,
7444
+ errorCode: result.errorCode
7445
+ };
7446
+ }
7447
+ return {
7448
+ success: true,
7449
+ data: result.data,
7450
+ totalCount: result.totalCount
7451
+ };
7452
+ } catch (error) {
7453
+ return {
7454
+ success: false,
7455
+ error: error instanceof Error ? error.message : "Network error"
7456
+ };
7457
+ }
7458
+ }
7459
+ /**
7460
+ * Get a single record by its ID.
7461
+ */
7462
+ async getById(collection, id) {
7463
+ const url = `${this.apiUrl}/api/apps/${this.appId}/collections/${collection}/records/${id}`;
7464
+ try {
7465
+ const response = await fetch(url, {
7466
+ method: "GET",
7467
+ headers: {
7468
+ "Content-Type": "application/json"
7469
+ }
7470
+ });
7471
+ const result = await response.json();
7472
+ if (!response.ok) {
7473
+ return {
7474
+ success: false,
7475
+ error: result.error || `HTTP ${response.status}`,
7476
+ errorCode: result.errorCode
7477
+ };
7478
+ }
7479
+ return {
7480
+ success: true,
7481
+ data: result.data
7482
+ };
7483
+ } catch (error) {
7484
+ return {
7485
+ success: false,
7486
+ error: error instanceof Error ? error.message : "Network error"
7487
+ };
7488
+ }
7489
+ }
7490
+ /**
7491
+ * Get a single record by a slug field value.
7492
+ * Convenience method that uses list with a filter.
7493
+ */
7494
+ async getBySlug(collection, slugField, slugValue) {
7495
+ const result = await this.list(collection, {
7496
+ filters: [
7497
+ { field: slugField, operator: "eq", value: slugValue }
7498
+ ],
7499
+ limit: 1
7500
+ });
7501
+ if (!result.success) {
7502
+ return {
7503
+ success: false,
7504
+ error: result.error,
7505
+ errorCode: result.errorCode
7506
+ };
7507
+ }
7508
+ if (!result.data || result.data.length === 0) {
7509
+ return {
7510
+ success: false,
7511
+ error: "Record not found",
7512
+ errorCode: "NOT_FOUND"
7513
+ };
7514
+ }
7515
+ return {
7516
+ success: true,
7517
+ data: result.data[0]
7518
+ };
7519
+ }
7520
+ };
7521
+ var cachedClient = null;
7522
+ function getCollectionClient() {
7523
+ if (!cachedClient) {
7524
+ const config = getConfig();
7525
+ cachedClient = new CollectionClient(config);
7526
+ }
7527
+ return cachedClient;
7528
+ }
7529
+ function resetCollectionClient() {
7530
+ cachedClient = null;
7531
+ }
7532
+
7533
+ // src/hooks/useCollection.ts
7534
+ function useCollectionList(options) {
7535
+ const {
7536
+ collection,
7537
+ filters,
7538
+ page = 1,
7539
+ pageSize = 10,
7540
+ orderBy,
7541
+ orderDir,
7542
+ enabled = true
7543
+ } = options;
7544
+ const [data, setData] = useState19(null);
7545
+ const [isLoading, setIsLoading] = useState19(true);
7546
+ const [error, setError] = useState19(null);
7547
+ const [totalCount, setTotalCount] = useState19(0);
7548
+ const [currentPage, setCurrentPage] = useState19(page);
7549
+ const fetchVersion = useRef20(0);
7550
+ const fetchData = useCallback21(async (pageNum) => {
7551
+ if (!enabled) {
7552
+ setIsLoading(false);
7553
+ return;
7554
+ }
7555
+ setIsLoading(true);
7556
+ setError(null);
7557
+ const version = ++fetchVersion.current;
7558
+ try {
7559
+ const client = getCollectionClient();
7560
+ const offset = (pageNum - 1) * pageSize;
7561
+ const result = await client.list(collection, {
7562
+ filters,
7563
+ limit: pageSize,
7564
+ offset,
7565
+ orderBy,
7566
+ orderDir
7567
+ });
7568
+ if (version !== fetchVersion.current) return;
7569
+ if (!result.success) {
7570
+ setError(result.error || "Failed to fetch collection");
7571
+ setData(null);
7572
+ setTotalCount(0);
7573
+ } else {
7574
+ setData(result.data || []);
7575
+ setTotalCount(result.totalCount || 0);
7576
+ setCurrentPage(pageNum);
7577
+ }
7578
+ } catch (err) {
7579
+ if (version !== fetchVersion.current) return;
7580
+ setError(err instanceof Error ? err.message : "Unknown error");
7581
+ setData(null);
7582
+ } finally {
7583
+ if (version === fetchVersion.current) {
7584
+ setIsLoading(false);
7585
+ }
7586
+ }
7587
+ }, [collection, JSON.stringify(filters), pageSize, orderBy, orderDir, enabled]);
7588
+ useEffect19(() => {
7589
+ fetchData(page);
7590
+ }, [fetchData, page]);
7591
+ const totalPages = Math.ceil(totalCount / pageSize);
7592
+ const hasMore = currentPage < totalPages;
7593
+ const refetch = useCallback21(() => {
7594
+ fetchData(currentPage);
7595
+ }, [fetchData, currentPage]);
7596
+ const goToPage = useCallback21((newPage) => {
7597
+ if (newPage >= 1 && newPage <= Math.max(1, totalPages)) {
7598
+ fetchData(newPage);
7599
+ }
7600
+ }, [fetchData, totalPages]);
7601
+ return {
7602
+ data,
7603
+ isLoading,
7604
+ error,
7605
+ totalCount,
7606
+ hasMore,
7607
+ currentPage,
7608
+ totalPages,
7609
+ refetch,
7610
+ goToPage
7611
+ };
7612
+ }
7613
+ function useCollectionRecord(options) {
7614
+ const {
7615
+ collection,
7616
+ slugField,
7617
+ slugValue,
7618
+ enabled = true
7619
+ } = options;
7620
+ const [data, setData] = useState19(null);
7621
+ const [isLoading, setIsLoading] = useState19(true);
7622
+ const [error, setError] = useState19(null);
7623
+ const [notFound, setNotFound] = useState19(false);
7624
+ const fetchVersion = useRef20(0);
7625
+ const fetchData = useCallback21(async () => {
7626
+ if (!enabled || !slugValue) {
7627
+ setIsLoading(false);
7628
+ return;
7629
+ }
7630
+ setIsLoading(true);
7631
+ setError(null);
7632
+ setNotFound(false);
7633
+ const version = ++fetchVersion.current;
7634
+ try {
7635
+ const client = getCollectionClient();
7636
+ const result = await client.getBySlug(
7637
+ collection,
7638
+ slugField,
7639
+ slugValue
7640
+ );
7641
+ if (version !== fetchVersion.current) return;
7642
+ if (!result.success) {
7643
+ if (result.errorCode === "NOT_FOUND") {
7644
+ setNotFound(true);
7645
+ setData(null);
7646
+ } else {
7647
+ setError(result.error || "Failed to fetch record");
7648
+ setData(null);
7649
+ }
7650
+ } else {
7651
+ setData(result.data || null);
7652
+ }
7653
+ } catch (err) {
7654
+ if (version !== fetchVersion.current) return;
7655
+ setError(err instanceof Error ? err.message : "Unknown error");
7656
+ setData(null);
7657
+ } finally {
7658
+ if (version === fetchVersion.current) {
7659
+ setIsLoading(false);
7660
+ }
7661
+ }
7662
+ }, [collection, slugField, slugValue, enabled]);
7663
+ useEffect19(() => {
7664
+ fetchData();
7665
+ }, [fetchData]);
7666
+ const refetch = useCallback21(() => {
7667
+ fetchData();
7668
+ }, [fetchData]);
7669
+ return {
7670
+ data,
7671
+ isLoading,
7672
+ error,
7673
+ notFound,
7674
+ refetch
7675
+ };
7676
+ }
7677
+
7678
+ // src/components/CollectionPage.tsx
7679
+ function CollectionListPage({
7680
+ collection,
7681
+ pageSize = 10,
7682
+ page = 1,
7683
+ filters,
7684
+ orderBy,
7685
+ orderDir,
7686
+ enabled = true,
7687
+ render
7688
+ }) {
7689
+ const result = useCollectionList({
7690
+ collection,
7691
+ pageSize,
7692
+ page,
7693
+ filters,
7694
+ orderBy,
7695
+ orderDir,
7696
+ enabled
7697
+ });
7698
+ return render(result);
7699
+ }
7700
+ function CollectionDetailPage({
7701
+ collection,
7702
+ slugField = "slug",
7703
+ slugParam = "slug",
7704
+ slug: slugOverride,
7705
+ enabled = true,
7706
+ render
7707
+ }) {
7708
+ const params = useParams();
7709
+ const slug = slugOverride || params[slugParam] || "";
7710
+ const result = useCollectionRecord({
7711
+ collection,
7712
+ slugField,
7713
+ slugValue: slug,
7714
+ enabled: enabled && Boolean(slug)
7715
+ });
7716
+ return render({
7717
+ ...result,
7718
+ slug
7719
+ });
7720
+ }
7721
+
7722
+ // src/components/CollectionList.tsx
7723
+ import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
7724
+ function CollectionList({
7725
+ collection,
7726
+ prefix,
7727
+ filters,
7728
+ page,
7729
+ pageSize,
7730
+ orderBy,
7731
+ orderDir,
7732
+ children,
7733
+ skeleton,
7734
+ empty,
7735
+ error,
7736
+ appId,
7737
+ enabled = true,
7738
+ pagination,
7739
+ wrapper: Wrapper
7740
+ }) {
7741
+ const result = useCollectionList({
7742
+ collection,
7743
+ filters,
7744
+ page,
7745
+ pageSize,
7746
+ orderBy,
7747
+ orderDir,
7748
+ enabled
7749
+ });
7750
+ if (result.isLoading) {
7751
+ const skeletonCount = pageSize || 10;
7752
+ const skeletonItems = Array.from(
7753
+ { length: skeletonCount },
7754
+ (_, index) => skeleton({ index })
7755
+ );
7756
+ return Wrapper ? /* @__PURE__ */ jsx22(Wrapper, { children: skeletonItems }) : /* @__PURE__ */ jsx22(Fragment7, { children: skeletonItems });
7757
+ }
7758
+ if (result.error) {
7759
+ return error?.(result.error) ?? null;
7760
+ }
7761
+ if (!result.data || result.data.length === 0) {
7762
+ return empty ?? null;
7763
+ }
7764
+ const items = result.data.map((record, index) => {
7765
+ const fieldPrefix = `${prefix}.${record.id}`;
7766
+ return /* @__PURE__ */ jsx22(
7767
+ CollectionContentProvider,
7768
+ {
7769
+ record: record.data,
7770
+ prefix: fieldPrefix,
7771
+ recordId: record.id,
7772
+ collectionSlug: collection,
7773
+ appId,
7774
+ children: children({ record, index, fieldPrefix })
7775
+ },
7776
+ record.id
7777
+ );
7778
+ });
7779
+ const content = Wrapper ? /* @__PURE__ */ jsx22(Wrapper, { children: items }) : /* @__PURE__ */ jsx22(Fragment7, { children: items });
7780
+ if (pagination) {
7781
+ return /* @__PURE__ */ jsxs12(Fragment7, { children: [
7782
+ content,
7783
+ pagination({
7784
+ currentPage: result.currentPage,
7785
+ totalPages: result.totalPages,
7786
+ totalCount: result.totalCount,
7787
+ hasMore: result.hasMore,
7788
+ goToPage: result.goToPage
7789
+ })
7790
+ ] });
7791
+ }
7792
+ return content;
7793
+ }
7794
+
7795
+ // src/components/CollectionItem.tsx
7796
+ import { jsx as jsx23 } from "react/jsx-runtime";
7797
+ function CollectionItem({
7798
+ collection,
7799
+ prefix,
7800
+ slugField = "slug",
7801
+ slugValue,
7802
+ children,
7803
+ skeleton,
7804
+ appId,
7805
+ enabled = true
7806
+ }) {
7807
+ const result = useCollectionRecord({
7808
+ collection,
7809
+ slugField,
7810
+ slugValue,
7811
+ enabled: enabled && Boolean(slugValue)
7812
+ });
7813
+ const renderProps = {
7814
+ record: result.data,
7815
+ isLoading: result.isLoading,
7816
+ notFound: result.notFound,
7817
+ error: result.error,
7818
+ refetch: result.refetch
7819
+ };
7820
+ if (result.isLoading) {
7821
+ return skeleton;
7822
+ }
7823
+ if (result.error || result.notFound || !result.data) {
7824
+ return children(renderProps);
7825
+ }
7826
+ return /* @__PURE__ */ jsx23(
7827
+ CollectionContentProvider,
7828
+ {
7829
+ record: result.data.data,
7830
+ prefix,
7831
+ recordId: result.data.id,
7832
+ collectionSlug: collection,
7833
+ appId,
7834
+ children: children(renderProps)
7835
+ }
7836
+ );
6966
7837
  }
6967
7838
 
6968
7839
  // src/router/Link.tsx
6969
7840
  import { Link as WouterLink2 } from "wouter";
6970
- import { jsx as jsx21 } from "react/jsx-runtime";
7841
+ import { jsx as jsx24 } from "react/jsx-runtime";
6971
7842
  function Link2({ to, href, children, className, onClick, replace, ...props }) {
6972
7843
  const target = href ?? to ?? "/";
6973
- return /* @__PURE__ */ jsx21(WouterLink2, { href: target, className, onClick, replace, ...props, children });
7844
+ return /* @__PURE__ */ jsx24(WouterLink2, { href: target, className, onClick, replace, ...props, children });
6974
7845
  }
6975
7846
 
6976
7847
  // src/router/useNavigate.ts
@@ -6989,7 +7860,7 @@ function useNavigate() {
6989
7860
 
6990
7861
  // src/router/Router.tsx
6991
7862
  import { Router as WouterRouter } from "wouter";
6992
- import { jsx as jsx22 } from "react/jsx-runtime";
7863
+ import { jsx as jsx25 } from "react/jsx-runtime";
6993
7864
  function detectBasename() {
6994
7865
  if (typeof window === "undefined") return "";
6995
7866
  const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
@@ -7004,11 +7875,11 @@ function detectBasename() {
7004
7875
  }
7005
7876
  function Router({ children, base }) {
7006
7877
  const basename = base ?? detectBasename();
7007
- return /* @__PURE__ */ jsx22(WouterRouter, { base: basename, children });
7878
+ return /* @__PURE__ */ jsx25(WouterRouter, { base: basename, children });
7008
7879
  }
7009
7880
 
7010
7881
  // src/router/ScrollRestoration.tsx
7011
- import { useEffect as useEffect18, useRef as useRef19 } from "react";
7882
+ import { useEffect as useEffect20, useRef as useRef21 } from "react";
7012
7883
  import { useLocation as useLocation3 } from "wouter";
7013
7884
  var SCROLL_POSITIONS_KEY = "yoamigo-scroll-positions";
7014
7885
  var HISTORY_INDEX_KEY = "yoamigo-history-index";
@@ -7044,10 +7915,10 @@ function setHistoryIndex(index) {
7044
7915
  var globalHistoryIndex = 0;
7045
7916
  function ScrollRestoration() {
7046
7917
  const [location] = useLocation3();
7047
- const previousLocation = useRef19(location);
7048
- const isPopState = useRef19(false);
7049
- const scrollPositionsRef = useRef19({});
7050
- useEffect18(() => {
7918
+ const previousLocation = useRef21(location);
7919
+ const isPopState = useRef21(false);
7920
+ const scrollPositionsRef = useRef21({});
7921
+ useEffect20(() => {
7051
7922
  if (typeof history !== "undefined" && "scrollRestoration" in history) {
7052
7923
  history.scrollRestoration = "manual";
7053
7924
  }
@@ -7065,7 +7936,7 @@ function ScrollRestoration() {
7065
7936
  window.addEventListener("popstate", handlePopState);
7066
7937
  return () => window.removeEventListener("popstate", handlePopState);
7067
7938
  }, []);
7068
- useEffect18(() => {
7939
+ useEffect20(() => {
7069
7940
  if (previousLocation.current === location) return;
7070
7941
  const prevHistoryIndex = globalHistoryIndex;
7071
7942
  const currentScrollY = window.scrollY;
@@ -7085,7 +7956,7 @@ function ScrollRestoration() {
7085
7956
  }
7086
7957
  previousLocation.current = location;
7087
7958
  }, [location]);
7088
- useEffect18(() => {
7959
+ useEffect20(() => {
7089
7960
  let timeoutId;
7090
7961
  const handleScroll = () => {
7091
7962
  clearTimeout(timeoutId);
@@ -7104,7 +7975,74 @@ function ScrollRestoration() {
7104
7975
  }
7105
7976
 
7106
7977
  // src/router/index.ts
7107
- import { Route, Switch, useParams } from "wouter";
7978
+ import { Route, Switch, useParams as useParams2, useLocation as useLocation4 } from "wouter";
7979
+
7980
+ // src/router/route-utils.ts
7981
+ function filePathToRoutePath(filePath, options = {}) {
7982
+ const {
7983
+ pagesDir = "/src/pages",
7984
+ extensions = [".tsx", ".ts", ".jsx", ".js"]
7985
+ } = options;
7986
+ let path = filePath;
7987
+ if (path.startsWith(pagesDir)) {
7988
+ path = path.slice(pagesDir.length);
7989
+ }
7990
+ for (const ext of extensions) {
7991
+ if (path.endsWith(ext)) {
7992
+ path = path.slice(0, -ext.length);
7993
+ break;
7994
+ }
7995
+ }
7996
+ if (path.endsWith("/index")) {
7997
+ path = path.slice(0, -6) || "/";
7998
+ }
7999
+ path = path.replace(/\[\.\.\.([^\]]+)\]/g, ":$1*");
8000
+ path = path.replace(/\[([^\]]+)\]/g, ":$1");
8001
+ if (!path.startsWith("/")) {
8002
+ path = "/" + path;
8003
+ }
8004
+ if (path === "" || path === "/index") {
8005
+ return "/";
8006
+ }
8007
+ return path;
8008
+ }
8009
+ function extractRouteParams(filePath) {
8010
+ const matches = filePath.matchAll(/\[\.\.\.([^\]]+)\]|\[([^\]]+)\]/g);
8011
+ const params = [];
8012
+ for (const match of matches) {
8013
+ params.push(match[1] || match[2]);
8014
+ }
8015
+ return params;
8016
+ }
8017
+ function createRouteDefinition(filePath, options) {
8018
+ const path = filePathToRoutePath(filePath, options);
8019
+ const params = extractRouteParams(filePath);
8020
+ return {
8021
+ path,
8022
+ filePath,
8023
+ params,
8024
+ isDynamic: params.length > 0
8025
+ };
8026
+ }
8027
+ function sortRoutesBySpecificity(routes) {
8028
+ return [...routes].sort((a, b) => {
8029
+ if (!a.isDynamic && b.isDynamic) return -1;
8030
+ if (a.isDynamic && !b.isDynamic) return 1;
8031
+ const aSegments = a.path.split("/").filter(Boolean);
8032
+ const bSegments = b.path.split("/").filter(Boolean);
8033
+ if (aSegments.length !== bSegments.length) {
8034
+ return bSegments.length - aSegments.length;
8035
+ }
8036
+ return a.params.length - b.params.length;
8037
+ });
8038
+ }
8039
+ function generatePath(routePath, params) {
8040
+ let path = routePath;
8041
+ for (const [key, value] of Object.entries(params)) {
8042
+ path = path.replace(new RegExp(`:${key}\\*?`, "g"), encodeURIComponent(value));
8043
+ }
8044
+ return path;
8045
+ }
7108
8046
 
7109
8047
  // src/lib/content-helpers.ts
7110
8048
  function text(content) {
@@ -7122,8 +8060,952 @@ function video(config) {
7122
8060
  function embed(config) {
7123
8061
  return JSON.stringify(config);
7124
8062
  }
8063
+
8064
+ // src/contexts/CartContext.tsx
8065
+ import { createContext as createContext5, useContext as useContext5, useEffect as useEffect22 } from "react";
8066
+
8067
+ // src/hooks/useCart.ts
8068
+ import { useState as useState20, useEffect as useEffect21, useCallback as useCallback22, useRef as useRef22 } from "react";
8069
+
8070
+ // src/lib/cart-storage.ts
8071
+ var CART_STORAGE_KEY_PREFIX = "yoamigo_cart_";
8072
+ var SESSION_ID_KEY = "yoamigo_cart_session";
8073
+ var CART_EXPIRY_DAYS = 7;
8074
+ function generateSessionId() {
8075
+ return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
8076
+ }
8077
+ function getSessionId() {
8078
+ if (typeof window === "undefined") {
8079
+ throw new Error("getSessionId requires browser environment");
8080
+ }
8081
+ let sessionId = localStorage.getItem(SESSION_ID_KEY);
8082
+ if (!sessionId) {
8083
+ sessionId = generateSessionId();
8084
+ localStorage.setItem(SESSION_ID_KEY, sessionId);
8085
+ }
8086
+ return sessionId;
8087
+ }
8088
+ function clearSessionId() {
8089
+ if (typeof window === "undefined") return;
8090
+ localStorage.removeItem(SESSION_ID_KEY);
8091
+ }
8092
+ function getStorageKey(appId) {
8093
+ return `${CART_STORAGE_KEY_PREFIX}${appId}`;
8094
+ }
8095
+ function getLocalCart(appId) {
8096
+ if (typeof window === "undefined") return null;
8097
+ try {
8098
+ const key = getStorageKey(appId);
8099
+ const data = localStorage.getItem(key);
8100
+ if (!data) return null;
8101
+ const cart = JSON.parse(data);
8102
+ const updatedAt = new Date(cart.updatedAt);
8103
+ const expiryDate = /* @__PURE__ */ new Date();
8104
+ expiryDate.setDate(expiryDate.getDate() - CART_EXPIRY_DAYS);
8105
+ if (updatedAt < expiryDate) {
8106
+ localStorage.removeItem(key);
8107
+ return null;
8108
+ }
8109
+ return cart;
8110
+ } catch (error) {
8111
+ console.warn("Failed to read cart from localStorage:", error);
8112
+ return null;
8113
+ }
8114
+ }
8115
+ function saveLocalCart(appId, items) {
8116
+ if (typeof window === "undefined") return;
8117
+ try {
8118
+ const key = getStorageKey(appId);
8119
+ const cart = {
8120
+ sessionId: getSessionId(),
8121
+ items,
8122
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
8123
+ };
8124
+ localStorage.setItem(key, JSON.stringify(cart));
8125
+ } catch (error) {
8126
+ console.warn("Failed to save cart to localStorage:", error);
8127
+ }
8128
+ }
8129
+ function clearLocalCart(appId) {
8130
+ if (typeof window === "undefined") return;
8131
+ try {
8132
+ const key = getStorageKey(appId);
8133
+ localStorage.removeItem(key);
8134
+ } catch (error) {
8135
+ console.warn("Failed to clear cart from localStorage:", error);
8136
+ }
8137
+ }
8138
+ function getLocalCartItems(appId) {
8139
+ const cart = getLocalCart(appId);
8140
+ return cart?.items || [];
8141
+ }
8142
+ function addLocalCartItem(appId, productId, collectionSlug, quantity = 1, variantId, data) {
8143
+ const items = getLocalCartItems(appId);
8144
+ const existingIndex = items.findIndex(
8145
+ (item) => item.productId === productId && item.variantId === variantId
8146
+ );
8147
+ if (existingIndex >= 0) {
8148
+ items[existingIndex].quantity += quantity;
8149
+ } else {
8150
+ items.push({
8151
+ id: `local_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
8152
+ productId,
8153
+ collectionSlug,
8154
+ quantity,
8155
+ variantId,
8156
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
8157
+ data
8158
+ });
8159
+ }
8160
+ saveLocalCart(appId, items);
8161
+ return items;
8162
+ }
8163
+ function updateLocalCartItem(appId, itemId, quantity) {
8164
+ const items = getLocalCartItems(appId);
8165
+ const itemIndex = items.findIndex((item) => item.id === itemId);
8166
+ if (itemIndex < 0) return items;
8167
+ if (quantity === 0) {
8168
+ items.splice(itemIndex, 1);
8169
+ } else {
8170
+ items[itemIndex].quantity = quantity;
8171
+ }
8172
+ saveLocalCart(appId, items);
8173
+ return items;
8174
+ }
8175
+ function removeLocalCartItem(appId, itemId) {
8176
+ const items = getLocalCartItems(appId);
8177
+ const filteredItems = items.filter((item) => item.id !== itemId);
8178
+ saveLocalCart(appId, filteredItems);
8179
+ return filteredItems;
8180
+ }
8181
+ function getLocalCartItemCount(appId) {
8182
+ const items = getLocalCartItems(appId);
8183
+ return items.reduce((sum, item) => sum + item.quantity, 0);
8184
+ }
8185
+
8186
+ // src/hooks/useCart.ts
8187
+ function getConfig2(options) {
8188
+ if (typeof window === "undefined") {
8189
+ throw new Error("useCart requires browser environment");
8190
+ }
8191
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8192
+ const appId = options.appId || runtimeConfig?.appId;
8193
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8194
+ if (!appId) {
8195
+ throw new Error("App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)");
8196
+ }
8197
+ if (!apiUrl) {
8198
+ throw new Error("API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)");
8199
+ }
8200
+ return { appId, apiUrl };
8201
+ }
8202
+ function useCart(options = {}) {
8203
+ const { userToken } = options;
8204
+ const [items, setItems] = useState20([]);
8205
+ const [isLoading, setIsLoading] = useState20(true);
8206
+ const [error, setError] = useState20(null);
8207
+ const fetchVersion = useRef22(0);
8208
+ const configRef = useRef22(null);
8209
+ if (!configRef.current && typeof window !== "undefined") {
8210
+ try {
8211
+ configRef.current = getConfig2(options);
8212
+ } catch {
8213
+ }
8214
+ }
8215
+ const isAuthenticated = !!userToken;
8216
+ const sessionId = typeof window !== "undefined" ? getSessionId() : null;
8217
+ const apiCall = useCallback22(async (endpoint, method = "GET", body) => {
8218
+ const config = configRef.current;
8219
+ if (!config) throw new Error("Cart not configured");
8220
+ const headers = {
8221
+ "Content-Type": "application/json"
8222
+ };
8223
+ if (isAuthenticated) {
8224
+ headers["X-App-User-Token"] = userToken;
8225
+ } else if (sessionId) {
8226
+ headers["X-Session-Id"] = sessionId;
8227
+ }
8228
+ const response = await fetch(
8229
+ `${config.apiUrl}/api/apps/${config.appId}/cart${endpoint}`,
8230
+ {
8231
+ method,
8232
+ headers,
8233
+ body: body ? JSON.stringify(body) : void 0
8234
+ }
8235
+ );
8236
+ return response.json();
8237
+ }, [userToken, isAuthenticated, sessionId]);
8238
+ const fetchCart = useCallback22(async () => {
8239
+ const config = configRef.current;
8240
+ if (!config) {
8241
+ setIsLoading(false);
8242
+ setError("Cart not configured");
8243
+ return;
8244
+ }
8245
+ const version = ++fetchVersion.current;
8246
+ setIsLoading(true);
8247
+ setError(null);
8248
+ try {
8249
+ if (isAuthenticated || sessionId) {
8250
+ const result = await apiCall("");
8251
+ if (version !== fetchVersion.current) return;
8252
+ if (result.success && result.data) {
8253
+ setItems(result.data.items);
8254
+ } else {
8255
+ if (!isAuthenticated) {
8256
+ setItems(getLocalCartItems(config.appId));
8257
+ } else {
8258
+ setError(result.error || "Failed to fetch cart");
8259
+ }
8260
+ }
8261
+ } else {
8262
+ setItems(getLocalCartItems(config.appId));
8263
+ }
8264
+ } catch (err) {
8265
+ if (version !== fetchVersion.current) return;
8266
+ if (!isAuthenticated) {
8267
+ setItems(getLocalCartItems(config.appId));
8268
+ } else {
8269
+ setError(err instanceof Error ? err.message : "Failed to fetch cart");
8270
+ }
8271
+ } finally {
8272
+ if (version === fetchVersion.current) {
8273
+ setIsLoading(false);
8274
+ }
8275
+ }
8276
+ }, [apiCall, isAuthenticated, sessionId]);
8277
+ useEffect21(() => {
8278
+ fetchCart();
8279
+ }, [fetchCart]);
8280
+ const addItem = useCallback22(async (productId, collectionSlug, quantity = 1, variantId, data) => {
8281
+ const config = configRef.current;
8282
+ if (!config) throw new Error("Cart not configured");
8283
+ setError(null);
8284
+ try {
8285
+ if (isAuthenticated || sessionId) {
8286
+ const result = await apiCall("/items", "POST", {
8287
+ productId,
8288
+ collectionSlug,
8289
+ quantity,
8290
+ variantId,
8291
+ data
8292
+ });
8293
+ if (result.success && result.data) {
8294
+ setItems(result.data.items);
8295
+ } else {
8296
+ throw new Error(result.error || "Failed to add item");
8297
+ }
8298
+ } else {
8299
+ const newItems = addLocalCartItem(config.appId, productId, collectionSlug, quantity, variantId, data);
8300
+ setItems(newItems);
8301
+ }
8302
+ } catch (err) {
8303
+ const message = err instanceof Error ? err.message : "Failed to add item";
8304
+ setError(message);
8305
+ throw err;
8306
+ }
8307
+ }, [apiCall, isAuthenticated, sessionId]);
8308
+ const updateQuantity = useCallback22(async (itemId, quantity) => {
8309
+ const config = configRef.current;
8310
+ if (!config) throw new Error("Cart not configured");
8311
+ setError(null);
8312
+ try {
8313
+ if (isAuthenticated || sessionId) {
8314
+ const result = await apiCall(`/items/${itemId}`, "PATCH", { quantity });
8315
+ if (result.success && result.data) {
8316
+ setItems(result.data.items);
8317
+ } else {
8318
+ throw new Error(result.error || "Failed to update item");
8319
+ }
8320
+ } else {
8321
+ const newItems = updateLocalCartItem(config.appId, itemId, quantity);
8322
+ setItems(newItems);
8323
+ }
8324
+ } catch (err) {
8325
+ const message = err instanceof Error ? err.message : "Failed to update item";
8326
+ setError(message);
8327
+ throw err;
8328
+ }
8329
+ }, [apiCall, isAuthenticated, sessionId]);
8330
+ const removeItem = useCallback22(async (itemId) => {
8331
+ const config = configRef.current;
8332
+ if (!config) throw new Error("Cart not configured");
8333
+ setError(null);
8334
+ try {
8335
+ if (isAuthenticated || sessionId) {
8336
+ const result = await apiCall(`/items/${itemId}`, "DELETE");
8337
+ if (result.success && result.data) {
8338
+ setItems(result.data.items);
8339
+ } else {
8340
+ throw new Error(result.error || "Failed to remove item");
8341
+ }
8342
+ } else {
8343
+ const newItems = removeLocalCartItem(config.appId, itemId);
8344
+ setItems(newItems);
8345
+ }
8346
+ } catch (err) {
8347
+ const message = err instanceof Error ? err.message : "Failed to remove item";
8348
+ setError(message);
8349
+ throw err;
8350
+ }
8351
+ }, [apiCall, isAuthenticated, sessionId]);
8352
+ const clearCart = useCallback22(async () => {
8353
+ const config = configRef.current;
8354
+ if (!config) throw new Error("Cart not configured");
8355
+ setError(null);
8356
+ try {
8357
+ if (isAuthenticated || sessionId) {
8358
+ const result = await apiCall("", "DELETE");
8359
+ if (result.success) {
8360
+ setItems([]);
8361
+ } else {
8362
+ throw new Error(result.error || "Failed to clear cart");
8363
+ }
8364
+ } else {
8365
+ clearLocalCart(config.appId);
8366
+ setItems([]);
8367
+ }
8368
+ } catch (err) {
8369
+ const message = err instanceof Error ? err.message : "Failed to clear cart";
8370
+ setError(message);
8371
+ throw err;
8372
+ }
8373
+ }, [apiCall, isAuthenticated, sessionId]);
8374
+ const mergeGuestCart = useCallback22(async () => {
8375
+ if (!isAuthenticated || !sessionId) return;
8376
+ setError(null);
8377
+ try {
8378
+ const result = await apiCall("/merge", "POST", {
8379
+ guestSessionId: sessionId,
8380
+ mergeStrategy: "sum"
8381
+ });
8382
+ if (result.success && result.data) {
8383
+ setItems(result.data.items);
8384
+ if (configRef.current) {
8385
+ clearLocalCart(configRef.current.appId);
8386
+ }
8387
+ } else {
8388
+ throw new Error(result.error || "Failed to merge cart");
8389
+ }
8390
+ } catch (err) {
8391
+ const message = err instanceof Error ? err.message : "Failed to merge cart";
8392
+ setError(message);
8393
+ }
8394
+ }, [apiCall, isAuthenticated, sessionId]);
8395
+ const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);
8396
+ return {
8397
+ items,
8398
+ itemCount,
8399
+ isLoading,
8400
+ error,
8401
+ addItem,
8402
+ updateQuantity,
8403
+ removeItem,
8404
+ clearCart,
8405
+ mergeGuestCart,
8406
+ refresh: fetchCart
8407
+ };
8408
+ }
8409
+
8410
+ // src/contexts/CartContext.tsx
8411
+ import { jsx as jsx26 } from "react/jsx-runtime";
8412
+ var CartContext = createContext5(null);
8413
+ function CartProvider({
8414
+ children,
8415
+ userToken,
8416
+ onUserTokenChange,
8417
+ ...options
8418
+ }) {
8419
+ const cart = useCart({ ...options, userToken });
8420
+ useEffect22(() => {
8421
+ if (userToken) {
8422
+ cart.mergeGuestCart();
8423
+ }
8424
+ onUserTokenChange?.(!!userToken);
8425
+ }, [userToken]);
8426
+ return /* @__PURE__ */ jsx26(CartContext.Provider, { value: cart, children });
8427
+ }
8428
+ function useCartContext() {
8429
+ const context = useContext5(CartContext);
8430
+ if (!context) {
8431
+ throw new Error("useCartContext must be used within a CartProvider");
8432
+ }
8433
+ return context;
8434
+ }
8435
+ function useOptionalCartContext() {
8436
+ return useContext5(CartContext);
8437
+ }
8438
+
8439
+ // src/hooks/useCheckout.ts
8440
+ import { useState as useState21, useCallback as useCallback23, useRef as useRef23 } from "react";
8441
+ function getConfig3(options) {
8442
+ if (typeof window === "undefined") {
8443
+ throw new Error("useCheckout requires browser environment");
8444
+ }
8445
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8446
+ const appId = options.appId || runtimeConfig?.appId;
8447
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8448
+ if (!appId) {
8449
+ throw new Error("App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)");
8450
+ }
8451
+ if (!apiUrl) {
8452
+ throw new Error("API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)");
8453
+ }
8454
+ return { appId, apiUrl };
8455
+ }
8456
+ function useCheckout(options = {}) {
8457
+ const { userToken } = options;
8458
+ const [isLoading, setIsLoading] = useState21(false);
8459
+ const [error, setError] = useState21(null);
8460
+ const configRef = useRef23(null);
8461
+ if (!configRef.current && typeof window !== "undefined") {
8462
+ try {
8463
+ configRef.current = getConfig3(options);
8464
+ } catch {
8465
+ }
8466
+ }
8467
+ const isAuthenticated = !!userToken;
8468
+ const sessionId = typeof window !== "undefined" ? getSessionId() : null;
8469
+ const initiateCheckout = useCallback23(async (checkoutOptions) => {
8470
+ const config = configRef.current;
8471
+ if (!config) {
8472
+ throw new Error("Checkout not configured");
8473
+ }
8474
+ setIsLoading(true);
8475
+ setError(null);
8476
+ try {
8477
+ const headers = {
8478
+ "Content-Type": "application/json"
8479
+ };
8480
+ if (isAuthenticated) {
8481
+ headers["X-App-User-Token"] = userToken;
8482
+ } else if (sessionId) {
8483
+ headers["X-Session-Id"] = sessionId;
8484
+ }
8485
+ const response = await fetch(
8486
+ `${config.apiUrl}/api/apps/${config.appId}/checkout/session`,
8487
+ {
8488
+ method: "POST",
8489
+ headers,
8490
+ body: JSON.stringify(checkoutOptions)
8491
+ }
8492
+ );
8493
+ const result = await response.json();
8494
+ if (!result.success || !result.data) {
8495
+ throw new Error(result.error || "Failed to create checkout session");
8496
+ }
8497
+ return result.data;
8498
+ } catch (err) {
8499
+ const message = err instanceof Error ? err.message : "Failed to initiate checkout";
8500
+ setError(message);
8501
+ throw err;
8502
+ } finally {
8503
+ setIsLoading(false);
8504
+ }
8505
+ }, [userToken, isAuthenticated, sessionId]);
8506
+ return {
8507
+ initiateCheckout,
8508
+ isLoading,
8509
+ error
8510
+ };
8511
+ }
8512
+ function useCheckoutStatus(options) {
8513
+ const { userToken, sessionId: checkoutSessionId, poll = false, pollInterval = 2e3 } = options;
8514
+ const [status, setStatus] = useState21(null);
8515
+ const [isLoading, setIsLoading] = useState21(true);
8516
+ const [error, setError] = useState21(null);
8517
+ const configRef = useRef23(null);
8518
+ if (!configRef.current && typeof window !== "undefined") {
8519
+ try {
8520
+ configRef.current = getConfig3(options);
8521
+ } catch {
8522
+ }
8523
+ }
8524
+ const isAuthenticated = !!userToken;
8525
+ const guestSessionId = typeof window !== "undefined" ? getSessionId() : null;
8526
+ const fetchStatus = useCallback23(async () => {
8527
+ const config = configRef.current;
8528
+ if (!config || !checkoutSessionId) {
8529
+ setIsLoading(false);
8530
+ return;
8531
+ }
8532
+ try {
8533
+ const headers = {
8534
+ "Content-Type": "application/json"
8535
+ };
8536
+ if (isAuthenticated) {
8537
+ headers["X-App-User-Token"] = userToken;
8538
+ } else if (guestSessionId) {
8539
+ headers["X-Session-Id"] = guestSessionId;
8540
+ }
8541
+ const response = await fetch(
8542
+ `${config.apiUrl}/api/apps/${config.appId}/checkout/session/${checkoutSessionId}/status`,
8543
+ { headers }
8544
+ );
8545
+ const result = await response.json();
8546
+ if (result.success && result.data) {
8547
+ setStatus(result.data);
8548
+ setError(null);
8549
+ } else {
8550
+ setError(result.error || "Failed to fetch status");
8551
+ }
8552
+ } catch (err) {
8553
+ setError(err instanceof Error ? err.message : "Failed to fetch status");
8554
+ } finally {
8555
+ setIsLoading(false);
8556
+ }
8557
+ }, [checkoutSessionId, userToken, isAuthenticated, guestSessionId]);
8558
+ useState21(() => {
8559
+ fetchStatus();
8560
+ if (poll) {
8561
+ const interval = setInterval(() => {
8562
+ if (status?.paymentStatus === "paid" || status?.status === "expired") {
8563
+ return;
8564
+ }
8565
+ fetchStatus();
8566
+ }, pollInterval);
8567
+ return () => clearInterval(interval);
8568
+ }
8569
+ });
8570
+ return {
8571
+ status,
8572
+ isLoading,
8573
+ error,
8574
+ refresh: fetchStatus
8575
+ };
8576
+ }
8577
+
8578
+ // src/hooks/useProducts.ts
8579
+ function useProducts(options = {}) {
8580
+ const {
8581
+ collection = "products",
8582
+ activeOnly = true,
8583
+ category,
8584
+ productType,
8585
+ filters = [],
8586
+ page,
8587
+ pageSize,
8588
+ orderBy = "createdAt",
8589
+ orderDir = "desc",
8590
+ enabled
8591
+ } = options;
8592
+ const allFilters = [...filters];
8593
+ if (activeOnly) {
8594
+ allFilters.push({
8595
+ field: "status",
8596
+ operator: "eq",
8597
+ value: "active"
8598
+ });
8599
+ }
8600
+ if (category) {
8601
+ allFilters.push({
8602
+ field: "category",
8603
+ operator: "eq",
8604
+ value: category
8605
+ });
8606
+ }
8607
+ if (productType) {
8608
+ allFilters.push({
8609
+ field: "productType",
8610
+ operator: "eq",
8611
+ value: productType
8612
+ });
8613
+ }
8614
+ const result = useCollectionList({
8615
+ collection,
8616
+ filters: allFilters,
8617
+ page,
8618
+ pageSize,
8619
+ orderBy,
8620
+ orderDir,
8621
+ enabled
8622
+ });
8623
+ return {
8624
+ ...result,
8625
+ products: result.data
8626
+ };
8627
+ }
8628
+ function useProduct(options) {
8629
+ const { collection = "products", slug, enabled = true } = options;
8630
+ const result = useCollectionList({
8631
+ collection,
8632
+ filters: [
8633
+ { field: "slug", operator: "eq", value: slug }
8634
+ ],
8635
+ pageSize: 1,
8636
+ enabled: enabled && !!slug
8637
+ });
8638
+ const product = result.data?.[0] || null;
8639
+ const notFound = !result.isLoading && !product && !result.error;
8640
+ return {
8641
+ product,
8642
+ isLoading: result.isLoading,
8643
+ error: result.error,
8644
+ notFound,
8645
+ refetch: result.refetch
8646
+ };
8647
+ }
8648
+
8649
+ // src/hooks/useSubscription.ts
8650
+ import { useState as useState22, useCallback as useCallback24, useRef as useRef24 } from "react";
8651
+ function getConfig4(options) {
8652
+ if (typeof window === "undefined") {
8653
+ throw new Error("useSubscription requires browser environment");
8654
+ }
8655
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8656
+ const appId = options.appId || runtimeConfig?.appId;
8657
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8658
+ if (!appId) {
8659
+ throw new Error("App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)");
8660
+ }
8661
+ if (!apiUrl) {
8662
+ throw new Error("API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)");
8663
+ }
8664
+ return { appId, apiUrl };
8665
+ }
8666
+ function useSubscription(options = {}) {
8667
+ const { userToken } = options;
8668
+ const [isLoading, setIsLoading] = useState22(false);
8669
+ const [error, setError] = useState22(null);
8670
+ const configRef = useRef24(null);
8671
+ if (!configRef.current && typeof window !== "undefined") {
8672
+ try {
8673
+ configRef.current = getConfig4(options);
8674
+ } catch {
8675
+ }
8676
+ }
8677
+ const subscribe = useCallback24(async (params) => {
8678
+ const config = configRef.current;
8679
+ if (!config) {
8680
+ return {
8681
+ success: false,
8682
+ error: "Subscription not configured"
8683
+ };
8684
+ }
8685
+ setIsLoading(true);
8686
+ setError(null);
8687
+ try {
8688
+ const headers = {
8689
+ "Content-Type": "application/json"
8690
+ };
8691
+ if (userToken) {
8692
+ headers["X-App-User-Token"] = userToken;
8693
+ }
8694
+ const response = await fetch(
8695
+ `${config.apiUrl}/api/apps/${config.appId}/subscriptions/checkout`,
8696
+ {
8697
+ method: "POST",
8698
+ headers,
8699
+ body: JSON.stringify({
8700
+ tierSlug: params.tierSlug,
8701
+ successUrl: params.successUrl,
8702
+ cancelUrl: params.cancelUrl,
8703
+ quantity: params.quantity,
8704
+ trialDays: params.trialDays,
8705
+ customerEmail: params.customerEmail,
8706
+ metadata: params.metadata
8707
+ })
8708
+ }
8709
+ );
8710
+ const result = await response.json();
8711
+ if (!result.success || !result.data) {
8712
+ const errorMessage = result.error || "Failed to create subscription checkout";
8713
+ setError(errorMessage);
8714
+ return {
8715
+ success: false,
8716
+ error: errorMessage
8717
+ };
8718
+ }
8719
+ return {
8720
+ success: true,
8721
+ checkoutUrl: result.data.url,
8722
+ sessionId: result.data.sessionId
8723
+ };
8724
+ } catch (err) {
8725
+ const message = err instanceof Error ? err.message : "Failed to create subscription checkout";
8726
+ setError(message);
8727
+ return {
8728
+ success: false,
8729
+ error: message
8730
+ };
8731
+ } finally {
8732
+ setIsLoading(false);
8733
+ }
8734
+ }, [userToken]);
8735
+ return {
8736
+ subscribe,
8737
+ isLoading,
8738
+ error
8739
+ };
8740
+ }
8741
+
8742
+ // src/hooks/useSubscriptionTiers.ts
8743
+ import { useState as useState23, useCallback as useCallback25, useEffect as useEffect23, useRef as useRef25 } from "react";
8744
+ function getConfig5(options) {
8745
+ if (typeof window === "undefined") {
8746
+ throw new Error("useSubscriptionTiers requires browser environment");
8747
+ }
8748
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8749
+ const appId = options.appId || runtimeConfig?.appId;
8750
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8751
+ if (!appId) {
8752
+ throw new Error(
8753
+ "App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)"
8754
+ );
8755
+ }
8756
+ if (!apiUrl) {
8757
+ throw new Error(
8758
+ "API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)"
8759
+ );
8760
+ }
8761
+ return { appId, apiUrl };
8762
+ }
8763
+ function useSubscriptionTiers(options = {}) {
8764
+ const { fetchOnMount = true } = options;
8765
+ const [tiers, setTiers] = useState23([]);
8766
+ const [isLoading, setIsLoading] = useState23(false);
8767
+ const [error, setError] = useState23(null);
8768
+ const configRef = useRef25(null);
8769
+ if (!configRef.current && typeof window !== "undefined") {
8770
+ try {
8771
+ configRef.current = getConfig5(options);
8772
+ } catch {
8773
+ }
8774
+ }
8775
+ const refresh = useCallback25(async () => {
8776
+ const config = configRef.current;
8777
+ if (!config) {
8778
+ setError("Subscription tiers not configured");
8779
+ return;
8780
+ }
8781
+ setIsLoading(true);
8782
+ setError(null);
8783
+ try {
8784
+ const response = await fetch(
8785
+ `${config.apiUrl}/api/apps/${config.appId}/subscriptions/tiers`,
8786
+ {
8787
+ method: "GET",
8788
+ headers: {
8789
+ "Content-Type": "application/json"
8790
+ }
8791
+ }
8792
+ );
8793
+ const result = await response.json();
8794
+ if (!result.success || !result.data) {
8795
+ const errorMessage = result.error || "Failed to fetch subscription tiers";
8796
+ setError(errorMessage);
8797
+ return;
8798
+ }
8799
+ setTiers(result.data.tiers);
8800
+ } catch (err) {
8801
+ const message = err instanceof Error ? err.message : "Failed to fetch subscription tiers";
8802
+ setError(message);
8803
+ } finally {
8804
+ setIsLoading(false);
8805
+ }
8806
+ }, []);
8807
+ useEffect23(() => {
8808
+ if (fetchOnMount && configRef.current) {
8809
+ refresh();
8810
+ }
8811
+ }, [fetchOnMount, refresh]);
8812
+ return {
8813
+ tiers,
8814
+ isLoading,
8815
+ error,
8816
+ refresh
8817
+ };
8818
+ }
8819
+
8820
+ // src/hooks/useCustomerPortal.ts
8821
+ import { useState as useState24, useCallback as useCallback26, useRef as useRef26 } from "react";
8822
+ function getConfig6(options) {
8823
+ if (typeof window === "undefined") {
8824
+ throw new Error("useCustomerPortal requires browser environment");
8825
+ }
8826
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8827
+ const appId = options.appId || runtimeConfig?.appId;
8828
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8829
+ if (!appId) {
8830
+ throw new Error("App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)");
8831
+ }
8832
+ if (!apiUrl) {
8833
+ throw new Error("API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)");
8834
+ }
8835
+ return { appId, apiUrl };
8836
+ }
8837
+ function useCustomerPortal(options) {
8838
+ const { userToken } = options;
8839
+ const [isLoading, setIsLoading] = useState24(false);
8840
+ const [error, setError] = useState24(null);
8841
+ const configRef = useRef26(null);
8842
+ if (!configRef.current && typeof window !== "undefined") {
8843
+ try {
8844
+ configRef.current = getConfig6(options);
8845
+ } catch {
8846
+ }
8847
+ }
8848
+ const openPortal = useCallback26(async (params) => {
8849
+ const config = configRef.current;
8850
+ if (!config) {
8851
+ return {
8852
+ success: false,
8853
+ error: "Customer portal not configured"
8854
+ };
8855
+ }
8856
+ if (!userToken) {
8857
+ return {
8858
+ success: false,
8859
+ error: "Authentication required to access customer portal"
8860
+ };
8861
+ }
8862
+ setIsLoading(true);
8863
+ setError(null);
8864
+ try {
8865
+ const response = await fetch(
8866
+ `${config.apiUrl}/api/apps/${config.appId}/subscriptions/portal`,
8867
+ {
8868
+ method: "POST",
8869
+ headers: {
8870
+ "Content-Type": "application/json",
8871
+ "X-App-User-Token": userToken
8872
+ },
8873
+ body: JSON.stringify({
8874
+ returnUrl: params.returnUrl
8875
+ })
8876
+ }
8877
+ );
8878
+ const result = await response.json();
8879
+ if (!result.success || !result.data) {
8880
+ const errorMessage = result.error || "Failed to create portal session";
8881
+ setError(errorMessage);
8882
+ return {
8883
+ success: false,
8884
+ error: errorMessage
8885
+ };
8886
+ }
8887
+ return {
8888
+ success: true,
8889
+ portalUrl: result.data.portalUrl
8890
+ };
8891
+ } catch (err) {
8892
+ const message = err instanceof Error ? err.message : "Failed to create portal session";
8893
+ setError(message);
8894
+ return {
8895
+ success: false,
8896
+ error: message
8897
+ };
8898
+ } finally {
8899
+ setIsLoading(false);
8900
+ }
8901
+ }, [userToken]);
8902
+ return {
8903
+ openPortal,
8904
+ isLoading,
8905
+ error
8906
+ };
8907
+ }
8908
+
8909
+ // src/hooks/useSubscriptionStatus.ts
8910
+ import { useState as useState25, useCallback as useCallback27, useRef as useRef27, useEffect as useEffect24 } from "react";
8911
+ function getConfig7(options) {
8912
+ if (typeof window === "undefined") {
8913
+ throw new Error("useSubscriptionStatus requires browser environment");
8914
+ }
8915
+ const runtimeConfig = window.YOAMIGO_CONFIG;
8916
+ const appId = options.appId || runtimeConfig?.appId;
8917
+ const apiUrl = options.apiUrl || runtimeConfig?.apiUrl;
8918
+ if (!appId) {
8919
+ throw new Error("App ID not configured (provide appId option or set YOAMIGO_CONFIG.appId)");
8920
+ }
8921
+ if (!apiUrl) {
8922
+ throw new Error("API URL not configured (provide apiUrl option or set YOAMIGO_CONFIG.apiUrl)");
8923
+ }
8924
+ return { appId, apiUrl };
8925
+ }
8926
+ function useSubscriptionStatus(options) {
8927
+ const { userToken, autoFetch = true, pollInterval = 0 } = options;
8928
+ const [status, setStatus] = useState25(null);
8929
+ const [subscriptions, setSubscriptions] = useState25([]);
8930
+ const [isLoading, setIsLoading] = useState25(autoFetch);
8931
+ const [error, setError] = useState25(null);
8932
+ const configRef = useRef27(null);
8933
+ if (!configRef.current && typeof window !== "undefined") {
8934
+ try {
8935
+ configRef.current = getConfig7(options);
8936
+ } catch {
8937
+ }
8938
+ }
8939
+ const fetchStatus = useCallback27(async () => {
8940
+ const config = configRef.current;
8941
+ if (!config) {
8942
+ setError("Subscription status not configured");
8943
+ setIsLoading(false);
8944
+ return;
8945
+ }
8946
+ if (!userToken) {
8947
+ setStatus("none");
8948
+ setSubscriptions([]);
8949
+ setIsLoading(false);
8950
+ return;
8951
+ }
8952
+ setIsLoading(true);
8953
+ try {
8954
+ const response = await fetch(
8955
+ `${config.apiUrl}/api/apps/${config.appId}/subscriptions/status`,
8956
+ {
8957
+ method: "GET",
8958
+ headers: {
8959
+ "Content-Type": "application/json",
8960
+ "X-App-User-Token": userToken
8961
+ }
8962
+ }
8963
+ );
8964
+ const result = await response.json();
8965
+ if (!result.success) {
8966
+ setError(result.error || "Failed to fetch subscription status");
8967
+ return;
8968
+ }
8969
+ setStatus(result.data?.status ?? "none");
8970
+ setSubscriptions(result.data?.subscriptions ?? []);
8971
+ setError(null);
8972
+ } catch (err) {
8973
+ setError(err instanceof Error ? err.message : "Failed to fetch subscription status");
8974
+ } finally {
8975
+ setIsLoading(false);
8976
+ }
8977
+ }, [userToken]);
8978
+ useEffect24(() => {
8979
+ if (autoFetch && userToken) {
8980
+ fetchStatus();
8981
+ }
8982
+ }, [autoFetch, userToken, fetchStatus]);
8983
+ useEffect24(() => {
8984
+ if (pollInterval <= 0 || !userToken) {
8985
+ return;
8986
+ }
8987
+ const interval = setInterval(() => {
8988
+ fetchStatus();
8989
+ }, pollInterval);
8990
+ return () => clearInterval(interval);
8991
+ }, [pollInterval, userToken, fetchStatus]);
8992
+ return {
8993
+ status,
8994
+ subscriptions,
8995
+ isLoading,
8996
+ error,
8997
+ refresh: fetchStatus
8998
+ };
8999
+ }
7125
9000
  export {
7126
9001
  AIEditProvider,
9002
+ CartProvider,
9003
+ CollectionClient,
9004
+ CollectionContentProvider,
9005
+ CollectionDetailPage,
9006
+ CollectionItem,
9007
+ CollectionList,
9008
+ CollectionListPage,
7127
9009
  ContentStoreProvider,
7128
9010
  ContentStoreProvider2 as ContentStoreProviderProd,
7129
9011
  Link2 as Link,
@@ -7146,12 +9028,21 @@ export {
7146
9028
  background,
7147
9029
  buildIntermediateText,
7148
9030
  calculateAnimationTiming,
9031
+ clearSessionId,
7149
9032
  computeTextDiff,
7150
9033
  containsHtml,
7151
9034
  contentRegistry,
9035
+ createRouteDefinition,
7152
9036
  embed,
9037
+ extractRouteParams,
9038
+ filePathToRoutePath,
9039
+ generatePath,
7153
9040
  getAllContent,
9041
+ getCollectionClient,
7154
9042
  getContent,
9043
+ getLocalCartItemCount,
9044
+ getLocalCartItems,
9045
+ getSessionId,
7155
9046
  getTextCursorPosition,
7156
9047
  hasContent,
7157
9048
  image,
@@ -7160,13 +9051,17 @@ export {
7160
9051
  linkTransitionStrategy,
7161
9052
  parseBackgroundConfig,
7162
9053
  parseEmbedUrl,
9054
+ parseFieldValue,
7163
9055
  registerContent,
9056
+ resetCollectionClient,
7164
9057
  resolveAssetUrl,
7165
9058
  serializeBackgroundConfig,
7166
9059
  serializeEmbedValue,
7167
9060
  serializeImageValue,
7168
9061
  serializeVideoValue,
7169
9062
  setAssetResolver,
9063
+ sortRoutesBySpecificity,
9064
+ stringifyFieldValue,
7170
9065
  stripHtml,
7171
9066
  text,
7172
9067
  textTypingStrategy,
@@ -7174,10 +9069,26 @@ export {
7174
9069
  useAIEditContext,
7175
9070
  useAIEditContextOptional,
7176
9071
  useAnimatedText,
9072
+ useCart,
9073
+ useCartContext,
9074
+ useCheckout,
9075
+ useCheckoutStatus,
9076
+ useCollectionContent,
9077
+ useCollectionList,
9078
+ useCollectionRecord,
9079
+ useContent,
7177
9080
  useContentStore,
7178
9081
  useContentStore2 as useContentStoreProd,
9082
+ useCustomerPortal,
9083
+ useLocation4 as useLocation,
7179
9084
  useNavigate,
7180
- useParams,
9085
+ useOptionalCartContext,
9086
+ useParams2 as useParams,
9087
+ useProduct,
9088
+ useProducts,
7181
9089
  useSafeTriangle,
9090
+ useSubscription,
9091
+ useSubscriptionStatus,
9092
+ useSubscriptionTiers,
7182
9093
  video
7183
9094
  };