@yoamigo.com/core 1.0.0 → 1.1.0
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/{api-client-D8FkeBAI.d.ts → api-client-BaZ_K5a6.d.ts} +0 -8
- package/dist/{content-helpers-DOUKazMz.d.ts → icon-metadata-CVUpe16i.d.ts} +209 -4
- package/dist/index.d.ts +70 -2
- package/dist/index.js +2032 -342
- package/dist/lib-prod.d.ts +1 -1
- package/dist/lib.d.ts +1 -1
- package/dist/lib.js +63 -0
- package/dist/plugin.js +3 -2
- package/dist/prod.d.ts +34 -3
- package/dist/prod.js +319 -55
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/icons/custom-icons.tsx
|
|
12
|
+
var custom_icons_exports = {};
|
|
13
|
+
__export(custom_icons_exports, {
|
|
14
|
+
CUSTOM_ICON_NAMES: () => CUSTOM_ICON_NAMES,
|
|
15
|
+
IconBrandAppleMusic: () => IconBrandAppleMusic
|
|
16
|
+
});
|
|
17
|
+
import { forwardRef, createElement } from "react";
|
|
18
|
+
var appleMusicIconNode, IconBrandAppleMusic, CUSTOM_ICON_NAMES;
|
|
19
|
+
var init_custom_icons = __esm({
|
|
20
|
+
"src/icons/custom-icons.tsx"() {
|
|
21
|
+
"use strict";
|
|
22
|
+
appleMusicIconNode = [
|
|
23
|
+
[
|
|
24
|
+
"path",
|
|
25
|
+
{
|
|
26
|
+
d: "M23.994 6.124a9.23 9.23 0 00-.24-2.19c-.317-1.31-1.062-2.31-2.18-3.043a5.022 5.022 0 00-1.877-.726 10.496 10.496 0 00-1.564-.15c-.04-.003-.083-.01-.124-.013H5.986c-.152.01-.303.017-.455.026-.747.043-1.49.123-2.193.4-1.336.53-2.3 1.452-2.865 2.78-.192.448-.292.925-.363 1.408-.056.392-.088.785-.1 1.18 0 .032-.007.062-.01.093v12.223c.01.14.017.283.027.424.05.815.154 1.624.497 2.373.65 1.42 1.738 2.353 3.234 2.801.42.127.856.187 1.293.228.555.053 1.11.06 1.667.06h11.03a12.5 12.5 0 001.57-.1c.822-.106 1.596-.35 2.295-.81a5.046 5.046 0 001.88-2.207c.186-.42.293-.87.37-1.324.113-.675.138-1.358.137-2.04-.002-3.8 0-7.595-.003-11.393zm-6.423 3.99v5.712c0 .417-.058.827-.244 1.206-.29.59-.76.962-1.388 1.14-.35.1-.706.157-1.07.173-.95.045-1.773-.6-1.943-1.536a1.88 1.88 0 011.038-2.022c.323-.16.67-.25 1.018-.324.378-.082.758-.153 1.134-.24.274-.063.457-.23.51-.516a.904.904 0 00.02-.193c0-1.815 0-3.63-.002-5.443a.725.725 0 00-.026-.185c-.04-.15-.15-.243-.304-.234-.16.01-.318.035-.475.066-.76.15-1.52.303-2.28.456l-2.325.47-1.374.278c-.016.003-.032.01-.048.013-.277.077-.377.203-.39.49-.002.042 0 .086 0 .13-.002 2.602 0 5.204-.003 7.805 0 .42-.047.836-.215 1.227-.278.64-.77 1.04-1.434 1.233-.35.1-.71.16-1.075.172-.96.036-1.755-.6-1.92-1.544-.14-.812.23-1.685 1.154-2.075.357-.15.73-.232 1.108-.31.287-.06.575-.116.86-.177.383-.083.583-.323.6-.714v-.15c0-2.96 0-5.922.002-8.882 0-.123.013-.25.042-.37.07-.285.273-.448.546-.518.255-.066.515-.112.774-.165.733-.15 1.466-.296 2.2-.444l2.27-.46c.67-.134 1.34-.27 2.01-.403.22-.043.442-.088.663-.106.31-.025.523.17.554.482.008.073.012.148.012.223.002 1.91.002 3.822 0 5.732z",
|
|
27
|
+
key: "svg-0"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
];
|
|
31
|
+
IconBrandAppleMusic = forwardRef(
|
|
32
|
+
({ color = "currentColor", size = 24, className, style, title, ...rest }, ref) => createElement(
|
|
33
|
+
"svg",
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
37
|
+
width: size,
|
|
38
|
+
height: size,
|
|
39
|
+
viewBox: "0 0 24 24",
|
|
40
|
+
fill: color,
|
|
41
|
+
className,
|
|
42
|
+
style,
|
|
43
|
+
...rest
|
|
44
|
+
},
|
|
45
|
+
// Title element provides native browser tooltip on hover
|
|
46
|
+
title && createElement("title", { key: "title" }, title),
|
|
47
|
+
...appleMusicIconNode.map(([tag, attrs]) => createElement(tag, attrs))
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
IconBrandAppleMusic.displayName = "IconBrandAppleMusic";
|
|
51
|
+
CUSTOM_ICON_NAMES = ["IconBrandAppleMusic"];
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
1
55
|
// src/lib/content-registry.ts
|
|
2
56
|
var contentMap = /* @__PURE__ */ new Map();
|
|
3
57
|
function registerContent(content) {
|
|
@@ -234,6 +288,9 @@ var BuilderSelectionManager = class {
|
|
|
234
288
|
case "GET_CURRENT_PAGE":
|
|
235
289
|
this.sendToParent({ type: "CURRENT_PAGE", pagePath: window.location.pathname });
|
|
236
290
|
break;
|
|
291
|
+
case "CHECK_BLANK_STATE":
|
|
292
|
+
this.checkBlankState();
|
|
293
|
+
break;
|
|
237
294
|
}
|
|
238
295
|
});
|
|
239
296
|
}
|
|
@@ -885,16 +942,16 @@ var BuilderSelectionManager = class {
|
|
|
885
942
|
}
|
|
886
943
|
const links = document.querySelectorAll('a[href^="/"]');
|
|
887
944
|
const routes = /* @__PURE__ */ new Set(["/"]);
|
|
888
|
-
links.forEach((
|
|
889
|
-
const href =
|
|
945
|
+
links.forEach((link2) => {
|
|
946
|
+
const href = link2.getAttribute("href");
|
|
890
947
|
if (href && href.startsWith("/") && !href.includes("http")) {
|
|
891
948
|
const path = href.split("?")[0].replace(/\/$/, "") || "/";
|
|
892
949
|
routes.add(path);
|
|
893
950
|
}
|
|
894
951
|
});
|
|
895
952
|
const navLinks = document.querySelectorAll("nav a[href]");
|
|
896
|
-
navLinks.forEach((
|
|
897
|
-
const href =
|
|
953
|
+
navLinks.forEach((link2) => {
|
|
954
|
+
const href = link2.getAttribute("href");
|
|
898
955
|
if (href?.startsWith("/")) {
|
|
899
956
|
const path = href.split("?")[0].replace(/\/$/, "") || "/";
|
|
900
957
|
routes.add(path);
|
|
@@ -1082,6 +1139,66 @@ var BuilderSelectionManager = class {
|
|
|
1082
1139
|
return null;
|
|
1083
1140
|
}
|
|
1084
1141
|
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Check if the page is visually blank (all white/uniform color)
|
|
1144
|
+
* Uses canvas pixel sampling for accuracy.
|
|
1145
|
+
* Triggered after AI edits to detect if preview went white and needs refresh.
|
|
1146
|
+
*/
|
|
1147
|
+
async checkBlankState() {
|
|
1148
|
+
try {
|
|
1149
|
+
const html2canvas = (await import("html2canvas-pro")).default;
|
|
1150
|
+
const canvas = await html2canvas(document.body, {
|
|
1151
|
+
scale: 0.1,
|
|
1152
|
+
// Small scale for speed
|
|
1153
|
+
logging: false,
|
|
1154
|
+
width: window.innerWidth,
|
|
1155
|
+
height: window.innerHeight,
|
|
1156
|
+
backgroundColor: null
|
|
1157
|
+
// Preserve actual background
|
|
1158
|
+
});
|
|
1159
|
+
const sampleCanvas = document.createElement("canvas");
|
|
1160
|
+
const size = 100;
|
|
1161
|
+
sampleCanvas.width = size;
|
|
1162
|
+
sampleCanvas.height = size;
|
|
1163
|
+
const ctx = sampleCanvas.getContext("2d");
|
|
1164
|
+
if (!ctx) {
|
|
1165
|
+
this.sendToParent({ type: "BLANK_STATE_RESULT", isBlank: false });
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
ctx.drawImage(canvas, 0, 0, size, size);
|
|
1169
|
+
const samplePoints = [
|
|
1170
|
+
[25, 25],
|
|
1171
|
+
[75, 25],
|
|
1172
|
+
[50, 50],
|
|
1173
|
+
[25, 75],
|
|
1174
|
+
[75, 75],
|
|
1175
|
+
[10, 10],
|
|
1176
|
+
[90, 90],
|
|
1177
|
+
[50, 25],
|
|
1178
|
+
[50, 75],
|
|
1179
|
+
[25, 50]
|
|
1180
|
+
];
|
|
1181
|
+
const pixels = samplePoints.map(([x, y]) => {
|
|
1182
|
+
const data = ctx.getImageData(x, y, 1, 1).data;
|
|
1183
|
+
return { r: data[0], g: data[1], b: data[2] };
|
|
1184
|
+
});
|
|
1185
|
+
const firstPixel = pixels[0];
|
|
1186
|
+
const tolerance = 10;
|
|
1187
|
+
const allSame = pixels.every(
|
|
1188
|
+
(p) => Math.abs(p.r - firstPixel.r) < tolerance && Math.abs(p.g - firstPixel.g) < tolerance && Math.abs(p.b - firstPixel.b) < tolerance
|
|
1189
|
+
);
|
|
1190
|
+
const isWhitish = firstPixel.r > 240 && firstPixel.g > 240 && firstPixel.b > 240;
|
|
1191
|
+
const isBlank = allSame && isWhitish;
|
|
1192
|
+
this.sendToParent({
|
|
1193
|
+
type: "BLANK_STATE_RESULT",
|
|
1194
|
+
isBlank,
|
|
1195
|
+
sampleColor: `rgb(${firstPixel.r},${firstPixel.g},${firstPixel.b})`
|
|
1196
|
+
});
|
|
1197
|
+
} catch (error) {
|
|
1198
|
+
console.error("[BuilderSelection] Blank check failed:", error);
|
|
1199
|
+
this.sendToParent({ type: "BLANK_STATE_RESULT", isBlank: false });
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1085
1202
|
};
|
|
1086
1203
|
var instance = null;
|
|
1087
1204
|
function initBuilderSelection() {
|
|
@@ -2041,16 +2158,16 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
2041
2158
|
if (mode !== "inline-edit" || !containerRef.current) return;
|
|
2042
2159
|
const container = containerRef.current;
|
|
2043
2160
|
const handleMouseOver = (e) => {
|
|
2044
|
-
const
|
|
2045
|
-
if (!
|
|
2161
|
+
const link2 = e.target.closest("a");
|
|
2162
|
+
if (!link2) return;
|
|
2046
2163
|
if (e.target.closest(".mp-text-editing, .mp-text-editable")) return;
|
|
2047
2164
|
const selectModeEnabled = window.__builderSelectModeEnabled;
|
|
2048
2165
|
if (selectModeEnabled) return;
|
|
2049
2166
|
clearTimeout(hideTimerRef.current);
|
|
2050
2167
|
showTimerRef.current = window.setTimeout(() => {
|
|
2051
|
-
const href =
|
|
2168
|
+
const href = link2.getAttribute("href") || "";
|
|
2052
2169
|
const { text: text2, isExternal } = extractLinkDisplayText(href);
|
|
2053
|
-
const rect =
|
|
2170
|
+
const rect = link2.getBoundingClientRect();
|
|
2054
2171
|
const top = rect.bottom + window.scrollY + 8;
|
|
2055
2172
|
const left = rect.left + rect.width / 2 + window.scrollX;
|
|
2056
2173
|
setPopoverState({
|
|
@@ -2063,8 +2180,8 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
2063
2180
|
}, 150);
|
|
2064
2181
|
};
|
|
2065
2182
|
const handleMouseOut = (e) => {
|
|
2066
|
-
const
|
|
2067
|
-
if (!
|
|
2183
|
+
const link2 = e.target.closest("a");
|
|
2184
|
+
if (!link2) return;
|
|
2068
2185
|
scheduleHide();
|
|
2069
2186
|
};
|
|
2070
2187
|
const handleClick = (e) => {
|
|
@@ -2077,8 +2194,8 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
2077
2194
|
}
|
|
2078
2195
|
return;
|
|
2079
2196
|
}
|
|
2080
|
-
const
|
|
2081
|
-
if (
|
|
2197
|
+
const link2 = e.target.closest("a");
|
|
2198
|
+
if (link2) {
|
|
2082
2199
|
e.preventDefault();
|
|
2083
2200
|
e.stopPropagation();
|
|
2084
2201
|
}
|
|
@@ -2653,6 +2770,71 @@ function useAnimatedText(fieldId, content, options = {}) {
|
|
|
2653
2770
|
};
|
|
2654
2771
|
}
|
|
2655
2772
|
|
|
2773
|
+
// src/lib/contrast-detection.ts
|
|
2774
|
+
function parseColor(color) {
|
|
2775
|
+
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
2776
|
+
if (rgbMatch) {
|
|
2777
|
+
return { r: parseInt(rgbMatch[1]), g: parseInt(rgbMatch[2]), b: parseInt(rgbMatch[3]) };
|
|
2778
|
+
}
|
|
2779
|
+
const hexMatch = color.match(/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
|
|
2780
|
+
if (hexMatch) {
|
|
2781
|
+
return { r: parseInt(hexMatch[1], 16), g: parseInt(hexMatch[2], 16), b: parseInt(hexMatch[3], 16) };
|
|
2782
|
+
}
|
|
2783
|
+
return null;
|
|
2784
|
+
}
|
|
2785
|
+
function getRelativeLuminance(r, g, b) {
|
|
2786
|
+
const [rs, gs, bs] = [r, g, b].map((c) => {
|
|
2787
|
+
const s = c / 255;
|
|
2788
|
+
return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
2789
|
+
});
|
|
2790
|
+
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
2791
|
+
}
|
|
2792
|
+
function getEffectiveBackgroundColor(element) {
|
|
2793
|
+
let el = element;
|
|
2794
|
+
while (el) {
|
|
2795
|
+
const bg = window.getComputedStyle(el).backgroundColor;
|
|
2796
|
+
const parsed = parseColor(bg);
|
|
2797
|
+
if (parsed && bg !== "transparent" && bg !== "rgba(0, 0, 0, 0)") {
|
|
2798
|
+
return bg;
|
|
2799
|
+
}
|
|
2800
|
+
el = el.parentElement;
|
|
2801
|
+
}
|
|
2802
|
+
return null;
|
|
2803
|
+
}
|
|
2804
|
+
function getContrastColor(bgColor) {
|
|
2805
|
+
const parsed = parseColor(bgColor);
|
|
2806
|
+
if (!parsed) return "white";
|
|
2807
|
+
const luminance = getRelativeLuminance(parsed.r, parsed.g, parsed.b);
|
|
2808
|
+
const contrastWithWhite = (1 + 0.05) / (luminance + 0.05);
|
|
2809
|
+
const contrastWithBlack = (luminance + 0.05) / (0 + 0.05);
|
|
2810
|
+
return contrastWithWhite > contrastWithBlack ? "white" : "black";
|
|
2811
|
+
}
|
|
2812
|
+
function setupContrastDetection(element) {
|
|
2813
|
+
const updateContrastColor = () => {
|
|
2814
|
+
const bgColor = getEffectiveBackgroundColor(element);
|
|
2815
|
+
if (bgColor) {
|
|
2816
|
+
const contrastColor = getContrastColor(bgColor);
|
|
2817
|
+
element.style.setProperty("--ya-contrast-color", contrastColor);
|
|
2818
|
+
}
|
|
2819
|
+
};
|
|
2820
|
+
updateContrastColor();
|
|
2821
|
+
let rafId = null;
|
|
2822
|
+
const throttledUpdate = () => {
|
|
2823
|
+
if (rafId) return;
|
|
2824
|
+
rafId = requestAnimationFrame(() => {
|
|
2825
|
+
updateContrastColor();
|
|
2826
|
+
rafId = null;
|
|
2827
|
+
});
|
|
2828
|
+
};
|
|
2829
|
+
window.addEventListener("scroll", throttledUpdate, { passive: true, capture: true });
|
|
2830
|
+
window.addEventListener("resize", throttledUpdate, { passive: true });
|
|
2831
|
+
return () => {
|
|
2832
|
+
window.removeEventListener("scroll", throttledUpdate, { capture: true });
|
|
2833
|
+
window.removeEventListener("resize", throttledUpdate);
|
|
2834
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2656
2838
|
// src/components/BubbleIcons.tsx
|
|
2657
2839
|
import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2658
2840
|
function BoldIcon({ size = 16, className }) {
|
|
@@ -3090,23 +3272,34 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
3090
3272
|
|
|
3091
3273
|
// src/components/ya-text.css
|
|
3092
3274
|
styleInject(`.ya-text-editable {
|
|
3275
|
+
position: relative;
|
|
3093
3276
|
cursor: text;
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
.ya-text-editable:hover {
|
|
3097
|
-
outline: 2px dashed var(--color-primary, #D4A574);
|
|
3277
|
+
border-radius: 4px;
|
|
3278
|
+
outline: 1.5px dashed transparent;
|
|
3098
3279
|
outline-offset: 4px;
|
|
3280
|
+
transition: outline-color 0.15s ease;
|
|
3281
|
+
}
|
|
3282
|
+
.ya-text-editing {
|
|
3283
|
+
position: relative;
|
|
3284
|
+
cursor: text;
|
|
3099
3285
|
border-radius: 4px;
|
|
3286
|
+
outline: 1.5px solid var(--ya-contrast-color, white);
|
|
3287
|
+
outline-offset: 4px;
|
|
3288
|
+
}
|
|
3289
|
+
.ya-text-editable:hover {
|
|
3290
|
+
outline-color: var(--ya-contrast-color, white);
|
|
3100
3291
|
}
|
|
3101
3292
|
body.builder-selector-active .ya-text-editable:hover {
|
|
3102
|
-
outline:
|
|
3293
|
+
outline-color: transparent;
|
|
3294
|
+
}
|
|
3295
|
+
body.builder-selector-active .ya-text-editable {
|
|
3103
3296
|
cursor: inherit;
|
|
3104
3297
|
}
|
|
3105
|
-
.ya-text-
|
|
3106
|
-
outline:
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3298
|
+
[data-ya-link=true] .ya-text-editable {
|
|
3299
|
+
outline: none;
|
|
3300
|
+
}
|
|
3301
|
+
[data-ya-link=true] .ya-text-editable:hover {
|
|
3302
|
+
outline: none;
|
|
3110
3303
|
}
|
|
3111
3304
|
.ya-text-editing .ProseMirror p::selection,
|
|
3112
3305
|
.ya-text-editing .ProseMirror::selection {
|
|
@@ -3637,6 +3830,10 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
3637
3830
|
handleSaveRef.current = handleSave;
|
|
3638
3831
|
handleCancelRef.current = handleCancel;
|
|
3639
3832
|
}, [handleSave, handleCancel]);
|
|
3833
|
+
useEffect8(() => {
|
|
3834
|
+
if (mode !== "inline-edit" || !containerRef.current) return;
|
|
3835
|
+
return setupContrastDetection(containerRef.current);
|
|
3836
|
+
}, [mode]);
|
|
3640
3837
|
useEffect8(() => {
|
|
3641
3838
|
if (mode !== "inline-edit") return;
|
|
3642
3839
|
const handleEditRequest = (event) => {
|
|
@@ -3689,8 +3886,8 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
3689
3886
|
if (selectModeEnabled) {
|
|
3690
3887
|
return;
|
|
3691
3888
|
}
|
|
3692
|
-
const
|
|
3693
|
-
if (
|
|
3889
|
+
const isInsideYaLink = e.currentTarget.closest('[data-ya-link="true"]') !== null;
|
|
3890
|
+
if (isInsideYaLink) {
|
|
3694
3891
|
return;
|
|
3695
3892
|
}
|
|
3696
3893
|
if (mode === "inline-edit" && !isEditing) {
|
|
@@ -5263,14 +5460,401 @@ function YaVideo({
|
|
|
5263
5460
|
);
|
|
5264
5461
|
}
|
|
5265
5462
|
|
|
5266
|
-
// src/components/
|
|
5463
|
+
// src/components/YaProtectedMedia.tsx
|
|
5267
5464
|
import { useCallback as useCallback15, useEffect as useEffect13, useRef as useRef14, useState as useState13 } from "react";
|
|
5268
5465
|
|
|
5466
|
+
// src/lib/api-client.ts
|
|
5467
|
+
function getApiUrl() {
|
|
5468
|
+
const runtimeConfig = window.YOAMIGO_CONFIG;
|
|
5469
|
+
const apiUrl = runtimeConfig?.apiUrl || import.meta.env.YA_API_URL;
|
|
5470
|
+
if (!apiUrl) {
|
|
5471
|
+
throw new Error("API URL not configured (check YOAMIGO_CONFIG or YA_API_URL)");
|
|
5472
|
+
}
|
|
5473
|
+
return apiUrl;
|
|
5474
|
+
}
|
|
5475
|
+
function getSiteId() {
|
|
5476
|
+
const runtimeConfig = window.YOAMIGO_CONFIG;
|
|
5477
|
+
const siteId = runtimeConfig?.siteId || import.meta.env.YA_SITE_ID;
|
|
5478
|
+
if (!siteId) {
|
|
5479
|
+
throw new Error("Site ID not configured (check YOAMIGO_CONFIG or YA_SITE_ID)");
|
|
5480
|
+
}
|
|
5481
|
+
return siteId;
|
|
5482
|
+
}
|
|
5483
|
+
|
|
5484
|
+
// src/components/ya-protected-media.css
|
|
5485
|
+
styleInject(".ya-protected-container {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n border-radius: 12px;\n overflow: hidden;\n background:\n linear-gradient(\n 135deg,\n #1c1917 0%,\n #292524 100%);\n}\n.ya-protected-container.ya-protected-audio {\n padding: 24px;\n background:\n linear-gradient(\n 135deg,\n #1c1917 0%,\n #292524 100%);\n}\n.ya-protected-container.ya-protected-loading {\n min-height: 200px;\n}\n.ya-protected-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid rgba(255, 255, 255, 0.1);\n border-top-color: #FF6B35;\n border-radius: 50%;\n animation: ya-spin 0.8s linear infinite;\n}\n@keyframes ya-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.ya-protected-error-state {\n min-height: 200px;\n}\n.ya-protected-error-message {\n color: #ef4444;\n font-size: 14px;\n text-align: center;\n padding: 20px;\n}\n.ya-protected-container.ya-protected-locked {\n background:\n linear-gradient(\n 135deg,\n #1c1917 0%,\n #292524 100%);\n}\n.ya-protected-preview-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.ya-protected-preview-badge {\n position: absolute;\n top: 12px;\n right: 12px;\n padding: 6px 12px;\n background: rgba(0, 0, 0, 0.7);\n color: #FF6B35;\n font-size: 12px;\n font-weight: 600;\n border-radius: 999px;\n backdrop-filter: blur(4px);\n}\n.ya-protected-video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.ya-protected-video.ya-protected-preview {\n opacity: 0.8;\n}\n.ya-protected-audio-player {\n width: 100%;\n height: 48px;\n border-radius: 8px;\n}\n.ya-protected-title {\n font-size: 16px;\n font-weight: 600;\n color: #f5f5f4;\n margin-bottom: 16px;\n text-align: center;\n}\n.ya-protected-unlock-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(28, 25, 23, 0.95);\n backdrop-filter: blur(8px);\n}\n.ya-protected-unlock-prompt {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 24px;\n background:\n linear-gradient(\n to top,\n rgba(28, 25, 23, 0.98) 0%,\n rgba(28, 25, 23, 0.9) 80%,\n transparent 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n}\n.ya-protected-unlock-form {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n padding: 32px;\n max-width: 320px;\n width: 100%;\n text-align: center;\n}\n.ya-protected-unlock-icon {\n color: #FF6B35;\n margin-bottom: 8px;\n}\n.ya-protected-unlock-title {\n font-size: 24px;\n font-weight: 700;\n color: #f5f5f4;\n letter-spacing: -0.02em;\n}\n.ya-protected-unlock-folder {\n font-size: 14px;\n color: #a8a29e;\n margin-top: -8px;\n}\n.ya-protected-unlock-subtitle {\n font-size: 14px;\n color: #a8a29e;\n margin-bottom: 8px;\n}\n.ya-protected-input {\n width: 100%;\n padding: 14px 16px;\n font-size: 15px;\n color: #f5f5f4;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n outline: none;\n transition: all 0.2s ease;\n}\n.ya-protected-input::placeholder {\n color: #78716c;\n}\n.ya-protected-input:focus {\n border-color: #FF6B35;\n background: rgba(255, 107, 53, 0.05);\n box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.1);\n}\n.ya-protected-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.ya-protected-button {\n width: 100%;\n padding: 14px 24px;\n font-size: 15px;\n font-weight: 600;\n color: #fff;\n background:\n linear-gradient(\n 135deg,\n #FF6B35 0%,\n #e05a2b 100%);\n border: none;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n.ya-protected-button:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 6px 20px rgba(255, 107, 53, 0.35);\n}\n.ya-protected-button:active:not(:disabled) {\n transform: translateY(0);\n}\n.ya-protected-button:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n.ya-protected-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n.ya-protected-error {\n color: #ef4444;\n font-size: 13px;\n padding: 8px 12px;\n background: rgba(239, 68, 68, 0.1);\n border-radius: 6px;\n width: 100%;\n}\n.ya-protected-disclaimer {\n font-size: 12px;\n color: #78716c;\n margin-top: -4px;\n}\n.ya-protected-container.ya-protected-unlocked {\n background: transparent;\n}\n@media (max-width: 480px) {\n .ya-protected-unlock-form {\n padding: 24px 16px;\n }\n .ya-protected-unlock-title {\n font-size: 20px;\n }\n .ya-protected-input,\n .ya-protected-button {\n padding: 12px 14px;\n font-size: 14px;\n }\n}\n@media (prefers-color-scheme: light) {\n .ya-protected-container.ya-protected-locked {\n background:\n linear-gradient(\n 135deg,\n #f5f5f4 0%,\n #e7e5e4 100%);\n }\n .ya-protected-unlock-overlay {\n background: rgba(245, 245, 244, 0.95);\n }\n .ya-protected-unlock-title {\n color: #1c1917;\n }\n .ya-protected-unlock-subtitle,\n .ya-protected-unlock-folder {\n color: #57534e;\n }\n .ya-protected-input {\n color: #1c1917;\n background: rgba(0, 0, 0, 0.03);\n border-color: rgba(0, 0, 0, 0.1);\n }\n .ya-protected-input::placeholder {\n color: #a8a29e;\n }\n .ya-protected-input:focus {\n background: rgba(255, 107, 53, 0.03);\n }\n .ya-protected-disclaimer {\n color: #78716c;\n }\n}\n");
|
|
5486
|
+
|
|
5487
|
+
// src/components/YaProtectedMedia.tsx
|
|
5488
|
+
import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5489
|
+
var COOKIE_PREFIX = "ya_access_";
|
|
5490
|
+
var COOKIE_EXPIRY_DAYS = 30;
|
|
5491
|
+
function getStoredAccess(folderId) {
|
|
5492
|
+
const name = `${COOKIE_PREFIX}${folderId}=`;
|
|
5493
|
+
const decodedCookie = decodeURIComponent(document.cookie);
|
|
5494
|
+
const cookies = decodedCookie.split(";");
|
|
5495
|
+
for (const cookie of cookies) {
|
|
5496
|
+
const c = cookie.trim();
|
|
5497
|
+
if (c.indexOf(name) === 0) {
|
|
5498
|
+
return c.substring(name.length);
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
return null;
|
|
5502
|
+
}
|
|
5503
|
+
function storeAccess(folderId, email) {
|
|
5504
|
+
const expires = /* @__PURE__ */ new Date();
|
|
5505
|
+
expires.setTime(expires.getTime() + COOKIE_EXPIRY_DAYS * 24 * 60 * 60 * 1e3);
|
|
5506
|
+
document.cookie = `${COOKIE_PREFIX}${folderId}=${email};expires=${expires.toUTCString()};path=/;SameSite=Lax`;
|
|
5507
|
+
}
|
|
5508
|
+
function clearStoredAccess(folderId) {
|
|
5509
|
+
document.cookie = `${COOKIE_PREFIX}${folderId}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
|
|
5510
|
+
}
|
|
5511
|
+
function UnlockForm({ accessInfo, onSubmit, isLoading, error }) {
|
|
5512
|
+
const [email, setEmail] = useState13("");
|
|
5513
|
+
const [password, setPassword] = useState13("");
|
|
5514
|
+
const handleSubmit = (e) => {
|
|
5515
|
+
e.preventDefault();
|
|
5516
|
+
if (accessInfo.authType === "password") {
|
|
5517
|
+
onSubmit({ password });
|
|
5518
|
+
} else {
|
|
5519
|
+
onSubmit({ email });
|
|
5520
|
+
}
|
|
5521
|
+
};
|
|
5522
|
+
const isEmailAuth = accessInfo.authType === "email" || accessInfo.authType === "subscriber";
|
|
5523
|
+
const isPasswordAuth = accessInfo.authType === "password";
|
|
5524
|
+
return /* @__PURE__ */ jsxs8("form", { className: "ya-protected-unlock-form", onSubmit: handleSubmit, children: [
|
|
5525
|
+
/* @__PURE__ */ jsx15("div", { className: "ya-protected-unlock-icon", children: /* @__PURE__ */ jsxs8(
|
|
5526
|
+
"svg",
|
|
5527
|
+
{
|
|
5528
|
+
width: "32",
|
|
5529
|
+
height: "32",
|
|
5530
|
+
viewBox: "0 0 24 24",
|
|
5531
|
+
fill: "none",
|
|
5532
|
+
stroke: "currentColor",
|
|
5533
|
+
strokeWidth: "2",
|
|
5534
|
+
strokeLinecap: "round",
|
|
5535
|
+
strokeLinejoin: "round",
|
|
5536
|
+
children: [
|
|
5537
|
+
/* @__PURE__ */ jsx15("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
|
|
5538
|
+
/* @__PURE__ */ jsx15("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
5539
|
+
]
|
|
5540
|
+
}
|
|
5541
|
+
) }),
|
|
5542
|
+
/* @__PURE__ */ jsx15("div", { className: "ya-protected-unlock-title", children: accessInfo.authType === "subscriber" ? "Subscribers Only" : "Exclusive Content" }),
|
|
5543
|
+
accessInfo.folderName && /* @__PURE__ */ jsx15("div", { className: "ya-protected-unlock-folder", children: accessInfo.folderName }),
|
|
5544
|
+
/* @__PURE__ */ jsx15("div", { className: "ya-protected-unlock-subtitle", children: isEmailAuth && accessInfo.authType === "subscriber" ? "Enter your email to verify access" : isEmailAuth ? "Enter your email to unlock" : "Enter password to access" }),
|
|
5545
|
+
isEmailAuth && /* @__PURE__ */ jsx15(
|
|
5546
|
+
"input",
|
|
5547
|
+
{
|
|
5548
|
+
type: "email",
|
|
5549
|
+
className: "ya-protected-input",
|
|
5550
|
+
placeholder: "your@email.com",
|
|
5551
|
+
value: email,
|
|
5552
|
+
onChange: (e) => setEmail(e.target.value),
|
|
5553
|
+
required: true,
|
|
5554
|
+
disabled: isLoading,
|
|
5555
|
+
autoFocus: true
|
|
5556
|
+
}
|
|
5557
|
+
),
|
|
5558
|
+
isPasswordAuth && /* @__PURE__ */ jsx15(
|
|
5559
|
+
"input",
|
|
5560
|
+
{
|
|
5561
|
+
type: "password",
|
|
5562
|
+
className: "ya-protected-input",
|
|
5563
|
+
placeholder: "Enter password",
|
|
5564
|
+
value: password,
|
|
5565
|
+
onChange: (e) => setPassword(e.target.value),
|
|
5566
|
+
required: true,
|
|
5567
|
+
disabled: isLoading,
|
|
5568
|
+
autoFocus: true
|
|
5569
|
+
}
|
|
5570
|
+
),
|
|
5571
|
+
error && /* @__PURE__ */ jsx15("div", { className: "ya-protected-error", children: error }),
|
|
5572
|
+
/* @__PURE__ */ jsx15("button", { type: "submit", className: "ya-protected-button", disabled: isLoading, children: isLoading ? /* @__PURE__ */ jsx15("span", { className: "ya-protected-loading", children: "Unlocking..." }) : "Unlock Now" }),
|
|
5573
|
+
isEmailAuth && accessInfo.authType === "email" && /* @__PURE__ */ jsx15("div", { className: "ya-protected-disclaimer", children: "Your email will be added to the mailing list." })
|
|
5574
|
+
] });
|
|
5575
|
+
}
|
|
5576
|
+
function YaProtectedMedia({
|
|
5577
|
+
fieldId,
|
|
5578
|
+
assetId,
|
|
5579
|
+
type,
|
|
5580
|
+
className,
|
|
5581
|
+
poster,
|
|
5582
|
+
aspectRatio = "16/9",
|
|
5583
|
+
title,
|
|
5584
|
+
onUnlock,
|
|
5585
|
+
onUnlockError
|
|
5586
|
+
}) {
|
|
5587
|
+
const containerRef = useRef14(null);
|
|
5588
|
+
const mediaRef = useRef14(null);
|
|
5589
|
+
const [accessInfo, setAccessInfo] = useState13(null);
|
|
5590
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
5591
|
+
const [isUnlocking, setIsUnlocking] = useState13(false);
|
|
5592
|
+
const [isUnlocked, setIsUnlocked] = useState13(false);
|
|
5593
|
+
const [unlockedUrl, setUnlockedUrl] = useState13(null);
|
|
5594
|
+
const [error, setError] = useState13(null);
|
|
5595
|
+
const [previewEnded, setPreviewEnded] = useState13(false);
|
|
5596
|
+
useEffect13(() => {
|
|
5597
|
+
async function fetchAccessInfo() {
|
|
5598
|
+
try {
|
|
5599
|
+
const apiUrl = getApiUrl();
|
|
5600
|
+
const siteId = getSiteId();
|
|
5601
|
+
const response = await fetch(`${apiUrl}/api/websites/${siteId}/access/asset/${assetId}`);
|
|
5602
|
+
if (!response.ok) {
|
|
5603
|
+
throw new Error("Failed to fetch access info");
|
|
5604
|
+
}
|
|
5605
|
+
const data = await response.json();
|
|
5606
|
+
setAccessInfo(data);
|
|
5607
|
+
if (!data.requiresAuth && data.url) {
|
|
5608
|
+
setIsUnlocked(true);
|
|
5609
|
+
setUnlockedUrl(data.url);
|
|
5610
|
+
}
|
|
5611
|
+
if (data.requiresAuth && data.folderId) {
|
|
5612
|
+
const storedEmail = getStoredAccess(data.folderId);
|
|
5613
|
+
if (storedEmail) {
|
|
5614
|
+
await tryStoredAccess(data.folderId, storedEmail);
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
} catch (err) {
|
|
5618
|
+
console.error("Failed to fetch access info:", err);
|
|
5619
|
+
setError("Unable to load content");
|
|
5620
|
+
} finally {
|
|
5621
|
+
setIsLoading(false);
|
|
5622
|
+
}
|
|
5623
|
+
}
|
|
5624
|
+
fetchAccessInfo();
|
|
5625
|
+
}, [assetId]);
|
|
5626
|
+
const tryStoredAccess = async (folderId, email) => {
|
|
5627
|
+
try {
|
|
5628
|
+
const apiUrl = getApiUrl();
|
|
5629
|
+
const siteId = getSiteId();
|
|
5630
|
+
const response = await fetch(`${apiUrl}/api/websites/${siteId}/access/asset/${assetId}/unlock`, {
|
|
5631
|
+
method: "POST",
|
|
5632
|
+
headers: { "Content-Type": "application/json" },
|
|
5633
|
+
body: JSON.stringify({ email })
|
|
5634
|
+
});
|
|
5635
|
+
if (response.ok) {
|
|
5636
|
+
const result = await response.json();
|
|
5637
|
+
if (result.success) {
|
|
5638
|
+
setIsUnlocked(true);
|
|
5639
|
+
setUnlockedUrl(result.url);
|
|
5640
|
+
return true;
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5643
|
+
clearStoredAccess(folderId);
|
|
5644
|
+
return false;
|
|
5645
|
+
} catch {
|
|
5646
|
+
clearStoredAccess(folderId);
|
|
5647
|
+
return false;
|
|
5648
|
+
}
|
|
5649
|
+
};
|
|
5650
|
+
const handleUnlock = useCallback15(
|
|
5651
|
+
async (data) => {
|
|
5652
|
+
if (!accessInfo) return;
|
|
5653
|
+
setIsUnlocking(true);
|
|
5654
|
+
setError(null);
|
|
5655
|
+
try {
|
|
5656
|
+
const apiUrl = getApiUrl();
|
|
5657
|
+
const siteId = getSiteId();
|
|
5658
|
+
const response = await fetch(`${apiUrl}/api/websites/${siteId}/access/asset/${assetId}/unlock`, {
|
|
5659
|
+
method: "POST",
|
|
5660
|
+
headers: { "Content-Type": "application/json" },
|
|
5661
|
+
body: JSON.stringify(data)
|
|
5662
|
+
});
|
|
5663
|
+
const result = await response.json();
|
|
5664
|
+
if (!response.ok) {
|
|
5665
|
+
throw new Error(result.error || "Failed to unlock");
|
|
5666
|
+
}
|
|
5667
|
+
if (result.success) {
|
|
5668
|
+
setIsUnlocked(true);
|
|
5669
|
+
setUnlockedUrl(result.url);
|
|
5670
|
+
if (accessInfo.folderId && data.email) {
|
|
5671
|
+
storeAccess(accessInfo.folderId, data.email);
|
|
5672
|
+
}
|
|
5673
|
+
onUnlock?.();
|
|
5674
|
+
} else {
|
|
5675
|
+
throw new Error(result.error || "Failed to unlock");
|
|
5676
|
+
}
|
|
5677
|
+
} catch (err) {
|
|
5678
|
+
const message = err instanceof Error ? err.message : "Failed to unlock";
|
|
5679
|
+
setError(message);
|
|
5680
|
+
onUnlockError?.(message);
|
|
5681
|
+
} finally {
|
|
5682
|
+
setIsUnlocking(false);
|
|
5683
|
+
}
|
|
5684
|
+
},
|
|
5685
|
+
[assetId, accessInfo, onUnlock, onUnlockError]
|
|
5686
|
+
);
|
|
5687
|
+
const handleTimeUpdate = useCallback15(() => {
|
|
5688
|
+
if (!accessInfo?.showPreview || !mediaRef.current || isUnlocked) return;
|
|
5689
|
+
const media = mediaRef.current;
|
|
5690
|
+
if (media.currentTime >= accessInfo.previewDuration) {
|
|
5691
|
+
media.pause();
|
|
5692
|
+
media.currentTime = 0;
|
|
5693
|
+
setPreviewEnded(true);
|
|
5694
|
+
}
|
|
5695
|
+
}, [accessInfo, isUnlocked]);
|
|
5696
|
+
if (isLoading) {
|
|
5697
|
+
return /* @__PURE__ */ jsx15(
|
|
5698
|
+
"div",
|
|
5699
|
+
{
|
|
5700
|
+
ref: containerRef,
|
|
5701
|
+
className: `ya-protected-container ya-protected-loading ${className || ""}`,
|
|
5702
|
+
style: { aspectRatio: type === "video" ? aspectRatio : void 0 },
|
|
5703
|
+
"data-field-id": fieldId,
|
|
5704
|
+
children: /* @__PURE__ */ jsx15("div", { className: "ya-protected-spinner" })
|
|
5705
|
+
}
|
|
5706
|
+
);
|
|
5707
|
+
}
|
|
5708
|
+
if (error && !accessInfo) {
|
|
5709
|
+
return /* @__PURE__ */ jsx15(
|
|
5710
|
+
"div",
|
|
5711
|
+
{
|
|
5712
|
+
ref: containerRef,
|
|
5713
|
+
className: `ya-protected-container ya-protected-error-state ${className || ""}`,
|
|
5714
|
+
style: { aspectRatio: type === "video" ? aspectRatio : void 0 },
|
|
5715
|
+
"data-field-id": fieldId,
|
|
5716
|
+
children: /* @__PURE__ */ jsx15("div", { className: "ya-protected-error-message", children: error })
|
|
5717
|
+
}
|
|
5718
|
+
);
|
|
5719
|
+
}
|
|
5720
|
+
if (isUnlocked && unlockedUrl) {
|
|
5721
|
+
const resolvedUrl = resolveAssetUrl(unlockedUrl);
|
|
5722
|
+
if (type === "video") {
|
|
5723
|
+
return /* @__PURE__ */ jsxs8(
|
|
5724
|
+
"div",
|
|
5725
|
+
{
|
|
5726
|
+
ref: containerRef,
|
|
5727
|
+
className: `ya-protected-container ya-protected-unlocked ${className || ""}`,
|
|
5728
|
+
style: { aspectRatio },
|
|
5729
|
+
"data-field-id": fieldId,
|
|
5730
|
+
children: [
|
|
5731
|
+
/* @__PURE__ */ jsx15(
|
|
5732
|
+
"video",
|
|
5733
|
+
{
|
|
5734
|
+
ref: mediaRef,
|
|
5735
|
+
src: resolvedUrl,
|
|
5736
|
+
poster: poster ? resolveAssetUrl(poster) : void 0,
|
|
5737
|
+
controls: true,
|
|
5738
|
+
playsInline: true,
|
|
5739
|
+
className: "ya-protected-video"
|
|
5740
|
+
}
|
|
5741
|
+
),
|
|
5742
|
+
title && /* @__PURE__ */ jsx15("div", { className: "ya-protected-title", children: title })
|
|
5743
|
+
]
|
|
5744
|
+
}
|
|
5745
|
+
);
|
|
5746
|
+
}
|
|
5747
|
+
return /* @__PURE__ */ jsxs8(
|
|
5748
|
+
"div",
|
|
5749
|
+
{
|
|
5750
|
+
ref: containerRef,
|
|
5751
|
+
className: `ya-protected-container ya-protected-unlocked ya-protected-audio ${className || ""}`,
|
|
5752
|
+
"data-field-id": fieldId,
|
|
5753
|
+
children: [
|
|
5754
|
+
title && /* @__PURE__ */ jsx15("div", { className: "ya-protected-title", children: title }),
|
|
5755
|
+
/* @__PURE__ */ jsx15(
|
|
5756
|
+
"audio",
|
|
5757
|
+
{
|
|
5758
|
+
ref: mediaRef,
|
|
5759
|
+
src: resolvedUrl,
|
|
5760
|
+
controls: true,
|
|
5761
|
+
className: "ya-protected-audio-player"
|
|
5762
|
+
}
|
|
5763
|
+
)
|
|
5764
|
+
]
|
|
5765
|
+
}
|
|
5766
|
+
);
|
|
5767
|
+
}
|
|
5768
|
+
if (accessInfo) {
|
|
5769
|
+
const showPreviewPlayer = accessInfo.showPreview && !previewEnded && accessInfo.url;
|
|
5770
|
+
return /* @__PURE__ */ jsxs8(
|
|
5771
|
+
"div",
|
|
5772
|
+
{
|
|
5773
|
+
ref: containerRef,
|
|
5774
|
+
className: `ya-protected-container ya-protected-locked ${className || ""}`,
|
|
5775
|
+
style: { aspectRatio: type === "video" ? aspectRatio : void 0 },
|
|
5776
|
+
"data-field-id": fieldId,
|
|
5777
|
+
children: [
|
|
5778
|
+
showPreviewPlayer && type === "video" && /* @__PURE__ */ jsxs8("div", { className: "ya-protected-preview-wrapper", children: [
|
|
5779
|
+
/* @__PURE__ */ jsx15(
|
|
5780
|
+
"video",
|
|
5781
|
+
{
|
|
5782
|
+
ref: mediaRef,
|
|
5783
|
+
src: resolveAssetUrl(accessInfo.url),
|
|
5784
|
+
poster: poster ? resolveAssetUrl(poster) : void 0,
|
|
5785
|
+
controls: true,
|
|
5786
|
+
playsInline: true,
|
|
5787
|
+
className: "ya-protected-video ya-protected-preview",
|
|
5788
|
+
onTimeUpdate: handleTimeUpdate
|
|
5789
|
+
}
|
|
5790
|
+
),
|
|
5791
|
+
/* @__PURE__ */ jsxs8("div", { className: "ya-protected-preview-badge", children: [
|
|
5792
|
+
"Preview (",
|
|
5793
|
+
accessInfo.previewDuration,
|
|
5794
|
+
"s)"
|
|
5795
|
+
] })
|
|
5796
|
+
] }),
|
|
5797
|
+
showPreviewPlayer && type === "audio" && /* @__PURE__ */ jsxs8("div", { className: "ya-protected-preview-wrapper", children: [
|
|
5798
|
+
title && /* @__PURE__ */ jsx15("div", { className: "ya-protected-title", children: title }),
|
|
5799
|
+
/* @__PURE__ */ jsx15(
|
|
5800
|
+
"audio",
|
|
5801
|
+
{
|
|
5802
|
+
ref: mediaRef,
|
|
5803
|
+
src: resolveAssetUrl(accessInfo.url),
|
|
5804
|
+
controls: true,
|
|
5805
|
+
className: "ya-protected-audio-player ya-protected-preview",
|
|
5806
|
+
onTimeUpdate: handleTimeUpdate
|
|
5807
|
+
}
|
|
5808
|
+
),
|
|
5809
|
+
/* @__PURE__ */ jsxs8("div", { className: "ya-protected-preview-badge", children: [
|
|
5810
|
+
"Preview (",
|
|
5811
|
+
accessInfo.previewDuration,
|
|
5812
|
+
"s)"
|
|
5813
|
+
] })
|
|
5814
|
+
] }),
|
|
5815
|
+
(!showPreviewPlayer || previewEnded) && /* @__PURE__ */ jsx15("div", { className: "ya-protected-unlock-overlay", children: /* @__PURE__ */ jsx15(
|
|
5816
|
+
UnlockForm,
|
|
5817
|
+
{
|
|
5818
|
+
accessInfo,
|
|
5819
|
+
onSubmit: handleUnlock,
|
|
5820
|
+
isLoading: isUnlocking,
|
|
5821
|
+
error
|
|
5822
|
+
}
|
|
5823
|
+
) }),
|
|
5824
|
+
showPreviewPlayer && previewEnded && /* @__PURE__ */ jsxs8("div", { className: "ya-protected-unlock-prompt", children: [
|
|
5825
|
+
/* @__PURE__ */ jsx15(
|
|
5826
|
+
"button",
|
|
5827
|
+
{
|
|
5828
|
+
className: "ya-protected-button",
|
|
5829
|
+
onClick: () => setPreviewEnded(false),
|
|
5830
|
+
children: "Replay Preview"
|
|
5831
|
+
}
|
|
5832
|
+
),
|
|
5833
|
+
/* @__PURE__ */ jsx15(
|
|
5834
|
+
UnlockForm,
|
|
5835
|
+
{
|
|
5836
|
+
accessInfo,
|
|
5837
|
+
onSubmit: handleUnlock,
|
|
5838
|
+
isLoading: isUnlocking,
|
|
5839
|
+
error
|
|
5840
|
+
}
|
|
5841
|
+
)
|
|
5842
|
+
] })
|
|
5843
|
+
]
|
|
5844
|
+
}
|
|
5845
|
+
);
|
|
5846
|
+
}
|
|
5847
|
+
return null;
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5850
|
+
// src/components/YaEmbed.tsx
|
|
5851
|
+
import { useCallback as useCallback16, useEffect as useEffect14, useRef as useRef15, useState as useState14 } from "react";
|
|
5852
|
+
|
|
5269
5853
|
// src/components/ya-embed.css
|
|
5270
5854
|
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');
|
|
5271
5855
|
|
|
5272
5856
|
// src/components/YaEmbed.tsx
|
|
5273
|
-
import { jsx as
|
|
5857
|
+
import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5274
5858
|
function parseEmbedUrl(url) {
|
|
5275
5859
|
if (!url) return null;
|
|
5276
5860
|
const trimmedUrl = url.trim();
|
|
@@ -5385,11 +5969,11 @@ function YaEmbed({
|
|
|
5385
5969
|
}) {
|
|
5386
5970
|
const content = useContent(fieldId);
|
|
5387
5971
|
const { mode } = content;
|
|
5388
|
-
const containerRef =
|
|
5389
|
-
const [isSelected, setIsSelected] =
|
|
5390
|
-
const [isHovered, setIsHovered] =
|
|
5391
|
-
const [isSmallEmbed, setIsSmallEmbed] =
|
|
5392
|
-
const [isInView, setIsInView] =
|
|
5972
|
+
const containerRef = useRef15(null);
|
|
5973
|
+
const [isSelected, setIsSelected] = useState14(false);
|
|
5974
|
+
const [isHovered, setIsHovered] = useState14(false);
|
|
5975
|
+
const [isSmallEmbed, setIsSmallEmbed] = useState14(false);
|
|
5976
|
+
const [isInView, setIsInView] = useState14(loading === "eager");
|
|
5393
5977
|
const rawValue = content.get();
|
|
5394
5978
|
const parsedValue = parseEmbedValue(rawValue);
|
|
5395
5979
|
const embedData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
|
|
@@ -5397,7 +5981,7 @@ function YaEmbed({
|
|
|
5397
5981
|
const embedType = embedData.type || "custom";
|
|
5398
5982
|
const height = embedData.height;
|
|
5399
5983
|
const aspectRatio = embedData.aspectRatio || propAspectRatio || "16/9";
|
|
5400
|
-
|
|
5984
|
+
useEffect14(() => {
|
|
5401
5985
|
if (loading === "eager" || isInView) return;
|
|
5402
5986
|
const observer = new IntersectionObserver(
|
|
5403
5987
|
(entries) => {
|
|
@@ -5414,7 +5998,7 @@ function YaEmbed({
|
|
|
5414
5998
|
}
|
|
5415
5999
|
return () => observer.disconnect();
|
|
5416
6000
|
}, [loading, isInView]);
|
|
5417
|
-
const handleClick =
|
|
6001
|
+
const handleClick = useCallback16(() => {
|
|
5418
6002
|
if (mode !== "inline-edit") return;
|
|
5419
6003
|
if (document.body.classList.contains("builder-selector-active")) return;
|
|
5420
6004
|
setIsSelected(true);
|
|
@@ -5434,7 +6018,7 @@ function YaEmbed({
|
|
|
5434
6018
|
"*"
|
|
5435
6019
|
);
|
|
5436
6020
|
}, [mode, fieldId, embedData]);
|
|
5437
|
-
|
|
6021
|
+
useEffect14(() => {
|
|
5438
6022
|
if (mode !== "inline-edit") return;
|
|
5439
6023
|
const handleMessage2 = (event) => {
|
|
5440
6024
|
if (event.data?.type === "YA_EMBED_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -5447,7 +6031,7 @@ function YaEmbed({
|
|
|
5447
6031
|
window.addEventListener("message", handleMessage2);
|
|
5448
6032
|
return () => window.removeEventListener("message", handleMessage2);
|
|
5449
6033
|
}, [mode, fieldId]);
|
|
5450
|
-
|
|
6034
|
+
useEffect14(() => {
|
|
5451
6035
|
if (mode !== "inline-edit") return;
|
|
5452
6036
|
const checkSize = () => {
|
|
5453
6037
|
if (containerRef.current) {
|
|
@@ -5459,7 +6043,7 @@ function YaEmbed({
|
|
|
5459
6043
|
window.addEventListener("resize", checkSize);
|
|
5460
6044
|
return () => window.removeEventListener("resize", checkSize);
|
|
5461
6045
|
}, [mode]);
|
|
5462
|
-
|
|
6046
|
+
useEffect14(() => {
|
|
5463
6047
|
if (!isSelected || mode !== "inline-edit") return;
|
|
5464
6048
|
let lastRectKey = "";
|
|
5465
6049
|
let lastTime = 0;
|
|
@@ -5495,17 +6079,17 @@ function YaEmbed({
|
|
|
5495
6079
|
}, [isSelected, fieldId, mode]);
|
|
5496
6080
|
const renderEmbed = (isReadOnly) => {
|
|
5497
6081
|
if (!src && !isReadOnly) {
|
|
5498
|
-
return /* @__PURE__ */
|
|
5499
|
-
/* @__PURE__ */
|
|
5500
|
-
/* @__PURE__ */
|
|
6082
|
+
return /* @__PURE__ */ jsxs9("div", { className: "ya-embed-placeholder", children: [
|
|
6083
|
+
/* @__PURE__ */ jsx16("img", { src: PLACEHOLDER_SVG3, alt: "" }),
|
|
6084
|
+
/* @__PURE__ */ jsx16("span", { children: "No embed selected" })
|
|
5501
6085
|
] });
|
|
5502
6086
|
}
|
|
5503
6087
|
if (!isInView && loading === "lazy" && !isReadOnly) {
|
|
5504
|
-
return /* @__PURE__ */
|
|
6088
|
+
return /* @__PURE__ */ jsx16("div", { className: "ya-embed-placeholder", style: { aspectRatio }, children: /* @__PURE__ */ jsx16("img", { src: PLACEHOLDER_SVG3, alt: "" }) });
|
|
5505
6089
|
}
|
|
5506
6090
|
if (embedType === "spotify" && src) {
|
|
5507
6091
|
const embedUrl = buildSpotifyEmbedUrl(src);
|
|
5508
|
-
return /* @__PURE__ */
|
|
6092
|
+
return /* @__PURE__ */ jsx16(
|
|
5509
6093
|
"iframe",
|
|
5510
6094
|
{
|
|
5511
6095
|
src: embedUrl,
|
|
@@ -5523,7 +6107,7 @@ function YaEmbed({
|
|
|
5523
6107
|
}
|
|
5524
6108
|
if (embedType === "soundcloud" && src) {
|
|
5525
6109
|
const embedUrl = buildSoundCloudEmbedUrl(src);
|
|
5526
|
-
return /* @__PURE__ */
|
|
6110
|
+
return /* @__PURE__ */ jsx16(
|
|
5527
6111
|
"iframe",
|
|
5528
6112
|
{
|
|
5529
6113
|
src: embedUrl,
|
|
@@ -5539,14 +6123,14 @@ function YaEmbed({
|
|
|
5539
6123
|
);
|
|
5540
6124
|
}
|
|
5541
6125
|
if (embedType === "twitter" && src) {
|
|
5542
|
-
return /* @__PURE__ */
|
|
5543
|
-
/* @__PURE__ */
|
|
5544
|
-
/* @__PURE__ */
|
|
6126
|
+
return /* @__PURE__ */ jsxs9("div", { className: "ya-embed-twitter", children: [
|
|
6127
|
+
/* @__PURE__ */ jsx16("blockquote", { className: "twitter-tweet", "data-dnt": "true", children: /* @__PURE__ */ jsx16("a", { href: embedData.originalUrl || `https://twitter.com/i/status/${src}`, children: "Loading tweet..." }) }),
|
|
6128
|
+
/* @__PURE__ */ jsx16(TwitterWidgetLoader, {})
|
|
5545
6129
|
] });
|
|
5546
6130
|
}
|
|
5547
6131
|
if (embedType === "instagram" && src) {
|
|
5548
6132
|
const embedUrl = buildInstagramEmbedUrl(src);
|
|
5549
|
-
return /* @__PURE__ */
|
|
6133
|
+
return /* @__PURE__ */ jsx16(
|
|
5550
6134
|
"iframe",
|
|
5551
6135
|
{
|
|
5552
6136
|
src: embedUrl,
|
|
@@ -5564,7 +6148,7 @@ function YaEmbed({
|
|
|
5564
6148
|
);
|
|
5565
6149
|
}
|
|
5566
6150
|
if (embedType === "custom" && src) {
|
|
5567
|
-
return /* @__PURE__ */
|
|
6151
|
+
return /* @__PURE__ */ jsx16(
|
|
5568
6152
|
"iframe",
|
|
5569
6153
|
{
|
|
5570
6154
|
src,
|
|
@@ -5588,7 +6172,7 @@ function YaEmbed({
|
|
|
5588
6172
|
maxWidth: maxWidth ? `${maxWidth}px` : void 0
|
|
5589
6173
|
};
|
|
5590
6174
|
if (mode === "read-only") {
|
|
5591
|
-
return /* @__PURE__ */
|
|
6175
|
+
return /* @__PURE__ */ jsx16(
|
|
5592
6176
|
"div",
|
|
5593
6177
|
{
|
|
5594
6178
|
ref: containerRef,
|
|
@@ -5600,7 +6184,7 @@ function YaEmbed({
|
|
|
5600
6184
|
}
|
|
5601
6185
|
);
|
|
5602
6186
|
}
|
|
5603
|
-
const embedIcon = /* @__PURE__ */
|
|
6187
|
+
const embedIcon = /* @__PURE__ */ jsxs9(
|
|
5604
6188
|
"svg",
|
|
5605
6189
|
{
|
|
5606
6190
|
width: "24",
|
|
@@ -5612,12 +6196,12 @@ function YaEmbed({
|
|
|
5612
6196
|
strokeLinecap: "round",
|
|
5613
6197
|
strokeLinejoin: "round",
|
|
5614
6198
|
children: [
|
|
5615
|
-
/* @__PURE__ */
|
|
5616
|
-
/* @__PURE__ */
|
|
6199
|
+
/* @__PURE__ */ jsx16("polyline", { points: "16 18 22 12 16 6" }),
|
|
6200
|
+
/* @__PURE__ */ jsx16("polyline", { points: "8 6 2 12 8 18" })
|
|
5617
6201
|
]
|
|
5618
6202
|
}
|
|
5619
6203
|
);
|
|
5620
|
-
return /* @__PURE__ */
|
|
6204
|
+
return /* @__PURE__ */ jsxs9(
|
|
5621
6205
|
"div",
|
|
5622
6206
|
{
|
|
5623
6207
|
ref: containerRef,
|
|
@@ -5640,14 +6224,14 @@ function YaEmbed({
|
|
|
5640
6224
|
style: wrapperStyle,
|
|
5641
6225
|
children: [
|
|
5642
6226
|
renderEmbed(false),
|
|
5643
|
-
isSmallEmbed ? /* @__PURE__ */
|
|
6227
|
+
isSmallEmbed ? /* @__PURE__ */ jsxs9(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
|
|
5644
6228
|
embedIcon,
|
|
5645
|
-
/* @__PURE__ */
|
|
6229
|
+
/* @__PURE__ */ jsx16("span", { children: "Click to edit" })
|
|
5646
6230
|
] }) : (
|
|
5647
6231
|
/* For large embeds: show overlay inside the container */
|
|
5648
|
-
/* @__PURE__ */
|
|
5649
|
-
/* @__PURE__ */
|
|
5650
|
-
/* @__PURE__ */
|
|
6232
|
+
/* @__PURE__ */ jsxs9("div", { className: "ya-embed-overlay", children: [
|
|
6233
|
+
/* @__PURE__ */ jsx16("div", { className: "ya-embed-edit-icon", children: embedIcon }),
|
|
6234
|
+
/* @__PURE__ */ jsx16("span", { className: "ya-embed-edit-label", children: "Click to edit" })
|
|
5651
6235
|
] })
|
|
5652
6236
|
)
|
|
5653
6237
|
]
|
|
@@ -5655,7 +6239,7 @@ function YaEmbed({
|
|
|
5655
6239
|
);
|
|
5656
6240
|
}
|
|
5657
6241
|
function TwitterWidgetLoader() {
|
|
5658
|
-
|
|
6242
|
+
useEffect14(() => {
|
|
5659
6243
|
if (window.twttr?.widgets) {
|
|
5660
6244
|
;
|
|
5661
6245
|
window.twttr.widgets.load();
|
|
@@ -5676,7 +6260,7 @@ function TwitterWidgetLoader() {
|
|
|
5676
6260
|
}
|
|
5677
6261
|
|
|
5678
6262
|
// src/components/YaLink.tsx
|
|
5679
|
-
import { useEffect as
|
|
6263
|
+
import { useEffect as useEffect19, useLayoutEffect as useLayoutEffect3, useRef as useRef19, useState as useState19, useCallback as useCallback20, useId } from "react";
|
|
5680
6264
|
import { createPortal as createPortal6 } from "react-dom";
|
|
5681
6265
|
import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
|
|
5682
6266
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
@@ -5686,7 +6270,7 @@ import { Extension as Extension2 } from "@tiptap/core";
|
|
|
5686
6270
|
import { Link as WouterLink, useLocation } from "wouter";
|
|
5687
6271
|
|
|
5688
6272
|
// src/components/SafeTriangleBelow.tsx
|
|
5689
|
-
import { useEffect as
|
|
6273
|
+
import { useEffect as useEffect15, useState as useState15, useRef as useRef16, useCallback as useCallback17 } from "react";
|
|
5690
6274
|
function SafeTriangleBelow({
|
|
5691
6275
|
triggerRef,
|
|
5692
6276
|
popoverRef,
|
|
@@ -5694,10 +6278,10 @@ function SafeTriangleBelow({
|
|
|
5694
6278
|
onLeave,
|
|
5695
6279
|
onStayInside
|
|
5696
6280
|
}) {
|
|
5697
|
-
const [bounds, setBounds] =
|
|
5698
|
-
const boundsRef =
|
|
6281
|
+
const [bounds, setBounds] = useState15(null);
|
|
6282
|
+
const boundsRef = useRef16(bounds);
|
|
5699
6283
|
boundsRef.current = bounds;
|
|
5700
|
-
|
|
6284
|
+
useEffect15(() => {
|
|
5701
6285
|
if (!isVisible || !triggerRef.current || !popoverRef.current) {
|
|
5702
6286
|
setBounds(null);
|
|
5703
6287
|
return;
|
|
@@ -5715,7 +6299,7 @@ function SafeTriangleBelow({
|
|
|
5715
6299
|
}, 10);
|
|
5716
6300
|
return () => clearTimeout(timer);
|
|
5717
6301
|
}, [isVisible, triggerRef, popoverRef]);
|
|
5718
|
-
const checkMousePosition =
|
|
6302
|
+
const checkMousePosition = useCallback17((e) => {
|
|
5719
6303
|
const b = boundsRef.current;
|
|
5720
6304
|
if (!b) return;
|
|
5721
6305
|
const { clientX: x, clientY: y } = e;
|
|
@@ -5727,7 +6311,7 @@ function SafeTriangleBelow({
|
|
|
5727
6311
|
onStayInside?.();
|
|
5728
6312
|
}
|
|
5729
6313
|
}, [onLeave, onStayInside]);
|
|
5730
|
-
|
|
6314
|
+
useEffect15(() => {
|
|
5731
6315
|
if (!isVisible || !bounds) return;
|
|
5732
6316
|
document.addEventListener("mousemove", checkMousePosition);
|
|
5733
6317
|
return () => document.removeEventListener("mousemove", checkMousePosition);
|
|
@@ -5736,22 +6320,36 @@ function SafeTriangleBelow({
|
|
|
5736
6320
|
}
|
|
5737
6321
|
|
|
5738
6322
|
// src/hooks/useSafeTriangle.ts
|
|
5739
|
-
import { useState as
|
|
6323
|
+
import { useState as useState16, useRef as useRef17, useCallback as useCallback18, useEffect as useEffect16 } from "react";
|
|
5740
6324
|
function useSafeTriangle(options = {}) {
|
|
5741
6325
|
const { showDelay = 0, hideDelay = 150, enabled = true } = options;
|
|
5742
|
-
const [isVisible, setIsVisible] =
|
|
5743
|
-
const [isHovering, setIsHovering] =
|
|
5744
|
-
const triggerRef =
|
|
5745
|
-
const popoverRef =
|
|
5746
|
-
const showTimeoutRef =
|
|
5747
|
-
const hideTimeoutRef =
|
|
5748
|
-
|
|
6326
|
+
const [isVisible, setIsVisible] = useState16(false);
|
|
6327
|
+
const [isHovering, setIsHovering] = useState16(false);
|
|
6328
|
+
const triggerRef = useRef17(null);
|
|
6329
|
+
const popoverRef = useRef17(null);
|
|
6330
|
+
const showTimeoutRef = useRef17(null);
|
|
6331
|
+
const hideTimeoutRef = useRef17(null);
|
|
6332
|
+
useEffect16(() => {
|
|
5749
6333
|
return () => {
|
|
5750
6334
|
if (showTimeoutRef.current) clearTimeout(showTimeoutRef.current);
|
|
5751
6335
|
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
5752
6336
|
};
|
|
5753
6337
|
}, []);
|
|
5754
|
-
|
|
6338
|
+
useEffect16(() => {
|
|
6339
|
+
if (!enabled) {
|
|
6340
|
+
if (showTimeoutRef.current) {
|
|
6341
|
+
clearTimeout(showTimeoutRef.current);
|
|
6342
|
+
showTimeoutRef.current = null;
|
|
6343
|
+
}
|
|
6344
|
+
if (hideTimeoutRef.current) {
|
|
6345
|
+
clearTimeout(hideTimeoutRef.current);
|
|
6346
|
+
hideTimeoutRef.current = null;
|
|
6347
|
+
}
|
|
6348
|
+
setIsVisible(false);
|
|
6349
|
+
setIsHovering(false);
|
|
6350
|
+
}
|
|
6351
|
+
}, [enabled]);
|
|
6352
|
+
const show = useCallback18(() => {
|
|
5755
6353
|
if (!enabled) return;
|
|
5756
6354
|
if (hideTimeoutRef.current) {
|
|
5757
6355
|
clearTimeout(hideTimeoutRef.current);
|
|
@@ -5759,7 +6357,7 @@ function useSafeTriangle(options = {}) {
|
|
|
5759
6357
|
}
|
|
5760
6358
|
setIsVisible(true);
|
|
5761
6359
|
}, [enabled]);
|
|
5762
|
-
const hide =
|
|
6360
|
+
const hide = useCallback18(() => {
|
|
5763
6361
|
if (showTimeoutRef.current) {
|
|
5764
6362
|
clearTimeout(showTimeoutRef.current);
|
|
5765
6363
|
showTimeoutRef.current = null;
|
|
@@ -5767,7 +6365,7 @@ function useSafeTriangle(options = {}) {
|
|
|
5767
6365
|
setIsVisible(false);
|
|
5768
6366
|
setIsHovering(false);
|
|
5769
6367
|
}, []);
|
|
5770
|
-
const handleMouseEnter =
|
|
6368
|
+
const handleMouseEnter = useCallback18(() => {
|
|
5771
6369
|
if (!enabled) return;
|
|
5772
6370
|
setIsHovering(true);
|
|
5773
6371
|
if (hideTimeoutRef.current) {
|
|
@@ -5782,7 +6380,7 @@ function useSafeTriangle(options = {}) {
|
|
|
5782
6380
|
setIsVisible(true);
|
|
5783
6381
|
}
|
|
5784
6382
|
}, [showDelay, enabled]);
|
|
5785
|
-
const handleMouseLeave =
|
|
6383
|
+
const handleMouseLeave = useCallback18(() => {
|
|
5786
6384
|
setIsHovering(false);
|
|
5787
6385
|
if (showTimeoutRef.current) {
|
|
5788
6386
|
clearTimeout(showTimeoutRef.current);
|
|
@@ -5792,16 +6390,16 @@ function useSafeTriangle(options = {}) {
|
|
|
5792
6390
|
setIsVisible(false);
|
|
5793
6391
|
}, hideDelay);
|
|
5794
6392
|
}, [hideDelay]);
|
|
5795
|
-
const handleFocus =
|
|
6393
|
+
const handleFocus = useCallback18(() => {
|
|
5796
6394
|
if (!enabled) return;
|
|
5797
6395
|
setIsVisible(true);
|
|
5798
6396
|
}, [enabled]);
|
|
5799
|
-
const handleTriangleLeave =
|
|
6397
|
+
const handleTriangleLeave = useCallback18(() => {
|
|
5800
6398
|
if (!isHovering) {
|
|
5801
6399
|
setIsVisible(false);
|
|
5802
6400
|
}
|
|
5803
6401
|
}, [isHovering]);
|
|
5804
|
-
const handleStayInside =
|
|
6402
|
+
const handleStayInside = useCallback18(() => {
|
|
5805
6403
|
if (hideTimeoutRef.current) {
|
|
5806
6404
|
clearTimeout(hideTimeoutRef.current);
|
|
5807
6405
|
hideTimeoutRef.current = null;
|
|
@@ -5828,13 +6426,696 @@ function useSafeTriangle(options = {}) {
|
|
|
5828
6426
|
};
|
|
5829
6427
|
}
|
|
5830
6428
|
|
|
5831
|
-
// src/
|
|
5832
|
-
|
|
6429
|
+
// src/icons/DynamicIcon.tsx
|
|
6430
|
+
import { useEffect as useEffect17, useState as useState17, memo } from "react";
|
|
5833
6431
|
|
|
5834
|
-
// src/
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
6432
|
+
// src/icons/icon-registry.ts
|
|
6433
|
+
var iconCache = /* @__PURE__ */ new Map();
|
|
6434
|
+
var pendingLoads = /* @__PURE__ */ new Map();
|
|
6435
|
+
var registeredLoaders = /* @__PURE__ */ new Map();
|
|
6436
|
+
var MAX_CACHE_SIZE = 100;
|
|
6437
|
+
function registerIcon(name, loader) {
|
|
6438
|
+
registeredLoaders.set(name, loader);
|
|
6439
|
+
}
|
|
6440
|
+
function registerIcons(loaders) {
|
|
6441
|
+
for (const [name, loader] of Object.entries(loaders)) {
|
|
6442
|
+
registeredLoaders.set(name, loader);
|
|
6443
|
+
}
|
|
6444
|
+
}
|
|
6445
|
+
function getIcon(name) {
|
|
6446
|
+
return iconCache.get(name) ?? null;
|
|
6447
|
+
}
|
|
6448
|
+
async function loadIcon(name) {
|
|
6449
|
+
if (iconCache.has(name)) {
|
|
6450
|
+
return iconCache.get(name);
|
|
6451
|
+
}
|
|
6452
|
+
if (pendingLoads.has(name)) {
|
|
6453
|
+
return pendingLoads.get(name);
|
|
6454
|
+
}
|
|
6455
|
+
const loadPromise = (async () => {
|
|
6456
|
+
try {
|
|
6457
|
+
let IconComponent;
|
|
6458
|
+
if (name === "IconBrandAppleMusic") {
|
|
6459
|
+
const customModule = await Promise.resolve().then(() => (init_custom_icons(), custom_icons_exports));
|
|
6460
|
+
IconComponent = customModule.IconBrandAppleMusic;
|
|
6461
|
+
} else if (registeredLoaders.has(name)) {
|
|
6462
|
+
const loader = registeredLoaders.get(name);
|
|
6463
|
+
const module = await loader();
|
|
6464
|
+
IconComponent = module.default;
|
|
6465
|
+
} else {
|
|
6466
|
+
const module = await import("@tabler/icons-react");
|
|
6467
|
+
IconComponent = module[name];
|
|
6468
|
+
}
|
|
6469
|
+
if (!IconComponent) {
|
|
6470
|
+
console.warn(`Icon "${name}" not found in @tabler/icons-react or custom icons`);
|
|
6471
|
+
return null;
|
|
6472
|
+
}
|
|
6473
|
+
if (iconCache.size >= MAX_CACHE_SIZE) {
|
|
6474
|
+
const firstKey = iconCache.keys().next().value;
|
|
6475
|
+
if (firstKey) {
|
|
6476
|
+
iconCache.delete(firstKey);
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6479
|
+
iconCache.set(name, IconComponent);
|
|
6480
|
+
return IconComponent;
|
|
6481
|
+
} catch (error) {
|
|
6482
|
+
console.error(`Failed to load icon "${name}":`, error);
|
|
6483
|
+
return null;
|
|
6484
|
+
} finally {
|
|
6485
|
+
pendingLoads.delete(name);
|
|
6486
|
+
}
|
|
6487
|
+
})();
|
|
6488
|
+
pendingLoads.set(name, loadPromise);
|
|
6489
|
+
return loadPromise;
|
|
6490
|
+
}
|
|
6491
|
+
async function preloadIcons(names) {
|
|
6492
|
+
await Promise.all(names.map(loadIcon));
|
|
6493
|
+
}
|
|
6494
|
+
function isIconLoaded(name) {
|
|
6495
|
+
return iconCache.has(name);
|
|
6496
|
+
}
|
|
6497
|
+
|
|
6498
|
+
// src/icons/DynamicIcon.tsx
|
|
6499
|
+
import { Fragment as Fragment4, jsx as jsx17 } from "react/jsx-runtime";
|
|
6500
|
+
function DynamicIconComponent({
|
|
6501
|
+
name,
|
|
6502
|
+
fallback = null,
|
|
6503
|
+
className,
|
|
6504
|
+
size = 24,
|
|
6505
|
+
stroke = 2,
|
|
6506
|
+
...props
|
|
6507
|
+
}) {
|
|
6508
|
+
const cachedIcon = getIcon(name);
|
|
6509
|
+
const [Icon, setIcon] = useState17(cachedIcon);
|
|
6510
|
+
const [isLoading, setIsLoading] = useState17(!cachedIcon && !!name);
|
|
6511
|
+
useEffect17(() => {
|
|
6512
|
+
if (!name) {
|
|
6513
|
+
setIcon(null);
|
|
6514
|
+
setIsLoading(false);
|
|
6515
|
+
return;
|
|
6516
|
+
}
|
|
6517
|
+
const cached = getIcon(name);
|
|
6518
|
+
if (cached) {
|
|
6519
|
+
setIcon(cached);
|
|
6520
|
+
setIsLoading(false);
|
|
6521
|
+
return;
|
|
6522
|
+
}
|
|
6523
|
+
setIsLoading(true);
|
|
6524
|
+
let cancelled = false;
|
|
6525
|
+
loadIcon(name).then((LoadedIcon) => {
|
|
6526
|
+
if (!cancelled) {
|
|
6527
|
+
setIcon(LoadedIcon);
|
|
6528
|
+
setIsLoading(false);
|
|
6529
|
+
}
|
|
6530
|
+
});
|
|
6531
|
+
return () => {
|
|
6532
|
+
cancelled = true;
|
|
6533
|
+
};
|
|
6534
|
+
}, [name]);
|
|
6535
|
+
if (!name) {
|
|
6536
|
+
return null;
|
|
6537
|
+
}
|
|
6538
|
+
if (isLoading || !Icon) {
|
|
6539
|
+
if (fallback) {
|
|
6540
|
+
return /* @__PURE__ */ jsx17(Fragment4, { children: fallback });
|
|
6541
|
+
}
|
|
6542
|
+
return /* @__PURE__ */ jsx17(
|
|
6543
|
+
"span",
|
|
6544
|
+
{
|
|
6545
|
+
className,
|
|
6546
|
+
style: {
|
|
6547
|
+
display: "inline-flex",
|
|
6548
|
+
width: size,
|
|
6549
|
+
height: size
|
|
6550
|
+
},
|
|
6551
|
+
"aria-hidden": "true"
|
|
6552
|
+
}
|
|
6553
|
+
);
|
|
6554
|
+
}
|
|
6555
|
+
return /* @__PURE__ */ jsx17(Icon, { size, stroke, className, ...props });
|
|
6556
|
+
}
|
|
6557
|
+
var DynamicIcon = memo(DynamicIconComponent);
|
|
6558
|
+
|
|
6559
|
+
// src/components/IconPicker.tsx
|
|
6560
|
+
import { useState as useState18, useEffect as useEffect18, useCallback as useCallback19, useRef as useRef18, useMemo as useMemo7 } from "react";
|
|
6561
|
+
|
|
6562
|
+
// src/icons/icon-metadata.ts
|
|
6563
|
+
var ICON_METADATA = [
|
|
6564
|
+
// ============================================================================
|
|
6565
|
+
// BRAND / SOCIAL MEDIA (~30 icons)
|
|
6566
|
+
// ============================================================================
|
|
6567
|
+
{ name: "IconBrandTwitter", category: "brand", keywords: ["twitter", "x", "social", "tweet"] },
|
|
6568
|
+
{ name: "IconBrandX", category: "brand", keywords: ["twitter", "x", "social"] },
|
|
6569
|
+
{ name: "IconBrandFacebook", category: "brand", keywords: ["facebook", "fb", "social", "meta"] },
|
|
6570
|
+
{ name: "IconBrandInstagram", category: "brand", keywords: ["instagram", "ig", "social", "photo"] },
|
|
6571
|
+
{ name: "IconBrandLinkedin", category: "brand", keywords: ["linkedin", "professional", "social", "job"] },
|
|
6572
|
+
{ name: "IconBrandYoutube", category: "brand", keywords: ["youtube", "video", "social", "stream"] },
|
|
6573
|
+
{ name: "IconBrandTiktok", category: "brand", keywords: ["tiktok", "video", "social", "short"] },
|
|
6574
|
+
{ name: "IconBrandSpotify", category: "brand", keywords: ["spotify", "music", "streaming", "audio"] },
|
|
6575
|
+
{ name: "IconBrandApple", category: "brand", keywords: ["apple", "mac", "ios", "iphone"] },
|
|
6576
|
+
{ name: "IconBrandApplePodcast", category: "brand", keywords: ["apple", "podcast", "audio"] },
|
|
6577
|
+
{ name: "IconBrandAppleMusic", category: "brand", keywords: ["apple", "music", "streaming", "audio", "itunes"] },
|
|
6578
|
+
{ name: "IconBrandGithub", category: "brand", keywords: ["github", "code", "git", "developer"] },
|
|
6579
|
+
{ name: "IconBrandDiscord", category: "brand", keywords: ["discord", "chat", "gaming", "community"] },
|
|
6580
|
+
{ name: "IconBrandSlack", category: "brand", keywords: ["slack", "chat", "work", "team"] },
|
|
6581
|
+
{ name: "IconBrandWhatsapp", category: "brand", keywords: ["whatsapp", "message", "chat", "phone"] },
|
|
6582
|
+
{ name: "IconBrandTelegram", category: "brand", keywords: ["telegram", "message", "chat"] },
|
|
6583
|
+
{ name: "IconBrandSnapchat", category: "brand", keywords: ["snapchat", "snap", "social", "photo"] },
|
|
6584
|
+
{ name: "IconBrandPinterest", category: "brand", keywords: ["pinterest", "pin", "social", "image"] },
|
|
6585
|
+
{ name: "IconBrandDribbble", category: "brand", keywords: ["dribbble", "design", "portfolio"] },
|
|
6586
|
+
{ name: "IconBrandBehance", category: "brand", keywords: ["behance", "design", "portfolio", "adobe"] },
|
|
6587
|
+
{ name: "IconBrandFigma", category: "brand", keywords: ["figma", "design", "ui", "prototype"] },
|
|
6588
|
+
{ name: "IconBrandStripe", category: "brand", keywords: ["stripe", "payment", "money"] },
|
|
6589
|
+
{ name: "IconBrandPaypal", category: "brand", keywords: ["paypal", "payment", "money"] },
|
|
6590
|
+
{ name: "IconBrandAmazon", category: "brand", keywords: ["amazon", "shop", "ecommerce"] },
|
|
6591
|
+
{ name: "IconBrandGoogle", category: "brand", keywords: ["google", "search", "gmail"] },
|
|
6592
|
+
{ name: "IconBrandMedium", category: "brand", keywords: ["medium", "blog", "writing", "article"] },
|
|
6593
|
+
{ name: "IconBrandReddit", category: "brand", keywords: ["reddit", "social", "community", "forum"] },
|
|
6594
|
+
{ name: "IconBrandTwitch", category: "brand", keywords: ["twitch", "stream", "gaming", "video"] },
|
|
6595
|
+
{ name: "IconBrandSoundcloud", category: "brand", keywords: ["soundcloud", "music", "audio", "stream"] },
|
|
6596
|
+
{ name: "IconBrandVimeo", category: "brand", keywords: ["vimeo", "video", "film"] },
|
|
6597
|
+
{ name: "IconBrandPatreon", category: "brand", keywords: ["patreon", "creator", "support", "subscription"] },
|
|
6598
|
+
// ============================================================================
|
|
6599
|
+
// COMMUNICATION (~15 icons)
|
|
6600
|
+
// ============================================================================
|
|
6601
|
+
{ name: "IconMail", category: "communication", keywords: ["mail", "email", "envelope", "message"] },
|
|
6602
|
+
{ name: "IconMailOpened", category: "communication", keywords: ["mail", "email", "open", "read"] },
|
|
6603
|
+
{ name: "IconInbox", category: "communication", keywords: ["inbox", "mail", "message"] },
|
|
6604
|
+
{ name: "IconSend", category: "communication", keywords: ["send", "submit", "message", "arrow"] },
|
|
6605
|
+
{ name: "IconPhone", category: "communication", keywords: ["phone", "call", "contact", "mobile"] },
|
|
6606
|
+
{ name: "IconPhoneCall", category: "communication", keywords: ["phone", "call", "ringing"] },
|
|
6607
|
+
{ name: "IconMessage", category: "communication", keywords: ["message", "chat", "bubble", "sms"] },
|
|
6608
|
+
{ name: "IconMessageCircle", category: "communication", keywords: ["message", "chat", "bubble"] },
|
|
6609
|
+
{ name: "IconMessages", category: "communication", keywords: ["messages", "chat", "conversation"] },
|
|
6610
|
+
{ name: "IconAt", category: "communication", keywords: ["at", "email", "mention", "address"] },
|
|
6611
|
+
{ name: "IconBell", category: "communication", keywords: ["bell", "notification", "alert"] },
|
|
6612
|
+
{ name: "IconBellRinging", category: "communication", keywords: ["bell", "notification", "alert", "ring"] },
|
|
6613
|
+
{ name: "IconBroadcast", category: "communication", keywords: ["broadcast", "live", "stream", "radio"] },
|
|
6614
|
+
{ name: "IconMicrophone", category: "communication", keywords: ["microphone", "audio", "voice", "record"] },
|
|
6615
|
+
{ name: "IconVideo", category: "communication", keywords: ["video", "camera", "record", "call"] },
|
|
6616
|
+
// ============================================================================
|
|
6617
|
+
// MEDIA (~20 icons)
|
|
6618
|
+
// ============================================================================
|
|
6619
|
+
{ name: "IconPlayerPlay", category: "media", keywords: ["play", "video", "start", "media"] },
|
|
6620
|
+
{ name: "IconPlayerPause", category: "media", keywords: ["pause", "stop", "media"] },
|
|
6621
|
+
{ name: "IconPlayerStop", category: "media", keywords: ["stop", "media", "end"] },
|
|
6622
|
+
{ name: "IconPlayerSkipForward", category: "media", keywords: ["skip", "forward", "next"] },
|
|
6623
|
+
{ name: "IconPlayerSkipBack", category: "media", keywords: ["skip", "back", "previous"] },
|
|
6624
|
+
{ name: "IconPlayerRecord", category: "media", keywords: ["record", "recording", "media"] },
|
|
6625
|
+
{ name: "IconVolume", category: "media", keywords: ["volume", "sound", "audio", "speaker"] },
|
|
6626
|
+
{ name: "IconVolume2", category: "media", keywords: ["volume", "sound", "audio", "medium"] },
|
|
6627
|
+
{ name: "IconVolume3", category: "media", keywords: ["volume", "sound", "audio", "high"] },
|
|
6628
|
+
{ name: "IconVolumeOff", category: "media", keywords: ["volume", "mute", "silent", "off"] },
|
|
6629
|
+
{ name: "IconMusic", category: "media", keywords: ["music", "audio", "note", "song"] },
|
|
6630
|
+
{ name: "IconPlaylist", category: "media", keywords: ["playlist", "music", "queue", "list"] },
|
|
6631
|
+
{ name: "IconHeadphones", category: "media", keywords: ["headphones", "audio", "music", "listen"] },
|
|
6632
|
+
{ name: "IconCamera", category: "media", keywords: ["camera", "photo", "picture", "capture"] },
|
|
6633
|
+
{ name: "IconPhoto", category: "media", keywords: ["photo", "image", "picture", "gallery"] },
|
|
6634
|
+
{ name: "IconMovie", category: "media", keywords: ["movie", "film", "video", "cinema"] },
|
|
6635
|
+
{ name: "IconScreenShare", category: "media", keywords: ["screen", "share", "present", "display"] },
|
|
6636
|
+
{ name: "IconCast", category: "media", keywords: ["cast", "chromecast", "stream", "tv"] },
|
|
6637
|
+
{ name: "IconPodium", category: "media", keywords: ["podium", "present", "speech", "stage"] },
|
|
6638
|
+
{ name: "IconVinyl", category: "media", keywords: ["vinyl", "record", "music", "retro"] },
|
|
6639
|
+
// ============================================================================
|
|
6640
|
+
// NAVIGATION (~20 icons)
|
|
6641
|
+
// ============================================================================
|
|
6642
|
+
{ name: "IconArrowRight", category: "navigation", keywords: ["arrow", "right", "next", "forward"] },
|
|
6643
|
+
{ name: "IconArrowLeft", category: "navigation", keywords: ["arrow", "left", "back", "previous"] },
|
|
6644
|
+
{ name: "IconArrowUp", category: "navigation", keywords: ["arrow", "up", "top"] },
|
|
6645
|
+
{ name: "IconArrowDown", category: "navigation", keywords: ["arrow", "down", "bottom"] },
|
|
6646
|
+
{ name: "IconArrowUpRight", category: "navigation", keywords: ["arrow", "external", "link", "open"] },
|
|
6647
|
+
{ name: "IconChevronRight", category: "navigation", keywords: ["chevron", "right", "next", "expand"] },
|
|
6648
|
+
{ name: "IconChevronLeft", category: "navigation", keywords: ["chevron", "left", "back", "collapse"] },
|
|
6649
|
+
{ name: "IconChevronUp", category: "navigation", keywords: ["chevron", "up", "expand"] },
|
|
6650
|
+
{ name: "IconChevronDown", category: "navigation", keywords: ["chevron", "down", "dropdown", "collapse"] },
|
|
6651
|
+
{ name: "IconMenu2", category: "navigation", keywords: ["menu", "hamburger", "nav", "mobile"] },
|
|
6652
|
+
{ name: "IconX", category: "navigation", keywords: ["close", "x", "cancel", "remove"] },
|
|
6653
|
+
{ name: "IconHome", category: "navigation", keywords: ["home", "house", "main", "start"] },
|
|
6654
|
+
{ name: "IconSearch", category: "navigation", keywords: ["search", "find", "magnify", "lookup"] },
|
|
6655
|
+
{ name: "IconExternalLink", category: "navigation", keywords: ["external", "link", "open", "new"] },
|
|
6656
|
+
{ name: "IconLink", category: "navigation", keywords: ["link", "chain", "url", "connect"] },
|
|
6657
|
+
{ name: "IconAnchor", category: "navigation", keywords: ["anchor", "link", "section", "scroll"] },
|
|
6658
|
+
{ name: "IconMapPin", category: "navigation", keywords: ["map", "pin", "location", "place"] },
|
|
6659
|
+
{ name: "IconMap", category: "navigation", keywords: ["map", "location", "directions"] },
|
|
6660
|
+
{ name: "IconCompass", category: "navigation", keywords: ["compass", "direction", "explore", "navigate"] },
|
|
6661
|
+
{ name: "IconRefresh", category: "navigation", keywords: ["refresh", "reload", "update", "sync"] },
|
|
6662
|
+
// ============================================================================
|
|
6663
|
+
// COMMERCE (~20 icons)
|
|
6664
|
+
// ============================================================================
|
|
6665
|
+
{ name: "IconShoppingCart", category: "commerce", keywords: ["cart", "shop", "buy", "ecommerce"] },
|
|
6666
|
+
{ name: "IconShoppingBag", category: "commerce", keywords: ["bag", "shop", "buy", "store"] },
|
|
6667
|
+
{ name: "IconBasket", category: "commerce", keywords: ["basket", "shop", "buy", "cart"] },
|
|
6668
|
+
{ name: "IconCreditCard", category: "commerce", keywords: ["credit", "card", "payment", "pay"] },
|
|
6669
|
+
{ name: "IconWallet", category: "commerce", keywords: ["wallet", "money", "payment", "cash"] },
|
|
6670
|
+
{ name: "IconCash", category: "commerce", keywords: ["cash", "money", "payment", "dollar"] },
|
|
6671
|
+
{ name: "IconReceipt", category: "commerce", keywords: ["receipt", "invoice", "bill", "payment"] },
|
|
6672
|
+
{ name: "IconTruck", category: "commerce", keywords: ["truck", "delivery", "shipping", "transport"] },
|
|
6673
|
+
{ name: "IconPackage", category: "commerce", keywords: ["package", "box", "shipping", "delivery"] },
|
|
6674
|
+
{ name: "IconGift", category: "commerce", keywords: ["gift", "present", "reward", "prize"] },
|
|
6675
|
+
{ name: "IconTicket", category: "commerce", keywords: ["ticket", "event", "coupon", "pass"] },
|
|
6676
|
+
{ name: "IconTag", category: "commerce", keywords: ["tag", "label", "price", "sale"] },
|
|
6677
|
+
{ name: "IconTags", category: "commerce", keywords: ["tags", "labels", "categories"] },
|
|
6678
|
+
{ name: "IconDiscount", category: "commerce", keywords: ["discount", "sale", "percent", "offer"] },
|
|
6679
|
+
{ name: "IconBuildingStore", category: "commerce", keywords: ["store", "shop", "building", "retail"] },
|
|
6680
|
+
{ name: "IconStarFilled", category: "commerce", keywords: ["star", "rating", "review", "favorite"] },
|
|
6681
|
+
{ name: "IconStar", category: "commerce", keywords: ["star", "rating", "review", "favorite"] },
|
|
6682
|
+
{ name: "IconHeart", category: "commerce", keywords: ["heart", "like", "love", "favorite", "wishlist"] },
|
|
6683
|
+
{ name: "IconHeartFilled", category: "commerce", keywords: ["heart", "like", "love", "favorite", "wishlist"] },
|
|
6684
|
+
{ name: "IconCoin", category: "commerce", keywords: ["coin", "money", "currency", "token"] },
|
|
6685
|
+
// ============================================================================
|
|
6686
|
+
// UI ELEMENTS (~25 icons)
|
|
6687
|
+
// ============================================================================
|
|
6688
|
+
{ name: "IconPlus", category: "ui", keywords: ["plus", "add", "new", "create"] },
|
|
6689
|
+
{ name: "IconMinus", category: "ui", keywords: ["minus", "remove", "subtract"] },
|
|
6690
|
+
{ name: "IconCheck", category: "ui", keywords: ["check", "done", "complete", "success"] },
|
|
6691
|
+
{ name: "IconCircleCheck", category: "ui", keywords: ["check", "done", "complete", "circle"] },
|
|
6692
|
+
{ name: "IconCircleX", category: "ui", keywords: ["close", "error", "fail", "circle"] },
|
|
6693
|
+
{ name: "IconAlertCircle", category: "ui", keywords: ["alert", "warning", "error", "info"] },
|
|
6694
|
+
{ name: "IconAlertTriangle", category: "ui", keywords: ["alert", "warning", "caution", "danger"] },
|
|
6695
|
+
{ name: "IconInfoCircle", category: "ui", keywords: ["info", "information", "help", "about"] },
|
|
6696
|
+
{ name: "IconQuestionMark", category: "ui", keywords: ["question", "help", "faq", "support"] },
|
|
6697
|
+
{ name: "IconHelp", category: "ui", keywords: ["help", "support", "question", "assist"] },
|
|
6698
|
+
{ name: "IconSettings", category: "ui", keywords: ["settings", "gear", "config", "preferences"] },
|
|
6699
|
+
{ name: "IconAdjustments", category: "ui", keywords: ["adjustments", "settings", "sliders", "filter"] },
|
|
6700
|
+
{ name: "IconFilter", category: "ui", keywords: ["filter", "sort", "funnel"] },
|
|
6701
|
+
{ name: "IconDotsVertical", category: "ui", keywords: ["dots", "menu", "more", "options"] },
|
|
6702
|
+
{ name: "IconDots", category: "ui", keywords: ["dots", "menu", "more", "options", "horizontal"] },
|
|
6703
|
+
{ name: "IconEdit", category: "ui", keywords: ["edit", "pencil", "modify", "write"] },
|
|
6704
|
+
{ name: "IconTrash", category: "ui", keywords: ["trash", "delete", "remove", "bin"] },
|
|
6705
|
+
{ name: "IconCopy", category: "ui", keywords: ["copy", "duplicate", "clone"] },
|
|
6706
|
+
{ name: "IconDownload", category: "ui", keywords: ["download", "save", "export", "arrow"] },
|
|
6707
|
+
{ name: "IconUpload", category: "ui", keywords: ["upload", "import", "add", "arrow"] },
|
|
6708
|
+
{ name: "IconShare", category: "ui", keywords: ["share", "social", "send", "export"] },
|
|
6709
|
+
{ name: "IconShare2", category: "ui", keywords: ["share", "network", "connect"] },
|
|
6710
|
+
{ name: "IconEye", category: "ui", keywords: ["eye", "view", "visible", "show"] },
|
|
6711
|
+
{ name: "IconEyeOff", category: "ui", keywords: ["eye", "hidden", "invisible", "hide"] },
|
|
6712
|
+
{ name: "IconLock", category: "ui", keywords: ["lock", "secure", "private", "password"] },
|
|
6713
|
+
{ name: "IconLockOpen", category: "ui", keywords: ["unlock", "open", "public", "access"] },
|
|
6714
|
+
// ============================================================================
|
|
6715
|
+
// FILES & DOCUMENTS (~15 icons)
|
|
6716
|
+
// ============================================================================
|
|
6717
|
+
{ name: "IconFile", category: "files", keywords: ["file", "document", "page"] },
|
|
6718
|
+
{ name: "IconFileText", category: "files", keywords: ["file", "document", "text", "page"] },
|
|
6719
|
+
{ name: "IconFileTypePdf", category: "files", keywords: ["pdf", "file", "document", "adobe"] },
|
|
6720
|
+
{ name: "IconFileMusic", category: "files", keywords: ["file", "music", "audio", "mp3"] },
|
|
6721
|
+
{ name: "IconVideo", category: "files", keywords: ["file", "video", "movie", "mp4"] },
|
|
6722
|
+
{ name: "IconPhoto", category: "files", keywords: ["file", "image", "photo", "picture"] },
|
|
6723
|
+
{ name: "IconFileCode", category: "files", keywords: ["file", "code", "programming", "dev"] },
|
|
6724
|
+
{ name: "IconFileZip", category: "files", keywords: ["file", "zip", "archive", "compress"] },
|
|
6725
|
+
{ name: "IconFolder", category: "files", keywords: ["folder", "directory", "files"] },
|
|
6726
|
+
{ name: "IconFolderOpen", category: "files", keywords: ["folder", "open", "directory"] },
|
|
6727
|
+
{ name: "IconClipboard", category: "files", keywords: ["clipboard", "paste", "copy"] },
|
|
6728
|
+
{ name: "IconClipboardCheck", category: "files", keywords: ["clipboard", "done", "complete"] },
|
|
6729
|
+
{ name: "IconNotes", category: "files", keywords: ["notes", "document", "memo", "write"] },
|
|
6730
|
+
{ name: "IconBook", category: "files", keywords: ["book", "read", "documentation", "manual"] },
|
|
6731
|
+
{ name: "IconBookmark", category: "files", keywords: ["bookmark", "save", "favorite", "mark"] },
|
|
6732
|
+
// ============================================================================
|
|
6733
|
+
// WEATHER (~10 icons)
|
|
6734
|
+
// ============================================================================
|
|
6735
|
+
{ name: "IconSun", category: "weather", keywords: ["sun", "sunny", "day", "bright"] },
|
|
6736
|
+
{ name: "IconMoon", category: "weather", keywords: ["moon", "night", "dark", "sleep"] },
|
|
6737
|
+
{ name: "IconCloud", category: "weather", keywords: ["cloud", "cloudy", "weather"] },
|
|
6738
|
+
{ name: "IconCloudRain", category: "weather", keywords: ["cloud", "rain", "weather", "rainy"] },
|
|
6739
|
+
{ name: "IconCloudSnow", category: "weather", keywords: ["cloud", "snow", "weather", "winter"] },
|
|
6740
|
+
{ name: "IconWind", category: "weather", keywords: ["wind", "windy", "weather", "air"] },
|
|
6741
|
+
{ name: "IconUmbrella", category: "weather", keywords: ["umbrella", "rain", "weather", "protection"] },
|
|
6742
|
+
{ name: "IconTemperature", category: "weather", keywords: ["temperature", "thermometer", "weather"] },
|
|
6743
|
+
{ name: "IconFlame", category: "weather", keywords: ["flame", "fire", "hot", "trending"] },
|
|
6744
|
+
{ name: "IconSnowflake", category: "weather", keywords: ["snowflake", "snow", "winter", "cold"] },
|
|
6745
|
+
// ============================================================================
|
|
6746
|
+
// MISCELLANEOUS (~15 icons)
|
|
6747
|
+
// ============================================================================
|
|
6748
|
+
{ name: "IconUser", category: "misc", keywords: ["user", "person", "account", "profile"] },
|
|
6749
|
+
{ name: "IconUsers", category: "misc", keywords: ["users", "people", "team", "group"] },
|
|
6750
|
+
{ name: "IconUserCircle", category: "misc", keywords: ["user", "avatar", "profile", "account"] },
|
|
6751
|
+
{ name: "IconBriefcase", category: "misc", keywords: ["briefcase", "work", "job", "business"] },
|
|
6752
|
+
{ name: "IconBuilding", category: "misc", keywords: ["building", "office", "company", "business"] },
|
|
6753
|
+
{ name: "IconCalendar", category: "misc", keywords: ["calendar", "date", "schedule", "event"] },
|
|
6754
|
+
{ name: "IconCalendarEvent", category: "misc", keywords: ["calendar", "event", "schedule", "meeting"] },
|
|
6755
|
+
{ name: "IconClock", category: "misc", keywords: ["clock", "time", "hour", "schedule"] },
|
|
6756
|
+
{ name: "IconHourglass", category: "misc", keywords: ["hourglass", "time", "wait", "timer"] },
|
|
6757
|
+
{ name: "IconRocket", category: "misc", keywords: ["rocket", "launch", "startup", "fast"] },
|
|
6758
|
+
{ name: "IconBolt", category: "misc", keywords: ["bolt", "lightning", "fast", "power"] },
|
|
6759
|
+
{ name: "IconSparkles", category: "misc", keywords: ["sparkles", "magic", "new", "ai"] },
|
|
6760
|
+
{ name: "IconTrophy", category: "misc", keywords: ["trophy", "award", "winner", "achievement"] },
|
|
6761
|
+
{ name: "IconTarget", category: "misc", keywords: ["target", "goal", "aim", "focus"] },
|
|
6762
|
+
{ name: "IconWorld", category: "misc", keywords: ["world", "globe", "earth", "international"] }
|
|
6763
|
+
];
|
|
6764
|
+
var ICON_CATEGORIES = {
|
|
6765
|
+
brand: "Social & Brands",
|
|
6766
|
+
communication: "Communication",
|
|
6767
|
+
media: "Media",
|
|
6768
|
+
navigation: "Navigation",
|
|
6769
|
+
commerce: "Commerce",
|
|
6770
|
+
ui: "UI Elements",
|
|
6771
|
+
files: "Files",
|
|
6772
|
+
weather: "Weather",
|
|
6773
|
+
misc: "Miscellaneous"
|
|
6774
|
+
};
|
|
6775
|
+
var ICON_ALIASES = {
|
|
6776
|
+
// Social media rebrands & abbreviations
|
|
6777
|
+
"x": ["IconBrandTwitter", "IconBrandX", "IconX"],
|
|
6778
|
+
"tweet": ["IconBrandTwitter", "IconBrandX"],
|
|
6779
|
+
"bird": ["IconBrandTwitter"],
|
|
6780
|
+
"ig": ["IconBrandInstagram"],
|
|
6781
|
+
"insta": ["IconBrandInstagram"],
|
|
6782
|
+
"gram": ["IconBrandInstagram"],
|
|
6783
|
+
"fb": ["IconBrandFacebook"],
|
|
6784
|
+
"meta": ["IconBrandFacebook", "IconBrandInstagram", "IconBrandWhatsapp"],
|
|
6785
|
+
"li": ["IconBrandLinkedin"],
|
|
6786
|
+
"yt": ["IconBrandYoutube"],
|
|
6787
|
+
"tt": ["IconBrandTiktok"],
|
|
6788
|
+
"gh": ["IconBrandGithub"],
|
|
6789
|
+
"wa": ["IconBrandWhatsapp"],
|
|
6790
|
+
"am": ["IconBrandAppleMusic"],
|
|
6791
|
+
"applemusic": ["IconBrandAppleMusic"],
|
|
6792
|
+
"itunes": ["IconBrandAppleMusic"],
|
|
6793
|
+
// Common abbreviations
|
|
6794
|
+
"email": ["IconMail", "IconMailOpened", "IconInbox", "IconAt"],
|
|
6795
|
+
"envelope": ["IconMail", "IconMailOpened"],
|
|
6796
|
+
"telephone": ["IconPhone", "IconPhoneCall"],
|
|
6797
|
+
"mobile": ["IconPhone", "IconPhoneCall"],
|
|
6798
|
+
"cell": ["IconPhone", "IconPhoneCall"],
|
|
6799
|
+
"sms": ["IconMessage", "IconMessageCircle", "IconMessages"],
|
|
6800
|
+
"txt": ["IconMessage", "IconMessageCircle"],
|
|
6801
|
+
"text": ["IconMessage", "IconMessageCircle", "IconFileText"],
|
|
6802
|
+
// Commerce
|
|
6803
|
+
"basket": ["IconShoppingCart", "IconShoppingBag", "IconBasket"],
|
|
6804
|
+
"buy": ["IconShoppingCart", "IconShoppingBag", "IconCreditCard"],
|
|
6805
|
+
"purchase": ["IconShoppingCart", "IconCreditCard", "IconReceipt"],
|
|
6806
|
+
"checkout": ["IconShoppingCart", "IconCreditCard"],
|
|
6807
|
+
"pay": ["IconCreditCard", "IconWallet", "IconCash", "IconBrandStripe", "IconBrandPaypal"],
|
|
6808
|
+
"money": ["IconCash", "IconWallet", "IconCoin", "IconCreditCard"],
|
|
6809
|
+
"dollar": ["IconCash", "IconCoin"],
|
|
6810
|
+
"ship": ["IconTruck", "IconPackage"],
|
|
6811
|
+
"deliver": ["IconTruck", "IconPackage"],
|
|
6812
|
+
// Common UI terms
|
|
6813
|
+
"close": ["IconX", "IconCircleX"],
|
|
6814
|
+
"cancel": ["IconX", "IconCircleX"],
|
|
6815
|
+
"remove": ["IconX", "IconTrash", "IconMinus"],
|
|
6816
|
+
"delete": ["IconTrash", "IconX"],
|
|
6817
|
+
"add": ["IconPlus", "IconUpload"],
|
|
6818
|
+
"new": ["IconPlus", "IconSparkles"],
|
|
6819
|
+
"create": ["IconPlus", "IconEdit"],
|
|
6820
|
+
"ok": ["IconCheck", "IconCircleCheck"],
|
|
6821
|
+
"yes": ["IconCheck", "IconCircleCheck"],
|
|
6822
|
+
"done": ["IconCheck", "IconCircleCheck", "IconClipboardCheck"],
|
|
6823
|
+
"complete": ["IconCheck", "IconCircleCheck"],
|
|
6824
|
+
"success": ["IconCheck", "IconCircleCheck"],
|
|
6825
|
+
"error": ["IconCircleX", "IconAlertCircle", "IconAlertTriangle"],
|
|
6826
|
+
"warning": ["IconAlertTriangle", "IconAlertCircle"],
|
|
6827
|
+
"info": ["IconInfoCircle", "IconHelp"],
|
|
6828
|
+
"help": ["IconHelp", "IconQuestionMark", "IconInfoCircle"],
|
|
6829
|
+
"faq": ["IconQuestionMark", "IconHelp"],
|
|
6830
|
+
"gear": ["IconSettings", "IconAdjustments"],
|
|
6831
|
+
"cog": ["IconSettings"],
|
|
6832
|
+
"config": ["IconSettings", "IconAdjustments"],
|
|
6833
|
+
"prefs": ["IconSettings", "IconAdjustments"],
|
|
6834
|
+
"menu": ["IconMenu2", "IconDotsVertical", "IconDotsHorizontal"],
|
|
6835
|
+
"hamburger": ["IconMenu2"],
|
|
6836
|
+
"more": ["IconDotsVertical", "IconDotsHorizontal"],
|
|
6837
|
+
"options": ["IconDotsVertical", "IconDotsHorizontal", "IconSettings"],
|
|
6838
|
+
// Navigation
|
|
6839
|
+
"next": ["IconArrowRight", "IconChevronRight", "IconPlayerSkipForward"],
|
|
6840
|
+
"prev": ["IconArrowLeft", "IconChevronLeft", "IconPlayerSkipBack"],
|
|
6841
|
+
"previous": ["IconArrowLeft", "IconChevronLeft", "IconPlayerSkipBack"],
|
|
6842
|
+
"back": ["IconArrowLeft", "IconChevronLeft"],
|
|
6843
|
+
"forward": ["IconArrowRight", "IconChevronRight", "IconPlayerSkipForward"],
|
|
6844
|
+
"up": ["IconArrowUp", "IconChevronUp"],
|
|
6845
|
+
"down": ["IconArrowDown", "IconChevronDown"],
|
|
6846
|
+
"external": ["IconExternalLink", "IconArrowUpRight"],
|
|
6847
|
+
"outbound": ["IconExternalLink", "IconArrowUpRight"],
|
|
6848
|
+
// Media
|
|
6849
|
+
"start": ["IconPlayerPlay"],
|
|
6850
|
+
"stop": ["IconPlayerStop", "IconPlayerPause"],
|
|
6851
|
+
"mute": ["IconVolumeOff"],
|
|
6852
|
+
"silent": ["IconVolumeOff", "IconBellOff"],
|
|
6853
|
+
"audio": ["IconVolume", "IconMusic", "IconHeadphones", "IconMicrophone"],
|
|
6854
|
+
"sound": ["IconVolume", "IconVolume2", "IconVolume3"],
|
|
6855
|
+
"speaker": ["IconVolume", "IconVolume2", "IconVolume3"],
|
|
6856
|
+
"mic": ["IconMicrophone"],
|
|
6857
|
+
"cam": ["IconCamera", "IconVideo"],
|
|
6858
|
+
"pic": ["IconPhoto", "IconCamera", "IconFileImage"],
|
|
6859
|
+
"img": ["IconPhoto", "IconFileImage"],
|
|
6860
|
+
"image": ["IconPhoto", "IconFileImage"],
|
|
6861
|
+
"picture": ["IconPhoto", "IconFileImage"],
|
|
6862
|
+
// Misc
|
|
6863
|
+
"person": ["IconUser", "IconUserCircle"],
|
|
6864
|
+
"profile": ["IconUser", "IconUserCircle"],
|
|
6865
|
+
"account": ["IconUser", "IconUserCircle"],
|
|
6866
|
+
"avatar": ["IconUserCircle"],
|
|
6867
|
+
"people": ["IconUsers"],
|
|
6868
|
+
"team": ["IconUsers"],
|
|
6869
|
+
"group": ["IconUsers"],
|
|
6870
|
+
"date": ["IconCalendar", "IconCalendarEvent"],
|
|
6871
|
+
"schedule": ["IconCalendar", "IconCalendarEvent", "IconClock"],
|
|
6872
|
+
"event": ["IconCalendar", "IconCalendarEvent", "IconTicket"],
|
|
6873
|
+
"time": ["IconClock", "IconHourglass"],
|
|
6874
|
+
"hour": ["IconClock"],
|
|
6875
|
+
"fast": ["IconRocket", "IconBolt"],
|
|
6876
|
+
"quick": ["IconRocket", "IconBolt"],
|
|
6877
|
+
"magic": ["IconSparkles"],
|
|
6878
|
+
"ai": ["IconSparkles", "IconRocket"],
|
|
6879
|
+
"globe": ["IconWorld"],
|
|
6880
|
+
"earth": ["IconWorld"],
|
|
6881
|
+
"international": ["IconWorld"],
|
|
6882
|
+
"hot": ["IconFlame", "IconTrending"],
|
|
6883
|
+
"fire": ["IconFlame"],
|
|
6884
|
+
"trending": ["IconFlame"]
|
|
6885
|
+
};
|
|
6886
|
+
function levenshteinDistance(str1, str2) {
|
|
6887
|
+
const m = str1.length;
|
|
6888
|
+
const n = str2.length;
|
|
6889
|
+
if (m === 0) return n;
|
|
6890
|
+
if (n === 0) return m;
|
|
6891
|
+
const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
|
|
6892
|
+
for (let i = 0; i <= m; i++) dp[i][0] = i;
|
|
6893
|
+
for (let j = 0; j <= n; j++) dp[0][j] = j;
|
|
6894
|
+
for (let i = 1; i <= m; i++) {
|
|
6895
|
+
for (let j = 1; j <= n; j++) {
|
|
6896
|
+
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
6897
|
+
dp[i][j] = Math.min(
|
|
6898
|
+
dp[i - 1][j] + 1,
|
|
6899
|
+
// deletion
|
|
6900
|
+
dp[i][j - 1] + 1,
|
|
6901
|
+
// insertion
|
|
6902
|
+
dp[i - 1][j - 1] + cost
|
|
6903
|
+
// substitution
|
|
6904
|
+
);
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
return dp[m][n];
|
|
6908
|
+
}
|
|
6909
|
+
function fuzzyMatch(query, target) {
|
|
6910
|
+
if (query.length < 3) return false;
|
|
6911
|
+
const threshold = query.length <= 5 ? 1 : 2;
|
|
6912
|
+
return levenshteinDistance(query, target) <= threshold;
|
|
6913
|
+
}
|
|
6914
|
+
function getIconsByCategory(category) {
|
|
6915
|
+
return ICON_METADATA.filter((icon) => icon.category === category);
|
|
6916
|
+
}
|
|
6917
|
+
function searchIcons(query) {
|
|
6918
|
+
const lowerQuery = query.toLowerCase().trim();
|
|
6919
|
+
if (!lowerQuery) return ICON_METADATA;
|
|
6920
|
+
const matches = /* @__PURE__ */ new Map();
|
|
6921
|
+
const addMatch = (iconName, score) => {
|
|
6922
|
+
const existing = matches.get(iconName);
|
|
6923
|
+
if (existing === void 0 || score < existing) {
|
|
6924
|
+
matches.set(iconName, score);
|
|
6925
|
+
}
|
|
6926
|
+
};
|
|
6927
|
+
const aliasMatches = ICON_ALIASES[lowerQuery];
|
|
6928
|
+
if (aliasMatches) {
|
|
6929
|
+
aliasMatches.forEach((iconName) => addMatch(iconName, 0));
|
|
6930
|
+
}
|
|
6931
|
+
for (const icon of ICON_METADATA) {
|
|
6932
|
+
const lowerName = icon.name.toLowerCase();
|
|
6933
|
+
if (lowerName.includes(lowerQuery)) {
|
|
6934
|
+
addMatch(icon.name, 1);
|
|
6935
|
+
continue;
|
|
6936
|
+
}
|
|
6937
|
+
if (icon.keywords.some((keyword) => keyword.includes(lowerQuery))) {
|
|
6938
|
+
addMatch(icon.name, 2);
|
|
6939
|
+
continue;
|
|
6940
|
+
}
|
|
6941
|
+
if (icon.keywords.some((keyword) => fuzzyMatch(lowerQuery, keyword))) {
|
|
6942
|
+
addMatch(icon.name, 3);
|
|
6943
|
+
continue;
|
|
6944
|
+
}
|
|
6945
|
+
const nameParts = icon.name.replace(/([A-Z])/g, " $1").toLowerCase().trim().split(/\s+/);
|
|
6946
|
+
if (nameParts.some((part) => fuzzyMatch(lowerQuery, part))) {
|
|
6947
|
+
addMatch(icon.name, 4);
|
|
6948
|
+
}
|
|
6949
|
+
}
|
|
6950
|
+
const sortedNames = [...matches.entries()].sort((a, b) => a[1] - b[1]).map(([name]) => name);
|
|
6951
|
+
return sortedNames.map((name) => ICON_METADATA.find((icon) => icon.name === name)).filter((icon) => icon !== void 0);
|
|
6952
|
+
}
|
|
6953
|
+
function getIconMeta(name) {
|
|
6954
|
+
return ICON_METADATA.find((icon) => icon.name === name);
|
|
6955
|
+
}
|
|
6956
|
+
function getIconLabel(name) {
|
|
6957
|
+
let label = name.replace(/^Icon/, "");
|
|
6958
|
+
label = label.replace(/^Brand/, "");
|
|
6959
|
+
label = label.replace(/([A-Z])/g, " $1").trim();
|
|
6960
|
+
return label;
|
|
6961
|
+
}
|
|
6962
|
+
|
|
6963
|
+
// src/components/icon-picker.css
|
|
6964
|
+
styleInject('.ya-icon-picker {\n min-width: 320px;\n max-width: 360px;\n background: #1a1a1a;\n border-radius: 12px;\n overflow: hidden;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.ya-icon-picker-search {\n padding: 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-icon-picker-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-icon-picker-input::placeholder {\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-icon-picker-input:focus {\n border-color: var(--color-primary, #D4A574);\n}\n.ya-icon-picker-categories {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-icon-category-btn {\n padding: 5px 10px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid transparent;\n border-radius: 6px;\n color: rgba(255, 255, 255, 0.7);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n.ya-icon-category-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n color: #ffffff;\n}\n.ya-icon-category-btn.is-active {\n background: var(--color-primary, #D4A574);\n color: #1a1a1a;\n border-color: var(--color-primary, #D4A574);\n}\n.ya-icon-picker-grid-container {\n position: relative;\n height: 264px;\n overflow: hidden;\n}\n.ya-icon-picker-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 4px;\n padding: 12px;\n height: 100%;\n overflow-y: auto;\n align-content: start;\n}\n.ya-icon-picker-grid::-webkit-scrollbar {\n width: 6px;\n}\n.ya-icon-picker-grid::-webkit-scrollbar-track {\n background: transparent;\n}\n.ya-icon-picker-grid::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n border-radius: 3px;\n}\n.ya-icon-picker-grid::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.3);\n}\n.ya-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid transparent;\n border-radius: 8px;\n color: rgba(255, 255, 255, 0.8);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.ya-icon-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.2);\n color: #ffffff;\n}\n.ya-icon-btn.is-selected {\n background: var(--color-primary, #D4A574);\n color: #1a1a1a;\n border-color: var(--color-primary, #D4A574);\n}\n.ya-icon-btn.is-focused {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: -2px;\n}\n.ya-icon-btn-none {\n position: relative;\n}\n.ya-icon-btn-none-x {\n font-size: 20px;\n line-height: 1;\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-icon-btn-none:hover .ya-icon-btn-none-x {\n color: rgba(255, 255, 255, 0.8);\n}\n.ya-icon-btn-none.is-selected .ya-icon-btn-none-x {\n color: #1a1a1a;\n}\n.ya-icon-picker-empty {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n color: rgba(255, 255, 255, 0.5);\n font-size: 13px;\n pointer-events: none;\n}\n.ya-icon-picker-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n background: rgba(255, 255, 255, 0.02);\n}\n.ya-icon-picker-selected-name {\n font-size: 12px;\n color: rgba(255, 255, 255, 0.7);\n}\n.ya-edit-icon-btn {\n display: flex;\n align-items: center;\n gap: 6px;\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-edit-icon-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.2);\n}\n.ya-edit-icon-preview {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n}\n.ya-edit-icon-label {\n flex: 1;\n}\n');
|
|
6965
|
+
|
|
6966
|
+
// src/components/IconPicker.tsx
|
|
6967
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
6968
|
+
function getIconPickerLabel(value) {
|
|
6969
|
+
if (!value) return "Icon";
|
|
6970
|
+
return getIconLabel(value);
|
|
6971
|
+
}
|
|
6972
|
+
function IconPicker({ value, onChange, onClose }) {
|
|
6973
|
+
const [searchQuery, setSearchQuery] = useState18("");
|
|
6974
|
+
const [activeCategory, setActiveCategory] = useState18("all");
|
|
6975
|
+
const [focusedIndex, setFocusedIndex] = useState18(-1);
|
|
6976
|
+
const searchInputRef = useRef18(null);
|
|
6977
|
+
const gridRef = useRef18(null);
|
|
6978
|
+
useEffect18(() => {
|
|
6979
|
+
searchInputRef.current?.focus();
|
|
6980
|
+
}, []);
|
|
6981
|
+
const filteredIcons = useMemo7(() => {
|
|
6982
|
+
if (searchQuery.trim()) {
|
|
6983
|
+
return searchIcons(searchQuery);
|
|
6984
|
+
}
|
|
6985
|
+
if (activeCategory === "all") {
|
|
6986
|
+
return ICON_METADATA;
|
|
6987
|
+
}
|
|
6988
|
+
return getIconsByCategory(activeCategory);
|
|
6989
|
+
}, [searchQuery, activeCategory]);
|
|
6990
|
+
const handleSearchChange = useCallback19((e) => {
|
|
6991
|
+
setSearchQuery(e.target.value);
|
|
6992
|
+
setFocusedIndex(-1);
|
|
6993
|
+
if (e.target.value.trim()) {
|
|
6994
|
+
setActiveCategory("all");
|
|
6995
|
+
}
|
|
6996
|
+
}, []);
|
|
6997
|
+
const handleIconSelect = useCallback19((iconName) => {
|
|
6998
|
+
onChange(iconName);
|
|
6999
|
+
onClose();
|
|
7000
|
+
}, [onChange, onClose]);
|
|
7001
|
+
const handleKeyDown = useCallback19((e) => {
|
|
7002
|
+
const iconsPerRow = 6;
|
|
7003
|
+
const totalIcons = filteredIcons.length + 1;
|
|
7004
|
+
switch (e.key) {
|
|
7005
|
+
case "ArrowDown":
|
|
7006
|
+
e.preventDefault();
|
|
7007
|
+
setFocusedIndex((prev) => {
|
|
7008
|
+
const next = prev + iconsPerRow;
|
|
7009
|
+
return next < totalIcons ? next : prev;
|
|
7010
|
+
});
|
|
7011
|
+
break;
|
|
7012
|
+
case "ArrowUp":
|
|
7013
|
+
e.preventDefault();
|
|
7014
|
+
setFocusedIndex((prev) => {
|
|
7015
|
+
const next = prev - iconsPerRow;
|
|
7016
|
+
return next >= 0 ? next : prev;
|
|
7017
|
+
});
|
|
7018
|
+
break;
|
|
7019
|
+
case "ArrowRight":
|
|
7020
|
+
e.preventDefault();
|
|
7021
|
+
setFocusedIndex((prev) => {
|
|
7022
|
+
const next = prev + 1;
|
|
7023
|
+
return next < totalIcons ? next : prev;
|
|
7024
|
+
});
|
|
7025
|
+
break;
|
|
7026
|
+
case "ArrowLeft":
|
|
7027
|
+
e.preventDefault();
|
|
7028
|
+
setFocusedIndex((prev) => {
|
|
7029
|
+
const next = prev - 1;
|
|
7030
|
+
return next >= 0 ? next : prev;
|
|
7031
|
+
});
|
|
7032
|
+
break;
|
|
7033
|
+
case "Enter":
|
|
7034
|
+
e.preventDefault();
|
|
7035
|
+
if (focusedIndex === 0) {
|
|
7036
|
+
handleIconSelect(null);
|
|
7037
|
+
} else if (focusedIndex > 0 && focusedIndex <= filteredIcons.length) {
|
|
7038
|
+
handleIconSelect(filteredIcons[focusedIndex - 1].name);
|
|
7039
|
+
}
|
|
7040
|
+
break;
|
|
7041
|
+
case "Escape":
|
|
7042
|
+
e.preventDefault();
|
|
7043
|
+
onClose();
|
|
7044
|
+
break;
|
|
7045
|
+
}
|
|
7046
|
+
}, [filteredIcons, focusedIndex, handleIconSelect, onClose]);
|
|
7047
|
+
useEffect18(() => {
|
|
7048
|
+
if (focusedIndex >= 0 && gridRef.current) {
|
|
7049
|
+
const focusedButton = gridRef.current.children[focusedIndex];
|
|
7050
|
+
focusedButton?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
7051
|
+
}
|
|
7052
|
+
}, [focusedIndex]);
|
|
7053
|
+
const handleMouseDown = useCallback19((e) => {
|
|
7054
|
+
e.preventDefault();
|
|
7055
|
+
e.stopPropagation();
|
|
7056
|
+
}, []);
|
|
7057
|
+
return /* @__PURE__ */ jsxs10("div", { className: "ya-icon-picker", onKeyDown: handleKeyDown, children: [
|
|
7058
|
+
/* @__PURE__ */ jsx18("div", { className: "ya-icon-picker-search", children: /* @__PURE__ */ jsx18(
|
|
7059
|
+
"input",
|
|
7060
|
+
{
|
|
7061
|
+
ref: searchInputRef,
|
|
7062
|
+
type: "text",
|
|
7063
|
+
value: searchQuery,
|
|
7064
|
+
onChange: handleSearchChange,
|
|
7065
|
+
onClick: (e) => e.stopPropagation(),
|
|
7066
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
7067
|
+
className: "ya-icon-picker-input",
|
|
7068
|
+
placeholder: "Search icons...",
|
|
7069
|
+
autoComplete: "off",
|
|
7070
|
+
spellCheck: false
|
|
7071
|
+
}
|
|
7072
|
+
) }),
|
|
7073
|
+
/* @__PURE__ */ jsxs10("div", { className: "ya-icon-picker-grid-container", children: [
|
|
7074
|
+
/* @__PURE__ */ jsxs10("div", { className: "ya-icon-picker-grid", ref: gridRef, children: [
|
|
7075
|
+
/* @__PURE__ */ jsx18(
|
|
7076
|
+
"button",
|
|
7077
|
+
{
|
|
7078
|
+
type: "button",
|
|
7079
|
+
className: `ya-icon-btn ya-icon-btn-none ${!value ? "is-selected" : ""} ${focusedIndex === 0 ? "is-focused" : ""}`,
|
|
7080
|
+
onClick: () => handleIconSelect(null),
|
|
7081
|
+
onMouseDown: handleMouseDown,
|
|
7082
|
+
title: "No icon",
|
|
7083
|
+
children: /* @__PURE__ */ jsx18("span", { className: "ya-icon-btn-none-x", children: "\xD7" })
|
|
7084
|
+
}
|
|
7085
|
+
),
|
|
7086
|
+
filteredIcons.map((icon, index) => /* @__PURE__ */ jsx18(
|
|
7087
|
+
"button",
|
|
7088
|
+
{
|
|
7089
|
+
type: "button",
|
|
7090
|
+
className: `ya-icon-btn ${value === icon.name ? "is-selected" : ""} ${focusedIndex === index + 1 ? "is-focused" : ""}`,
|
|
7091
|
+
onClick: () => handleIconSelect(icon.name),
|
|
7092
|
+
onMouseDown: handleMouseDown,
|
|
7093
|
+
title: getIconLabel(icon.name),
|
|
7094
|
+
children: /* @__PURE__ */ jsx18(DynamicIcon, { name: icon.name, size: 20 })
|
|
7095
|
+
},
|
|
7096
|
+
icon.name
|
|
7097
|
+
))
|
|
7098
|
+
] }),
|
|
7099
|
+
filteredIcons.length === 0 && /* @__PURE__ */ jsxs10("div", { className: "ya-icon-picker-empty", children: [
|
|
7100
|
+
'No icons found for "',
|
|
7101
|
+
searchQuery,
|
|
7102
|
+
'"'
|
|
7103
|
+
] })
|
|
7104
|
+
] }),
|
|
7105
|
+
value && /* @__PURE__ */ jsxs10("div", { className: "ya-icon-picker-footer", children: [
|
|
7106
|
+
/* @__PURE__ */ jsx18(DynamicIcon, { name: value, size: 16 }),
|
|
7107
|
+
/* @__PURE__ */ jsx18("span", { className: "ya-icon-picker-selected-name", children: getIconLabel(value) })
|
|
7108
|
+
] })
|
|
7109
|
+
] });
|
|
7110
|
+
}
|
|
7111
|
+
|
|
7112
|
+
// src/components/ya-link.css
|
|
7113
|
+
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-editable:has(.ya-text-editing),\n.ya-link-editable:has(.ya-text-editing):hover {\n outline: none !important;\n cursor: text;\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@keyframes ya-link-success {\n 0% {\n outline-color: var(--color-primary, #D4A574);\n }\n 30% {\n outline-color: rgba(134, 239, 172, 0.6);\n outline-width: 2px;\n }\n 100% {\n outline-color: transparent;\n outline-width: 2px;\n }\n}\n.ya-link-success {\n outline: 2px solid transparent;\n outline-offset: 4px;\n border-radius: 4px;\n animation: ya-link-success 0.5s ease;\n}\n');
|
|
7114
|
+
|
|
7115
|
+
// src/components/YaLink.tsx
|
|
7116
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7117
|
+
function isInternalPath(path) {
|
|
7118
|
+
if (!path) return false;
|
|
5838
7119
|
if (path.startsWith("#")) return false;
|
|
5839
7120
|
if (path.startsWith("//")) return false;
|
|
5840
7121
|
if (path.includes("://")) return false;
|
|
@@ -5929,41 +7210,49 @@ function discoverSectionsFromDOM() {
|
|
|
5929
7210
|
});
|
|
5930
7211
|
return sections;
|
|
5931
7212
|
}
|
|
5932
|
-
function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName, style, as: Component = "a", children, availablePages, onClick, target, rel }) {
|
|
7213
|
+
function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName, style, as: Component = "a", children, availablePages, onClick, target, rel, title, iconPosition, iconSize }) {
|
|
7214
|
+
const effectiveIconSize = iconSize ?? (iconPosition === "only" ? 24 : 20);
|
|
5933
7215
|
const textFieldId = `${fieldId}.text`;
|
|
5934
7216
|
const hrefFieldId = `${fieldId}.href`;
|
|
7217
|
+
const iconFieldId = `${fieldId}.icon`;
|
|
5935
7218
|
const textContent = useContent(textFieldId);
|
|
5936
7219
|
const hrefContent = useContent(hrefFieldId);
|
|
7220
|
+
const iconContent = useContent(iconFieldId);
|
|
5937
7221
|
const { mode } = textContent;
|
|
5938
7222
|
const { getPages } = useContentStore();
|
|
5939
7223
|
const [, navigate] = useLocation();
|
|
5940
7224
|
const pages = availablePages ?? getPages();
|
|
5941
|
-
const [sections, setSections] =
|
|
5942
|
-
const [sectionsExpanded, setSectionsExpanded] =
|
|
7225
|
+
const [sections, setSections] = useState19([]);
|
|
7226
|
+
const [sectionsExpanded, setSectionsExpanded] = useState19(false);
|
|
5943
7227
|
const storeText = textContent.get();
|
|
5944
7228
|
const storeHref = hrefContent.get();
|
|
7229
|
+
const storeIcon = iconContent.get();
|
|
5945
7230
|
const isIconMode = children != null && typeof children !== "string";
|
|
5946
7231
|
const text2 = storeText || (typeof children === "string" ? children : "");
|
|
5947
7232
|
const href = storeHref || defaultHref;
|
|
7233
|
+
const currentIcon = storeIcon || null;
|
|
5948
7234
|
const isExternal = isExternalHref(href);
|
|
5949
7235
|
const effectiveTarget = target ?? (isExternal ? "_blank" : void 0);
|
|
5950
7236
|
const effectiveRel = rel ?? (isExternal ? "noopener noreferrer" : void 0);
|
|
5951
|
-
const [editingMode, setEditingMode] =
|
|
5952
|
-
const [
|
|
5953
|
-
const [
|
|
5954
|
-
const [
|
|
5955
|
-
const [
|
|
5956
|
-
const [
|
|
5957
|
-
const
|
|
5958
|
-
const
|
|
5959
|
-
const
|
|
5960
|
-
const [
|
|
5961
|
-
const [
|
|
5962
|
-
const [
|
|
5963
|
-
const [
|
|
5964
|
-
const
|
|
7237
|
+
const [editingMode, setEditingMode] = useState19(null);
|
|
7238
|
+
const [showSuccess, setShowSuccess] = useState19(false);
|
|
7239
|
+
const [originalText, setOriginalText] = useState19(text2);
|
|
7240
|
+
const [originalHref, setOriginalHref] = useState19(href);
|
|
7241
|
+
const [currentHref, setCurrentHref] = useState19(href);
|
|
7242
|
+
const [isExternalUrl, setIsExternalUrl] = useState19(false);
|
|
7243
|
+
const [externalUrl, setExternalUrl] = useState19("");
|
|
7244
|
+
const containerRef = useRef19(null);
|
|
7245
|
+
const hrefPopoverRef = useRef19(null);
|
|
7246
|
+
const [actionButtonsPos, setActionButtonsPos] = useState19(null);
|
|
7247
|
+
const [editPopoverPos, setEditPopoverPos] = useState19(null);
|
|
7248
|
+
const [editPopoverVisible, setEditPopoverVisible] = useState19(false);
|
|
7249
|
+
const [editPopoverMounted, setEditPopoverMounted] = useState19(false);
|
|
7250
|
+
const [hrefPopoverPos, setHrefPopoverPos] = useState19(null);
|
|
7251
|
+
const [iconPopoverPos, setIconPopoverPos] = useState19(null);
|
|
7252
|
+
const iconPopoverRef = useRef19(null);
|
|
7253
|
+
const handleSaveTextRef = useRef19(() => {
|
|
5965
7254
|
});
|
|
5966
|
-
const handleCancelTextRef =
|
|
7255
|
+
const handleCancelTextRef = useRef19(() => {
|
|
5967
7256
|
});
|
|
5968
7257
|
const {
|
|
5969
7258
|
popoverRef: editPopoverRef,
|
|
@@ -5977,12 +7266,12 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
5977
7266
|
});
|
|
5978
7267
|
const triggerRef = containerRef;
|
|
5979
7268
|
const instanceId = useId();
|
|
5980
|
-
|
|
7269
|
+
useEffect19(() => {
|
|
5981
7270
|
if (showEditPopover && mode === "inline-edit" && !editingMode) {
|
|
5982
7271
|
window.dispatchEvent(new CustomEvent("yalink:popover-open", { detail: { id: instanceId } }));
|
|
5983
7272
|
}
|
|
5984
7273
|
}, [showEditPopover, mode, editingMode, instanceId]);
|
|
5985
|
-
|
|
7274
|
+
useEffect19(() => {
|
|
5986
7275
|
const handleOtherPopoverOpen = (event) => {
|
|
5987
7276
|
const customEvent = event;
|
|
5988
7277
|
if (customEvent.detail.id !== instanceId && showEditPopover) {
|
|
@@ -6036,19 +7325,19 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6036
7325
|
}
|
|
6037
7326
|
}
|
|
6038
7327
|
});
|
|
6039
|
-
|
|
7328
|
+
useEffect19(() => {
|
|
6040
7329
|
if (editor && editingMode !== "text") {
|
|
6041
7330
|
if (editor.getHTML() !== text2) {
|
|
6042
7331
|
editor.commands.setContent(text2);
|
|
6043
7332
|
}
|
|
6044
7333
|
}
|
|
6045
7334
|
}, [text2, editor, editingMode]);
|
|
6046
|
-
|
|
7335
|
+
useEffect19(() => {
|
|
6047
7336
|
if (editingMode !== "link") {
|
|
6048
7337
|
setCurrentHref(href);
|
|
6049
7338
|
}
|
|
6050
7339
|
}, [href, editingMode]);
|
|
6051
|
-
|
|
7340
|
+
useEffect19(() => {
|
|
6052
7341
|
if (editingMode !== "text" || !containerRef.current) {
|
|
6053
7342
|
setActionButtonsPos(null);
|
|
6054
7343
|
return;
|
|
@@ -6069,7 +7358,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6069
7358
|
window.removeEventListener("resize", updatePosition);
|
|
6070
7359
|
};
|
|
6071
7360
|
}, [editingMode]);
|
|
6072
|
-
|
|
7361
|
+
useEffect19(() => {
|
|
6073
7362
|
const shouldShow = showEditPopover && !editingMode && mode === "inline-edit";
|
|
6074
7363
|
if (shouldShow) {
|
|
6075
7364
|
setEditPopoverMounted(true);
|
|
@@ -6131,7 +7420,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6131
7420
|
window.removeEventListener("resize", updatePosition);
|
|
6132
7421
|
};
|
|
6133
7422
|
}, [editingMode]);
|
|
6134
|
-
|
|
7423
|
+
useEffect19(() => {
|
|
6135
7424
|
if (editingMode !== "link") return;
|
|
6136
7425
|
const handleClickOutside = (event) => {
|
|
6137
7426
|
const target2 = event.target;
|
|
@@ -6145,7 +7434,44 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6145
7434
|
document.addEventListener("mousedown", handleClickOutside);
|
|
6146
7435
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
6147
7436
|
}, [editingMode, originalHref]);
|
|
6148
|
-
|
|
7437
|
+
useLayoutEffect3(() => {
|
|
7438
|
+
if (editingMode !== "icon" || !containerRef.current) {
|
|
7439
|
+
setIconPopoverPos(null);
|
|
7440
|
+
return;
|
|
7441
|
+
}
|
|
7442
|
+
const updatePosition = () => {
|
|
7443
|
+
if (!containerRef.current) return;
|
|
7444
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
7445
|
+
const popoverHeight = 400;
|
|
7446
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
7447
|
+
const spaceAbove = rect.top;
|
|
7448
|
+
const isAbove = spaceBelow < popoverHeight && spaceAbove > spaceBelow;
|
|
7449
|
+
setIconPopoverPos({
|
|
7450
|
+
top: isAbove ? rect.top - 8 : rect.bottom + 8,
|
|
7451
|
+
left: rect.left + rect.width / 2,
|
|
7452
|
+
isAbove
|
|
7453
|
+
});
|
|
7454
|
+
};
|
|
7455
|
+
updatePosition();
|
|
7456
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
7457
|
+
window.addEventListener("resize", updatePosition);
|
|
7458
|
+
return () => {
|
|
7459
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
7460
|
+
window.removeEventListener("resize", updatePosition);
|
|
7461
|
+
};
|
|
7462
|
+
}, [editingMode]);
|
|
7463
|
+
useEffect19(() => {
|
|
7464
|
+
if (editingMode !== "icon") return;
|
|
7465
|
+
const handleClickOutside = (event) => {
|
|
7466
|
+
const target2 = event.target;
|
|
7467
|
+
if (iconPopoverRef.current?.contains(target2)) return;
|
|
7468
|
+
if (containerRef.current?.contains(target2)) return;
|
|
7469
|
+
setEditingMode(null);
|
|
7470
|
+
};
|
|
7471
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
7472
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
7473
|
+
}, [editingMode]);
|
|
7474
|
+
const handleSaveText = useCallback20(() => {
|
|
6149
7475
|
if (!editor) return;
|
|
6150
7476
|
let html = editor.getHTML();
|
|
6151
7477
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
@@ -6153,30 +7479,40 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6153
7479
|
textContent.save();
|
|
6154
7480
|
setEditingMode(null);
|
|
6155
7481
|
}, [editor, textContent]);
|
|
6156
|
-
const handleSaveLink =
|
|
7482
|
+
const handleSaveLink = useCallback20(() => {
|
|
6157
7483
|
hrefContent.set(currentHref, "user");
|
|
6158
7484
|
hrefContent.save();
|
|
6159
7485
|
setEditingMode(null);
|
|
6160
7486
|
setIsExternalUrl(false);
|
|
6161
7487
|
setExternalUrl("");
|
|
6162
7488
|
}, [currentHref, hrefContent]);
|
|
6163
|
-
const handleCancelText =
|
|
7489
|
+
const handleCancelText = useCallback20(() => {
|
|
6164
7490
|
if (editor) {
|
|
6165
7491
|
editor.commands.setContent(originalText);
|
|
6166
7492
|
}
|
|
6167
7493
|
setEditingMode(null);
|
|
6168
7494
|
}, [editor, originalText]);
|
|
6169
|
-
const handleCancelLink =
|
|
7495
|
+
const handleCancelLink = useCallback20(() => {
|
|
6170
7496
|
setCurrentHref(originalHref);
|
|
6171
7497
|
setEditingMode(null);
|
|
6172
7498
|
setIsExternalUrl(false);
|
|
6173
7499
|
setExternalUrl("");
|
|
6174
7500
|
}, [originalHref]);
|
|
6175
|
-
|
|
7501
|
+
const handleIconSelect = useCallback20((iconName) => {
|
|
7502
|
+
iconContent.set(iconName || "", "user");
|
|
7503
|
+
iconContent.save();
|
|
7504
|
+
setEditingMode(null);
|
|
7505
|
+
setShowSuccess(true);
|
|
7506
|
+
setTimeout(() => setShowSuccess(false), 500);
|
|
7507
|
+
}, [iconContent]);
|
|
7508
|
+
const handleCancelIcon = useCallback20(() => {
|
|
7509
|
+
setEditingMode(null);
|
|
7510
|
+
}, []);
|
|
7511
|
+
useEffect19(() => {
|
|
6176
7512
|
handleSaveTextRef.current = handleSaveText;
|
|
6177
7513
|
handleCancelTextRef.current = handleCancelText;
|
|
6178
7514
|
}, [handleSaveText, handleCancelText]);
|
|
6179
|
-
const handleClick =
|
|
7515
|
+
const handleClick = useCallback20(
|
|
6180
7516
|
(e) => {
|
|
6181
7517
|
const selectModeEnabled = window.__builderSelectModeEnabled;
|
|
6182
7518
|
if (selectModeEnabled) {
|
|
@@ -6208,7 +7544,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6208
7544
|
},
|
|
6209
7545
|
[href, navigate, onClick]
|
|
6210
7546
|
);
|
|
6211
|
-
const startEditText =
|
|
7547
|
+
const startEditText = useCallback20(() => {
|
|
6212
7548
|
hideEditPopover();
|
|
6213
7549
|
if (isIconMode) {
|
|
6214
7550
|
window.dispatchEvent(new CustomEvent("yatext:edit-mode", {
|
|
@@ -6222,14 +7558,18 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6222
7558
|
}, 20);
|
|
6223
7559
|
}
|
|
6224
7560
|
}, [text2, editor, hideEditPopover, isIconMode, fieldId]);
|
|
6225
|
-
const startEditLink =
|
|
7561
|
+
const startEditLink = useCallback20(() => {
|
|
6226
7562
|
hideEditPopover();
|
|
6227
7563
|
setEditingMode("link");
|
|
6228
7564
|
setOriginalHref(href);
|
|
6229
7565
|
setCurrentHref(href);
|
|
6230
7566
|
setSections(discoverSectionsFromDOM());
|
|
6231
7567
|
}, [href, hideEditPopover]);
|
|
6232
|
-
const
|
|
7568
|
+
const startEditIcon = useCallback20(() => {
|
|
7569
|
+
hideEditPopover();
|
|
7570
|
+
setEditingMode("icon");
|
|
7571
|
+
}, [hideEditPopover]);
|
|
7572
|
+
const handleKeyDown = useCallback20(
|
|
6233
7573
|
(event) => {
|
|
6234
7574
|
if (editingMode !== "text") return;
|
|
6235
7575
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -6250,7 +7590,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6250
7590
|
},
|
|
6251
7591
|
[editingMode, handleSaveText, handleCancelText]
|
|
6252
7592
|
);
|
|
6253
|
-
const handleFontSizeChange =
|
|
7593
|
+
const handleFontSizeChange = useCallback20(
|
|
6254
7594
|
(e) => {
|
|
6255
7595
|
if (!editor) return;
|
|
6256
7596
|
const size = e.target.value;
|
|
@@ -6262,7 +7602,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6262
7602
|
},
|
|
6263
7603
|
[editor]
|
|
6264
7604
|
);
|
|
6265
|
-
const handleFontWeightChange =
|
|
7605
|
+
const handleFontWeightChange = useCallback20(
|
|
6266
7606
|
(e) => {
|
|
6267
7607
|
if (!editor) return;
|
|
6268
7608
|
const weight = e.target.value;
|
|
@@ -6274,11 +7614,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6274
7614
|
},
|
|
6275
7615
|
[editor]
|
|
6276
7616
|
);
|
|
6277
|
-
const handlePageSelect =
|
|
7617
|
+
const handlePageSelect = useCallback20((path) => {
|
|
6278
7618
|
setCurrentHref(path);
|
|
6279
7619
|
setIsExternalUrl(false);
|
|
6280
7620
|
}, []);
|
|
6281
|
-
const handleExternalUrlApply =
|
|
7621
|
+
const handleExternalUrlApply = useCallback20(() => {
|
|
6282
7622
|
if (externalUrl) {
|
|
6283
7623
|
setCurrentHref(externalUrl);
|
|
6284
7624
|
}
|
|
@@ -6293,28 +7633,58 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6293
7633
|
const attrs = editor.getAttributes("textStyle");
|
|
6294
7634
|
return attrs.fontWeight || "";
|
|
6295
7635
|
};
|
|
7636
|
+
const renderIcon = () => currentIcon ? /* @__PURE__ */ jsx19(DynamicIcon, { name: currentIcon, size: effectiveIconSize }) : null;
|
|
7637
|
+
const renderLinkContent = (textContent2) => {
|
|
7638
|
+
if (iconPosition === "only") {
|
|
7639
|
+
return currentIcon ? renderIcon() : children;
|
|
7640
|
+
}
|
|
7641
|
+
if (iconPosition === "left") {
|
|
7642
|
+
return /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7643
|
+
renderIcon(),
|
|
7644
|
+
renderIcon() && /* @__PURE__ */ jsx19("span", { style: { marginLeft: "0.35em" } }),
|
|
7645
|
+
textContent2
|
|
7646
|
+
] });
|
|
7647
|
+
}
|
|
7648
|
+
if (iconPosition === "right") {
|
|
7649
|
+
return /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7650
|
+
textContent2,
|
|
7651
|
+
renderIcon() && /* @__PURE__ */ jsx19("span", { style: { marginRight: "0.35em" } }),
|
|
7652
|
+
renderIcon()
|
|
7653
|
+
] });
|
|
7654
|
+
}
|
|
7655
|
+
return textContent2;
|
|
7656
|
+
};
|
|
6296
7657
|
if (mode === "read-only") {
|
|
6297
|
-
|
|
7658
|
+
let content;
|
|
7659
|
+
if (iconPosition) {
|
|
7660
|
+
content = renderLinkContent(/* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode }));
|
|
7661
|
+
} else if (isIconMode) {
|
|
7662
|
+
content = children;
|
|
7663
|
+
} else {
|
|
7664
|
+
content = /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode });
|
|
7665
|
+
}
|
|
6298
7666
|
if (isInternalPath(href)) {
|
|
6299
|
-
return /* @__PURE__ */
|
|
7667
|
+
return /* @__PURE__ */ jsx19(
|
|
6300
7668
|
WouterLink,
|
|
6301
7669
|
{
|
|
6302
7670
|
href,
|
|
6303
7671
|
className,
|
|
6304
7672
|
style,
|
|
7673
|
+
title,
|
|
6305
7674
|
"data-ya-restricted": "true",
|
|
6306
7675
|
"data-field-id": fieldId,
|
|
6307
7676
|
children: content
|
|
6308
7677
|
}
|
|
6309
7678
|
);
|
|
6310
7679
|
}
|
|
6311
|
-
return /* @__PURE__ */
|
|
7680
|
+
return /* @__PURE__ */ jsx19(
|
|
6312
7681
|
Component,
|
|
6313
7682
|
{
|
|
6314
7683
|
ref: containerRef,
|
|
6315
7684
|
href: Component === "a" ? href : void 0,
|
|
6316
7685
|
target: Component === "a" ? effectiveTarget : void 0,
|
|
6317
7686
|
rel: Component === "a" ? effectiveRel : void 0,
|
|
7687
|
+
title,
|
|
6318
7688
|
className,
|
|
6319
7689
|
style,
|
|
6320
7690
|
"data-ya-restricted": "true",
|
|
@@ -6323,29 +7693,48 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6323
7693
|
}
|
|
6324
7694
|
);
|
|
6325
7695
|
}
|
|
6326
|
-
return /* @__PURE__ */
|
|
6327
|
-
/* @__PURE__ */
|
|
7696
|
+
return /* @__PURE__ */ jsxs11("span", { className: `ya-link-wrapper ${wrapperClassName || ""}`, children: [
|
|
7697
|
+
/* @__PURE__ */ jsx19(
|
|
6328
7698
|
Component,
|
|
6329
7699
|
{
|
|
6330
7700
|
ref: containerRef,
|
|
6331
7701
|
href: Component === "a" ? href : void 0,
|
|
6332
7702
|
target: Component === "a" ? effectiveTarget : void 0,
|
|
6333
7703
|
rel: Component === "a" ? effectiveRel : void 0,
|
|
6334
|
-
|
|
7704
|
+
title,
|
|
7705
|
+
className: `${className || ""} ${editingMode ? "ya-link-editing" : "ya-link-editable"} ${showSuccess ? "ya-link-success" : ""}`,
|
|
6335
7706
|
style,
|
|
6336
7707
|
"data-ya-restricted": "true",
|
|
7708
|
+
"data-ya-link": "true",
|
|
6337
7709
|
"data-field-id": fieldId,
|
|
6338
7710
|
onClick: handleClick,
|
|
6339
7711
|
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
6340
7712
|
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
6341
7713
|
onFocus: safeTriangleHandlers.onFocus,
|
|
6342
7714
|
onKeyDown: handleKeyDown,
|
|
6343
|
-
children:
|
|
6344
|
-
// Icon mode: render
|
|
7715
|
+
children: iconPosition === "only" ? (
|
|
7716
|
+
// Icon-only mode: render DynamicIcon
|
|
7717
|
+
currentIcon ? /* @__PURE__ */ jsx19(DynamicIcon, { name: currentIcon, size: effectiveIconSize }) : children
|
|
7718
|
+
) : iconPosition === "left" ? (
|
|
7719
|
+
// Icon before text
|
|
7720
|
+
/* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7721
|
+
renderIcon(),
|
|
7722
|
+
renderIcon() && /* @__PURE__ */ jsx19("span", { style: { marginLeft: "0.35em" } }),
|
|
7723
|
+
isIconMode ? children : editor ? editingMode === "text" ? /* @__PURE__ */ jsx19(EditorContent2, { editor }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode })
|
|
7724
|
+
] })
|
|
7725
|
+
) : iconPosition === "right" ? (
|
|
7726
|
+
// Text before icon
|
|
7727
|
+
/* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7728
|
+
isIconMode ? children : editor ? editingMode === "text" ? /* @__PURE__ */ jsx19(EditorContent2, { editor }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode }),
|
|
7729
|
+
renderIcon() && /* @__PURE__ */ jsx19("span", { style: { marginRight: "0.35em" } }),
|
|
7730
|
+
renderIcon()
|
|
7731
|
+
] })
|
|
7732
|
+
) : isIconMode ? (
|
|
7733
|
+
// Icon mode (children is React node): render children directly, no text editing
|
|
6345
7734
|
children
|
|
6346
|
-
) : editor ? /* @__PURE__ */
|
|
7735
|
+
) : editor ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
6347
7736
|
createPortal6(
|
|
6348
|
-
/* @__PURE__ */
|
|
7737
|
+
/* @__PURE__ */ jsxs11(
|
|
6349
7738
|
BubbleMenu,
|
|
6350
7739
|
{
|
|
6351
7740
|
editor,
|
|
@@ -6353,28 +7742,28 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6353
7742
|
options: { offset: 6, placement: "top" },
|
|
6354
7743
|
className: "ya-bubble-menu",
|
|
6355
7744
|
children: [
|
|
6356
|
-
/* @__PURE__ */
|
|
7745
|
+
/* @__PURE__ */ jsx19(
|
|
6357
7746
|
"button",
|
|
6358
7747
|
{
|
|
6359
7748
|
type: "button",
|
|
6360
7749
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
6361
7750
|
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
6362
7751
|
title: "Bold",
|
|
6363
|
-
children: /* @__PURE__ */
|
|
7752
|
+
children: /* @__PURE__ */ jsx19("strong", { children: "B" })
|
|
6364
7753
|
}
|
|
6365
7754
|
),
|
|
6366
|
-
/* @__PURE__ */
|
|
7755
|
+
/* @__PURE__ */ jsx19(
|
|
6367
7756
|
"button",
|
|
6368
7757
|
{
|
|
6369
7758
|
type: "button",
|
|
6370
7759
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
6371
7760
|
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
6372
7761
|
title: "Italic",
|
|
6373
|
-
children: /* @__PURE__ */
|
|
7762
|
+
children: /* @__PURE__ */ jsx19("em", { children: "I" })
|
|
6374
7763
|
}
|
|
6375
7764
|
),
|
|
6376
|
-
/* @__PURE__ */
|
|
6377
|
-
/* @__PURE__ */
|
|
7765
|
+
/* @__PURE__ */ jsx19("span", { className: "ya-bubble-divider" }),
|
|
7766
|
+
/* @__PURE__ */ jsxs11(
|
|
6378
7767
|
"select",
|
|
6379
7768
|
{
|
|
6380
7769
|
value: getCurrentFontSize(),
|
|
@@ -6382,12 +7771,12 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6382
7771
|
className: "ya-bubble-select",
|
|
6383
7772
|
title: "Font Size",
|
|
6384
7773
|
children: [
|
|
6385
|
-
/* @__PURE__ */
|
|
6386
|
-
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */
|
|
7774
|
+
/* @__PURE__ */ jsx19("option", { value: "", children: "Size" }),
|
|
7775
|
+
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */ jsx19("option", { value: size, children: name }, name))
|
|
6387
7776
|
]
|
|
6388
7777
|
}
|
|
6389
7778
|
),
|
|
6390
|
-
/* @__PURE__ */
|
|
7779
|
+
/* @__PURE__ */ jsxs11(
|
|
6391
7780
|
"select",
|
|
6392
7781
|
{
|
|
6393
7782
|
value: getCurrentFontWeight(),
|
|
@@ -6395,8 +7784,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6395
7784
|
className: "ya-bubble-select",
|
|
6396
7785
|
title: "Font Weight",
|
|
6397
7786
|
children: [
|
|
6398
|
-
/* @__PURE__ */
|
|
6399
|
-
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */
|
|
7787
|
+
/* @__PURE__ */ jsx19("option", { value: "", children: "Weight" }),
|
|
7788
|
+
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */ jsx19("option", { value: weight, children: name }, name))
|
|
6400
7789
|
]
|
|
6401
7790
|
}
|
|
6402
7791
|
)
|
|
@@ -6405,10 +7794,10 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6405
7794
|
),
|
|
6406
7795
|
document.body
|
|
6407
7796
|
),
|
|
6408
|
-
editingMode === "text" ? /* @__PURE__ */
|
|
6409
|
-
/* @__PURE__ */
|
|
7797
|
+
editingMode === "text" ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7798
|
+
/* @__PURE__ */ jsx19(EditorContent2, { editor }),
|
|
6410
7799
|
actionButtonsPos && createPortal6(
|
|
6411
|
-
/* @__PURE__ */
|
|
7800
|
+
/* @__PURE__ */ jsxs11(
|
|
6412
7801
|
"div",
|
|
6413
7802
|
{
|
|
6414
7803
|
className: "ya-link-actions",
|
|
@@ -6418,19 +7807,19 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6418
7807
|
right: actionButtonsPos.right
|
|
6419
7808
|
},
|
|
6420
7809
|
children: [
|
|
6421
|
-
/* @__PURE__ */
|
|
6422
|
-
/* @__PURE__ */
|
|
7810
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: handleCancelText, className: "ya-link-btn ya-link-btn-cancel", children: "Cancel" }),
|
|
7811
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: handleSaveText, className: "ya-link-btn ya-link-btn-save", children: "Save" })
|
|
6423
7812
|
]
|
|
6424
7813
|
}
|
|
6425
7814
|
),
|
|
6426
7815
|
document.body
|
|
6427
7816
|
)
|
|
6428
|
-
] }) : /* @__PURE__ */
|
|
6429
|
-
] }) : /* @__PURE__ */
|
|
7817
|
+
] }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode })
|
|
7818
|
+
] }) : /* @__PURE__ */ jsx19(SafeHtml, { content: text2, mode })
|
|
6430
7819
|
}
|
|
6431
7820
|
),
|
|
6432
7821
|
editPopoverMounted && editPopoverPos && createPortal6(
|
|
6433
|
-
/* @__PURE__ */
|
|
7822
|
+
/* @__PURE__ */ jsx19(
|
|
6434
7823
|
"div",
|
|
6435
7824
|
{
|
|
6436
7825
|
ref: editPopoverRef,
|
|
@@ -6443,15 +7832,31 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6443
7832
|
},
|
|
6444
7833
|
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
6445
7834
|
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
6446
|
-
children:
|
|
6447
|
-
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
|
|
7835
|
+
children: iconPosition === "only" ? (
|
|
7836
|
+
// Icon-only mode: show "Edit icon" + "Edit link"
|
|
7837
|
+
/* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7838
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditIcon, children: "Edit icon" }),
|
|
7839
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
7840
|
+
] })
|
|
7841
|
+
) : iconPosition ? (
|
|
7842
|
+
// Icon + text mode: show all three options
|
|
7843
|
+
/* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7844
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditIcon, children: "Edit icon" }),
|
|
7845
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditText, children: "Edit text" }),
|
|
7846
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
7847
|
+
] })
|
|
7848
|
+
) : (
|
|
7849
|
+
// Text-only mode: show "Edit text" + "Edit link"
|
|
7850
|
+
/* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7851
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditText, children: "Edit text" }),
|
|
7852
|
+
/* @__PURE__ */ jsx19("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
7853
|
+
] })
|
|
7854
|
+
)
|
|
6450
7855
|
}
|
|
6451
7856
|
),
|
|
6452
7857
|
document.body
|
|
6453
7858
|
),
|
|
6454
|
-
/* @__PURE__ */
|
|
7859
|
+
/* @__PURE__ */ jsx19(
|
|
6455
7860
|
SafeTriangleBelow,
|
|
6456
7861
|
{
|
|
6457
7862
|
triggerRef,
|
|
@@ -6462,7 +7867,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6462
7867
|
}
|
|
6463
7868
|
),
|
|
6464
7869
|
editingMode === "link" && hrefPopoverPos && createPortal6(
|
|
6465
|
-
/* @__PURE__ */
|
|
7870
|
+
/* @__PURE__ */ jsxs11(
|
|
6466
7871
|
"div",
|
|
6467
7872
|
{
|
|
6468
7873
|
ref: hrefPopoverRef,
|
|
@@ -6474,24 +7879,24 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6474
7879
|
transform: "translateX(-50%)"
|
|
6475
7880
|
},
|
|
6476
7881
|
children: [
|
|
6477
|
-
/* @__PURE__ */
|
|
6478
|
-
!isExternalUrl ? /* @__PURE__ */
|
|
6479
|
-
sections.length > 0 && /* @__PURE__ */
|
|
6480
|
-
/* @__PURE__ */
|
|
7882
|
+
/* @__PURE__ */ jsx19("div", { className: "ya-href-popover-header", children: "Link destination" }),
|
|
7883
|
+
!isExternalUrl ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7884
|
+
sections.length > 0 && /* @__PURE__ */ jsxs11("div", { className: "ya-href-popover-section", children: [
|
|
7885
|
+
/* @__PURE__ */ jsxs11(
|
|
6481
7886
|
"button",
|
|
6482
7887
|
{
|
|
6483
7888
|
type: "button",
|
|
6484
7889
|
className: "ya-href-popover-label ya-href-collapsible-header",
|
|
6485
7890
|
onClick: () => setSectionsExpanded(!sectionsExpanded),
|
|
6486
7891
|
children: [
|
|
6487
|
-
/* @__PURE__ */
|
|
7892
|
+
/* @__PURE__ */ jsx19("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
|
|
6488
7893
|
"Scroll to section (",
|
|
6489
7894
|
sections.length,
|
|
6490
7895
|
")"
|
|
6491
7896
|
]
|
|
6492
7897
|
}
|
|
6493
7898
|
),
|
|
6494
|
-
sectionsExpanded && /* @__PURE__ */
|
|
7899
|
+
sectionsExpanded && /* @__PURE__ */ jsx19("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs11(
|
|
6495
7900
|
"button",
|
|
6496
7901
|
{
|
|
6497
7902
|
type: "button",
|
|
@@ -6499,15 +7904,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6499
7904
|
onClick: () => handlePageSelect(section.path),
|
|
6500
7905
|
children: [
|
|
6501
7906
|
section.label,
|
|
6502
|
-
/* @__PURE__ */
|
|
7907
|
+
/* @__PURE__ */ jsx19("span", { className: "ya-href-page-path", children: section.path })
|
|
6503
7908
|
]
|
|
6504
7909
|
},
|
|
6505
7910
|
section.path
|
|
6506
7911
|
)) })
|
|
6507
7912
|
] }),
|
|
6508
|
-
pages.length > 0 && /* @__PURE__ */
|
|
6509
|
-
/* @__PURE__ */
|
|
6510
|
-
/* @__PURE__ */
|
|
7913
|
+
pages.length > 0 && /* @__PURE__ */ jsxs11("div", { className: "ya-href-popover-section", children: [
|
|
7914
|
+
/* @__PURE__ */ jsx19("label", { className: "ya-href-popover-label", children: "Navigate to page" }),
|
|
7915
|
+
/* @__PURE__ */ jsx19("div", { className: "ya-href-popover-pages", children: pages.map((page) => /* @__PURE__ */ jsxs11(
|
|
6511
7916
|
"button",
|
|
6512
7917
|
{
|
|
6513
7918
|
type: "button",
|
|
@@ -6515,13 +7920,13 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6515
7920
|
onClick: () => handlePageSelect(page.path),
|
|
6516
7921
|
children: [
|
|
6517
7922
|
page.label,
|
|
6518
|
-
/* @__PURE__ */
|
|
7923
|
+
/* @__PURE__ */ jsx19("span", { className: "ya-href-page-path", children: page.path })
|
|
6519
7924
|
]
|
|
6520
7925
|
},
|
|
6521
7926
|
page.path
|
|
6522
7927
|
)) })
|
|
6523
7928
|
] }),
|
|
6524
|
-
/* @__PURE__ */
|
|
7929
|
+
/* @__PURE__ */ jsx19(
|
|
6525
7930
|
"button",
|
|
6526
7931
|
{
|
|
6527
7932
|
type: "button",
|
|
@@ -6533,10 +7938,10 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6533
7938
|
children: "Use external URL instead"
|
|
6534
7939
|
}
|
|
6535
7940
|
)
|
|
6536
|
-
] }) : /* @__PURE__ */
|
|
6537
|
-
/* @__PURE__ */
|
|
6538
|
-
/* @__PURE__ */
|
|
6539
|
-
/* @__PURE__ */
|
|
7941
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
7942
|
+
/* @__PURE__ */ jsxs11("div", { className: "ya-href-popover-section", children: [
|
|
7943
|
+
/* @__PURE__ */ jsx19("label", { className: "ya-href-popover-label", children: "External URL" }),
|
|
7944
|
+
/* @__PURE__ */ jsx19(
|
|
6540
7945
|
"input",
|
|
6541
7946
|
{
|
|
6542
7947
|
type: "url",
|
|
@@ -6548,49 +7953,313 @@ function YaLink({ fieldId, href: defaultHref = "#", className, wrapperClassName,
|
|
|
6548
7953
|
}
|
|
6549
7954
|
)
|
|
6550
7955
|
] }),
|
|
6551
|
-
/* @__PURE__ */
|
|
7956
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
|
|
6552
7957
|
] }),
|
|
6553
|
-
/* @__PURE__ */
|
|
6554
|
-
/* @__PURE__ */
|
|
6555
|
-
isExternalUrl ? /* @__PURE__ */
|
|
7958
|
+
/* @__PURE__ */ jsxs11("div", { className: "ya-href-popover-actions", children: [
|
|
7959
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "ya-link-btn ya-link-btn-cancel", onClick: handleCancelLink, children: "Cancel" }),
|
|
7960
|
+
isExternalUrl ? /* @__PURE__ */ jsx19("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleExternalUrlApply, children: "Apply" }) : /* @__PURE__ */ jsx19("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleSaveLink, children: "Save" })
|
|
6556
7961
|
] })
|
|
6557
7962
|
]
|
|
6558
7963
|
}
|
|
6559
7964
|
),
|
|
6560
7965
|
document.body
|
|
7966
|
+
),
|
|
7967
|
+
editingMode === "icon" && iconPopoverPos && createPortal6(
|
|
7968
|
+
/* @__PURE__ */ jsx19(
|
|
7969
|
+
"div",
|
|
7970
|
+
{
|
|
7971
|
+
ref: iconPopoverRef,
|
|
7972
|
+
className: `ya-href-popover ${iconPopoverPos.isAbove ? "ya-href-popover--above" : ""}`,
|
|
7973
|
+
style: {
|
|
7974
|
+
top: iconPopoverPos.isAbove ? "auto" : iconPopoverPos.top,
|
|
7975
|
+
bottom: iconPopoverPos.isAbove ? window.innerHeight - iconPopoverPos.top : "auto",
|
|
7976
|
+
left: iconPopoverPos.left,
|
|
7977
|
+
transform: "translateX(-50%)"
|
|
7978
|
+
},
|
|
7979
|
+
children: /* @__PURE__ */ jsx19(
|
|
7980
|
+
IconPicker,
|
|
7981
|
+
{
|
|
7982
|
+
value: currentIcon,
|
|
7983
|
+
onChange: handleIconSelect,
|
|
7984
|
+
onClose: handleCancelIcon
|
|
7985
|
+
}
|
|
7986
|
+
)
|
|
7987
|
+
}
|
|
7988
|
+
),
|
|
7989
|
+
document.body
|
|
7990
|
+
)
|
|
7991
|
+
] });
|
|
7992
|
+
}
|
|
7993
|
+
|
|
7994
|
+
// src/components/YaIcon.tsx
|
|
7995
|
+
import React9, { useLayoutEffect as useLayoutEffect4, useRef as useRef20, useState as useState20, useCallback as useCallback21, useId as useId2, useEffect as useEffect20 } from "react";
|
|
7996
|
+
import { createPortal as createPortal7 } from "react-dom";
|
|
7997
|
+
|
|
7998
|
+
// src/components/ya-icon.css
|
|
7999
|
+
styleInject('.ya-icon-wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n.ya-icon-editable {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border-radius: 4px;\n}\n.ya-icon-editable::after {\n content: "";\n position: absolute;\n inset: -4px;\n border: 1.5px dotted var(--ya-contrast-color, white);\n border-radius: 4px;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s ease;\n}\n.ya-icon-editable:hover::after {\n opacity: 1;\n}\nbody.builder-selector-active .ya-icon-editable:hover::after {\n opacity: 0;\n}\nbody.builder-selector-active .ya-icon-editable {\n cursor: inherit;\n}\n.ya-icon-editing::after {\n opacity: 1;\n border-style: solid;\n}\n.ya-icon-placeholder {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: rgba(212, 165, 116, 0.15);\n border: 1px dashed rgba(212, 165, 116, 0.5);\n border-radius: 4px;\n color: var(--color-primary, #D4A574);\n}\n@keyframes ya-icon-success {\n 0% {\n opacity: 1;\n border-color: white;\n }\n 30% {\n opacity: 1;\n border-color: rgba(134, 239, 172, 0.8);\n }\n 100% {\n opacity: 0;\n border-color: rgba(134, 239, 172, 0.8);\n }\n}\n.ya-icon-success::after {\n border-style: solid;\n animation: ya-icon-success 0.5s ease forwards;\n}\n.ya-icon-edit-popover {\n position: fixed;\n z-index: 10000;\n background: #2a2a2a;\n border-radius: 6px;\n padding: 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-icon-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-icon-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-icon-edit-popover button:hover {\n background: #4a4a4a;\n}\n.ya-icon-picker-popover {\n position: fixed;\n z-index: 10000;\n background: #1a1a1a;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);\n animation: ya-icon-picker-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-icon-picker-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-icon-picker-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-icon-picker-popover--above {\n animation: ya-icon-picker-fade-in-above 0.15s ease;\n}\n@keyframes ya-icon-picker-fade-in-above {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-icon-picker-popover--above::before {\n top: auto;\n bottom: -6px;\n border-bottom: none;\n border-top: 8px solid #1a1a1a;\n}\n');
|
|
8000
|
+
|
|
8001
|
+
// src/components/YaIcon.tsx
|
|
8002
|
+
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8003
|
+
function YaIcon({
|
|
8004
|
+
fieldId,
|
|
8005
|
+
fallback,
|
|
8006
|
+
size = 24,
|
|
8007
|
+
stroke = 2,
|
|
8008
|
+
className,
|
|
8009
|
+
wrapperClassName
|
|
8010
|
+
}) {
|
|
8011
|
+
const iconFieldId = `${fieldId}.icon`;
|
|
8012
|
+
const iconContent = useContent(iconFieldId);
|
|
8013
|
+
const { mode } = iconContent;
|
|
8014
|
+
const storeIcon = iconContent.get();
|
|
8015
|
+
const currentIcon = storeIcon || fallback || null;
|
|
8016
|
+
const [isEditing, setIsEditing] = useState20(false);
|
|
8017
|
+
const [showSuccess, setShowSuccess] = useState20(false);
|
|
8018
|
+
const containerRef = useRef20(null);
|
|
8019
|
+
const iconPopoverRef = useRef20(null);
|
|
8020
|
+
const [editPopoverPos, setEditPopoverPos] = useState20(null);
|
|
8021
|
+
const [editPopoverVisible, setEditPopoverVisible] = useState20(false);
|
|
8022
|
+
const [editPopoverMounted, setEditPopoverMounted] = useState20(false);
|
|
8023
|
+
const [iconPickerPos, setIconPickerPos] = useState20(null);
|
|
8024
|
+
const instanceId = useId2();
|
|
8025
|
+
const {
|
|
8026
|
+
popoverRef: editPopoverRef,
|
|
8027
|
+
isVisible: showEditPopover,
|
|
8028
|
+
handlers: safeTriangleHandlers,
|
|
8029
|
+
triangleProps,
|
|
8030
|
+
hide: hideEditPopover
|
|
8031
|
+
} = useSafeTriangle({
|
|
8032
|
+
enabled: mode === "inline-edit" && !isEditing,
|
|
8033
|
+
hideDelay: 150
|
|
8034
|
+
});
|
|
8035
|
+
const triggerRef = containerRef;
|
|
8036
|
+
useEffect20(() => {
|
|
8037
|
+
if (mode !== "inline-edit" || !containerRef.current) return;
|
|
8038
|
+
return setupContrastDetection(containerRef.current);
|
|
8039
|
+
}, [mode]);
|
|
8040
|
+
React9.useEffect(() => {
|
|
8041
|
+
if (showEditPopover && mode === "inline-edit" && !isEditing) {
|
|
8042
|
+
window.dispatchEvent(new CustomEvent("yaicon:popover-open", { detail: { id: instanceId } }));
|
|
8043
|
+
}
|
|
8044
|
+
}, [showEditPopover, mode, isEditing, instanceId]);
|
|
8045
|
+
React9.useEffect(() => {
|
|
8046
|
+
const handleOtherPopoverOpen = (event) => {
|
|
8047
|
+
const customEvent = event;
|
|
8048
|
+
if (customEvent.detail.id !== instanceId && showEditPopover) {
|
|
8049
|
+
hideEditPopover();
|
|
8050
|
+
}
|
|
8051
|
+
};
|
|
8052
|
+
window.addEventListener("yaicon:popover-open", handleOtherPopoverOpen);
|
|
8053
|
+
window.addEventListener("yalink:popover-open", handleOtherPopoverOpen);
|
|
8054
|
+
return () => {
|
|
8055
|
+
window.removeEventListener("yaicon:popover-open", handleOtherPopoverOpen);
|
|
8056
|
+
window.removeEventListener("yalink:popover-open", handleOtherPopoverOpen);
|
|
8057
|
+
};
|
|
8058
|
+
}, [instanceId, showEditPopover, hideEditPopover]);
|
|
8059
|
+
React9.useEffect(() => {
|
|
8060
|
+
const shouldShow = showEditPopover && !isEditing && mode === "inline-edit";
|
|
8061
|
+
if (shouldShow) {
|
|
8062
|
+
setEditPopoverMounted(true);
|
|
8063
|
+
requestAnimationFrame(() => {
|
|
8064
|
+
setEditPopoverVisible(true);
|
|
8065
|
+
});
|
|
8066
|
+
} else {
|
|
8067
|
+
setEditPopoverVisible(false);
|
|
8068
|
+
const timer = setTimeout(() => {
|
|
8069
|
+
setEditPopoverMounted(false);
|
|
8070
|
+
}, 100);
|
|
8071
|
+
return () => clearTimeout(timer);
|
|
8072
|
+
}
|
|
8073
|
+
}, [showEditPopover, isEditing, mode]);
|
|
8074
|
+
useLayoutEffect4(() => {
|
|
8075
|
+
if (!editPopoverMounted || !containerRef.current) {
|
|
8076
|
+
setEditPopoverPos(null);
|
|
8077
|
+
return;
|
|
8078
|
+
}
|
|
8079
|
+
const updatePosition = () => {
|
|
8080
|
+
if (!containerRef.current) return;
|
|
8081
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
8082
|
+
setEditPopoverPos({
|
|
8083
|
+
top: rect.bottom + 8,
|
|
8084
|
+
left: rect.left + rect.width / 2
|
|
8085
|
+
});
|
|
8086
|
+
};
|
|
8087
|
+
updatePosition();
|
|
8088
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
8089
|
+
window.addEventListener("resize", updatePosition);
|
|
8090
|
+
return () => {
|
|
8091
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
8092
|
+
window.removeEventListener("resize", updatePosition);
|
|
8093
|
+
};
|
|
8094
|
+
}, [editPopoverMounted]);
|
|
8095
|
+
useLayoutEffect4(() => {
|
|
8096
|
+
if (!isEditing || !containerRef.current) {
|
|
8097
|
+
setIconPickerPos(null);
|
|
8098
|
+
return;
|
|
8099
|
+
}
|
|
8100
|
+
const updatePosition = () => {
|
|
8101
|
+
if (!containerRef.current) return;
|
|
8102
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
8103
|
+
const popoverHeight = 400;
|
|
8104
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
8105
|
+
const spaceAbove = rect.top;
|
|
8106
|
+
const isAbove = spaceBelow < popoverHeight && spaceAbove > spaceBelow;
|
|
8107
|
+
setIconPickerPos({
|
|
8108
|
+
top: isAbove ? rect.top - 8 : rect.bottom + 8,
|
|
8109
|
+
left: rect.left + rect.width / 2,
|
|
8110
|
+
isAbove
|
|
8111
|
+
});
|
|
8112
|
+
};
|
|
8113
|
+
updatePosition();
|
|
8114
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
8115
|
+
window.addEventListener("resize", updatePosition);
|
|
8116
|
+
return () => {
|
|
8117
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
8118
|
+
window.removeEventListener("resize", updatePosition);
|
|
8119
|
+
};
|
|
8120
|
+
}, [isEditing]);
|
|
8121
|
+
React9.useEffect(() => {
|
|
8122
|
+
if (!isEditing) return;
|
|
8123
|
+
const handleClickOutside = (event) => {
|
|
8124
|
+
const target = event.target;
|
|
8125
|
+
if (iconPopoverRef.current?.contains(target)) return;
|
|
8126
|
+
if (containerRef.current?.contains(target)) return;
|
|
8127
|
+
setIsEditing(false);
|
|
8128
|
+
};
|
|
8129
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
8130
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
8131
|
+
}, [isEditing]);
|
|
8132
|
+
const startEdit = useCallback21(() => {
|
|
8133
|
+
hideEditPopover();
|
|
8134
|
+
setIsEditing(true);
|
|
8135
|
+
}, [hideEditPopover]);
|
|
8136
|
+
const handleIconSelect = useCallback21((iconName) => {
|
|
8137
|
+
iconContent.set(iconName || "", "user");
|
|
8138
|
+
iconContent.save();
|
|
8139
|
+
setIsEditing(false);
|
|
8140
|
+
setShowSuccess(true);
|
|
8141
|
+
setTimeout(() => setShowSuccess(false), 500);
|
|
8142
|
+
}, [iconContent]);
|
|
8143
|
+
const handleCancel = useCallback21(() => {
|
|
8144
|
+
setIsEditing(false);
|
|
8145
|
+
}, []);
|
|
8146
|
+
if (mode === "read-only") {
|
|
8147
|
+
if (!currentIcon) return null;
|
|
8148
|
+
return /* @__PURE__ */ jsx20(
|
|
8149
|
+
DynamicIcon,
|
|
8150
|
+
{
|
|
8151
|
+
name: currentIcon,
|
|
8152
|
+
size,
|
|
8153
|
+
stroke,
|
|
8154
|
+
className,
|
|
8155
|
+
"data-ya-restricted": "true",
|
|
8156
|
+
"data-field-id": fieldId
|
|
8157
|
+
}
|
|
8158
|
+
);
|
|
8159
|
+
}
|
|
8160
|
+
return /* @__PURE__ */ jsxs12("span", { className: `ya-icon-wrapper ${wrapperClassName || ""}`, children: [
|
|
8161
|
+
/* @__PURE__ */ jsx20(
|
|
8162
|
+
"span",
|
|
8163
|
+
{
|
|
8164
|
+
ref: containerRef,
|
|
8165
|
+
className: `ya-icon-editable ${isEditing ? "ya-icon-editing" : ""} ${showSuccess ? "ya-icon-success" : ""}`,
|
|
8166
|
+
"data-ya-restricted": "true",
|
|
8167
|
+
"data-ya-icon": "true",
|
|
8168
|
+
"data-field-id": fieldId,
|
|
8169
|
+
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
8170
|
+
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
8171
|
+
onFocus: safeTriangleHandlers.onFocus,
|
|
8172
|
+
children: currentIcon ? /* @__PURE__ */ jsx20(DynamicIcon, { name: currentIcon, size, stroke, className }) : (
|
|
8173
|
+
// Placeholder when no icon set
|
|
8174
|
+
/* @__PURE__ */ jsx20("span", { className: `ya-icon-placeholder ${className || ""}`, style: { width: size, height: size }, children: /* @__PURE__ */ jsx20(DynamicIcon, { name: "IconPlus", size: size * 0.6, stroke }) })
|
|
8175
|
+
)
|
|
8176
|
+
}
|
|
8177
|
+
),
|
|
8178
|
+
editPopoverMounted && editPopoverPos && createPortal7(
|
|
8179
|
+
/* @__PURE__ */ jsx20(
|
|
8180
|
+
"div",
|
|
8181
|
+
{
|
|
8182
|
+
ref: editPopoverRef,
|
|
8183
|
+
className: "ya-icon-edit-popover",
|
|
8184
|
+
style: {
|
|
8185
|
+
top: editPopoverPos.top,
|
|
8186
|
+
left: editPopoverPos.left,
|
|
8187
|
+
transform: "translateX(-50%)",
|
|
8188
|
+
opacity: editPopoverVisible ? 1 : 0
|
|
8189
|
+
},
|
|
8190
|
+
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
8191
|
+
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
8192
|
+
children: /* @__PURE__ */ jsx20("button", { type: "button", onClick: startEdit, children: "Edit icon" })
|
|
8193
|
+
}
|
|
8194
|
+
),
|
|
8195
|
+
document.body
|
|
8196
|
+
),
|
|
8197
|
+
/* @__PURE__ */ jsx20(
|
|
8198
|
+
SafeTriangleBelow,
|
|
8199
|
+
{
|
|
8200
|
+
triggerRef,
|
|
8201
|
+
popoverRef: editPopoverRef,
|
|
8202
|
+
isVisible: showEditPopover && !isEditing && mode === "inline-edit",
|
|
8203
|
+
onLeave: triangleProps.onLeave,
|
|
8204
|
+
onStayInside: triangleProps.onStayInside
|
|
8205
|
+
}
|
|
8206
|
+
),
|
|
8207
|
+
isEditing && iconPickerPos && createPortal7(
|
|
8208
|
+
/* @__PURE__ */ jsx20(
|
|
8209
|
+
"div",
|
|
8210
|
+
{
|
|
8211
|
+
ref: iconPopoverRef,
|
|
8212
|
+
className: `ya-icon-picker-popover ${iconPickerPos.isAbove ? "ya-icon-picker-popover--above" : ""}`,
|
|
8213
|
+
style: {
|
|
8214
|
+
top: iconPickerPos.isAbove ? "auto" : iconPickerPos.top,
|
|
8215
|
+
bottom: iconPickerPos.isAbove ? window.innerHeight - iconPickerPos.top : "auto",
|
|
8216
|
+
left: iconPickerPos.left,
|
|
8217
|
+
transform: "translateX(-50%)"
|
|
8218
|
+
},
|
|
8219
|
+
children: /* @__PURE__ */ jsx20(
|
|
8220
|
+
IconPicker,
|
|
8221
|
+
{
|
|
8222
|
+
value: currentIcon,
|
|
8223
|
+
onChange: handleIconSelect,
|
|
8224
|
+
onClose: handleCancel
|
|
8225
|
+
}
|
|
8226
|
+
)
|
|
8227
|
+
}
|
|
8228
|
+
),
|
|
8229
|
+
document.body
|
|
6561
8230
|
)
|
|
6562
8231
|
] });
|
|
6563
8232
|
}
|
|
6564
8233
|
|
|
6565
8234
|
// src/components/YaContainer.tsx
|
|
6566
|
-
import { useCallback as
|
|
6567
|
-
import { createPortal as
|
|
8235
|
+
import { useCallback as useCallback23, useEffect as useEffect22, useRef as useRef22, useState as useState22 } from "react";
|
|
8236
|
+
import { createPortal as createPortal9 } from "react-dom";
|
|
6568
8237
|
|
|
6569
8238
|
// src/components/Tooltip.tsx
|
|
6570
|
-
import { useState as
|
|
6571
|
-
import { createPortal as
|
|
8239
|
+
import { useState as useState21, useRef as useRef21, useEffect as useEffect21, useLayoutEffect as useLayoutEffect5, useCallback as useCallback22 } from "react";
|
|
8240
|
+
import { createPortal as createPortal8 } from "react-dom";
|
|
6572
8241
|
|
|
6573
8242
|
// src/components/tooltip.css
|
|
6574
8243
|
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');
|
|
6575
8244
|
|
|
6576
8245
|
// src/components/Tooltip.tsx
|
|
6577
|
-
import { Fragment as
|
|
8246
|
+
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6578
8247
|
function Tooltip({
|
|
6579
8248
|
content,
|
|
6580
8249
|
children,
|
|
6581
8250
|
position = "bottom",
|
|
6582
8251
|
delay = 0
|
|
6583
8252
|
}) {
|
|
6584
|
-
const [isVisible, setIsVisible] =
|
|
6585
|
-
const [tooltipPosition, setTooltipPosition] =
|
|
6586
|
-
const [isMounted, setIsMounted] =
|
|
6587
|
-
const triggerRef =
|
|
6588
|
-
const tooltipRef =
|
|
6589
|
-
const timeoutRef =
|
|
6590
|
-
|
|
8253
|
+
const [isVisible, setIsVisible] = useState21(false);
|
|
8254
|
+
const [tooltipPosition, setTooltipPosition] = useState21(null);
|
|
8255
|
+
const [isMounted, setIsMounted] = useState21(false);
|
|
8256
|
+
const triggerRef = useRef21(null);
|
|
8257
|
+
const tooltipRef = useRef21(null);
|
|
8258
|
+
const timeoutRef = useRef21(null);
|
|
8259
|
+
useEffect21(() => {
|
|
6591
8260
|
setIsMounted(true);
|
|
6592
8261
|
}, []);
|
|
6593
|
-
const calculatePosition =
|
|
8262
|
+
const calculatePosition = useCallback22(() => {
|
|
6594
8263
|
if (!triggerRef.current) return null;
|
|
6595
8264
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
6596
8265
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
@@ -6675,7 +8344,7 @@ function Tooltip({
|
|
|
6675
8344
|
setIsVisible(false);
|
|
6676
8345
|
setTooltipPosition(null);
|
|
6677
8346
|
};
|
|
6678
|
-
|
|
8347
|
+
useEffect21(() => {
|
|
6679
8348
|
return () => {
|
|
6680
8349
|
if (timeoutRef.current) {
|
|
6681
8350
|
clearTimeout(timeoutRef.current);
|
|
@@ -6683,7 +8352,7 @@ function Tooltip({
|
|
|
6683
8352
|
};
|
|
6684
8353
|
}, []);
|
|
6685
8354
|
const edgePadding = 12;
|
|
6686
|
-
|
|
8355
|
+
useLayoutEffect5(() => {
|
|
6687
8356
|
if (!isVisible || !tooltipRef.current || !tooltipPosition || tooltipPosition.adjusted) {
|
|
6688
8357
|
return;
|
|
6689
8358
|
}
|
|
@@ -6734,8 +8403,8 @@ function Tooltip({
|
|
|
6734
8403
|
}
|
|
6735
8404
|
}
|
|
6736
8405
|
}, [isVisible, tooltipPosition]);
|
|
6737
|
-
const tooltipContent = isMounted && isVisible && tooltipPosition ?
|
|
6738
|
-
/* @__PURE__ */
|
|
8406
|
+
const tooltipContent = isMounted && isVisible && tooltipPosition ? createPortal8(
|
|
8407
|
+
/* @__PURE__ */ jsxs13(
|
|
6739
8408
|
"div",
|
|
6740
8409
|
{
|
|
6741
8410
|
ref: tooltipRef,
|
|
@@ -6748,7 +8417,7 @@ function Tooltip({
|
|
|
6748
8417
|
role: "tooltip",
|
|
6749
8418
|
children: [
|
|
6750
8419
|
content,
|
|
6751
|
-
/* @__PURE__ */
|
|
8420
|
+
/* @__PURE__ */ jsx21(
|
|
6752
8421
|
"div",
|
|
6753
8422
|
{
|
|
6754
8423
|
className: "ya-tooltip-v2-arrow",
|
|
@@ -6760,8 +8429,8 @@ function Tooltip({
|
|
|
6760
8429
|
),
|
|
6761
8430
|
document.body
|
|
6762
8431
|
) : null;
|
|
6763
|
-
return /* @__PURE__ */
|
|
6764
|
-
/* @__PURE__ */
|
|
8432
|
+
return /* @__PURE__ */ jsxs13(Fragment6, { children: [
|
|
8433
|
+
/* @__PURE__ */ jsx21(
|
|
6765
8434
|
"div",
|
|
6766
8435
|
{
|
|
6767
8436
|
ref: triggerRef,
|
|
@@ -6779,7 +8448,7 @@ function Tooltip({
|
|
|
6779
8448
|
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');
|
|
6780
8449
|
|
|
6781
8450
|
// src/components/YaContainer.tsx
|
|
6782
|
-
import { jsx as
|
|
8451
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6783
8452
|
function parseBackgroundConfig(value) {
|
|
6784
8453
|
if (!value) {
|
|
6785
8454
|
return { type: "none" };
|
|
@@ -6821,8 +8490,8 @@ function deriveContainerLabel(element) {
|
|
|
6821
8490
|
return tagLabels[tagName] || "Section";
|
|
6822
8491
|
}
|
|
6823
8492
|
function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick: _onAIClick, onClearClick, hasBackground }) {
|
|
6824
|
-
const [position, setPosition] =
|
|
6825
|
-
|
|
8493
|
+
const [position, setPosition] = useState22(null);
|
|
8494
|
+
useEffect22(() => {
|
|
6826
8495
|
const updatePosition = () => {
|
|
6827
8496
|
if (containerRef.current) {
|
|
6828
8497
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -6841,8 +8510,8 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick: _onAICli
|
|
|
6841
8510
|
};
|
|
6842
8511
|
}, [containerRef]);
|
|
6843
8512
|
if (!position) return null;
|
|
6844
|
-
return
|
|
6845
|
-
/* @__PURE__ */
|
|
8513
|
+
return createPortal9(
|
|
8514
|
+
/* @__PURE__ */ jsxs14(
|
|
6846
8515
|
"div",
|
|
6847
8516
|
{
|
|
6848
8517
|
className: "ya-container-toolbar",
|
|
@@ -6853,40 +8522,40 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick: _onAICli
|
|
|
6853
8522
|
},
|
|
6854
8523
|
onClick: (e) => e.stopPropagation(),
|
|
6855
8524
|
children: [
|
|
6856
|
-
/* @__PURE__ */
|
|
8525
|
+
/* @__PURE__ */ jsx22(Tooltip, { content: "Background Image", position: "bottom", children: /* @__PURE__ */ jsx22(
|
|
6857
8526
|
"button",
|
|
6858
8527
|
{
|
|
6859
8528
|
type: "button",
|
|
6860
8529
|
onClick: onImageClick,
|
|
6861
8530
|
"aria-label": "Edit background image",
|
|
6862
|
-
children: /* @__PURE__ */
|
|
6863
|
-
/* @__PURE__ */
|
|
6864
|
-
/* @__PURE__ */
|
|
6865
|
-
/* @__PURE__ */
|
|
8531
|
+
children: /* @__PURE__ */ jsxs14("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
8532
|
+
/* @__PURE__ */ jsx22("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
8533
|
+
/* @__PURE__ */ jsx22("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
8534
|
+
/* @__PURE__ */ jsx22("polyline", { points: "21 15 16 10 5 21" })
|
|
6866
8535
|
] })
|
|
6867
8536
|
}
|
|
6868
8537
|
) }),
|
|
6869
|
-
/* @__PURE__ */
|
|
8538
|
+
/* @__PURE__ */ jsx22(Tooltip, { content: "Background Color", position: "bottom", children: /* @__PURE__ */ jsx22(
|
|
6870
8539
|
"button",
|
|
6871
8540
|
{
|
|
6872
8541
|
type: "button",
|
|
6873
8542
|
onClick: onColorClick,
|
|
6874
8543
|
"aria-label": "Edit background color",
|
|
6875
|
-
children: /* @__PURE__ */
|
|
6876
|
-
/* @__PURE__ */
|
|
6877
|
-
/* @__PURE__ */
|
|
8544
|
+
children: /* @__PURE__ */ jsxs14("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
8545
|
+
/* @__PURE__ */ jsx22("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8546
|
+
/* @__PURE__ */ jsx22("path", { d: "M12 2a10 10 0 0 1 0 20", fill: "currentColor" })
|
|
6878
8547
|
] })
|
|
6879
8548
|
}
|
|
6880
8549
|
) }),
|
|
6881
|
-
hasBackground && /* @__PURE__ */
|
|
8550
|
+
hasBackground && /* @__PURE__ */ jsx22(Tooltip, { content: "Remove Background", position: "bottom", children: /* @__PURE__ */ jsx22(
|
|
6882
8551
|
"button",
|
|
6883
8552
|
{
|
|
6884
8553
|
type: "button",
|
|
6885
8554
|
onClick: onClearClick,
|
|
6886
8555
|
"aria-label": "Clear background",
|
|
6887
|
-
children: /* @__PURE__ */
|
|
6888
|
-
/* @__PURE__ */
|
|
6889
|
-
/* @__PURE__ */
|
|
8556
|
+
children: /* @__PURE__ */ jsxs14("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
8557
|
+
/* @__PURE__ */ jsx22("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8558
|
+
/* @__PURE__ */ jsx22("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
|
|
6890
8559
|
] })
|
|
6891
8560
|
}
|
|
6892
8561
|
) })
|
|
@@ -6905,13 +8574,13 @@ function YaContainer({
|
|
|
6905
8574
|
defaultBackground
|
|
6906
8575
|
}) {
|
|
6907
8576
|
const { getValue, setValue, saveToWorker, mode } = useContentStore();
|
|
6908
|
-
const containerRef =
|
|
6909
|
-
const [isHovered, setIsHovered] =
|
|
6910
|
-
const [isSelected, setIsSelected] =
|
|
6911
|
-
const [isDropMode, setIsDropMode] =
|
|
6912
|
-
const [isDropHover, setIsDropHover] =
|
|
6913
|
-
const [previewConfig, setPreviewConfig] =
|
|
6914
|
-
|
|
8577
|
+
const containerRef = useRef22(null);
|
|
8578
|
+
const [isHovered, setIsHovered] = useState22(false);
|
|
8579
|
+
const [isSelected, setIsSelected] = useState22(false);
|
|
8580
|
+
const [isDropMode, setIsDropMode] = useState22(false);
|
|
8581
|
+
const [isDropHover, setIsDropHover] = useState22(false);
|
|
8582
|
+
const [previewConfig, setPreviewConfig] = useState22(null);
|
|
8583
|
+
useEffect22(() => {
|
|
6915
8584
|
if (mode !== "inline-edit") return;
|
|
6916
8585
|
const containerEl = containerRef.current;
|
|
6917
8586
|
if (!containerEl) return;
|
|
@@ -6954,7 +8623,7 @@ function YaContainer({
|
|
|
6954
8623
|
overlayCustomProps["--ya-overlay-color"] = displayConfig.overlay.color;
|
|
6955
8624
|
overlayCustomProps["--ya-overlay-opacity"] = displayConfig.overlay.opacity;
|
|
6956
8625
|
}
|
|
6957
|
-
const handleImageClick =
|
|
8626
|
+
const handleImageClick = useCallback23(() => {
|
|
6958
8627
|
if (mode !== "inline-edit") return;
|
|
6959
8628
|
setIsSelected(true);
|
|
6960
8629
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -6974,7 +8643,7 @@ function YaContainer({
|
|
|
6974
8643
|
"*"
|
|
6975
8644
|
);
|
|
6976
8645
|
}, [mode, fieldId, backgroundConfig]);
|
|
6977
|
-
const handleColorClick =
|
|
8646
|
+
const handleColorClick = useCallback23(() => {
|
|
6978
8647
|
if (mode !== "inline-edit") return;
|
|
6979
8648
|
setIsSelected(true);
|
|
6980
8649
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -6994,7 +8663,7 @@ function YaContainer({
|
|
|
6994
8663
|
"*"
|
|
6995
8664
|
);
|
|
6996
8665
|
}, [mode, fieldId, backgroundConfig]);
|
|
6997
|
-
const handleAIClick =
|
|
8666
|
+
const handleAIClick = useCallback23(() => {
|
|
6998
8667
|
if (mode !== "inline-edit") return;
|
|
6999
8668
|
const label = deriveContainerLabel(containerRef.current);
|
|
7000
8669
|
window.parent.postMessage(
|
|
@@ -7007,14 +8676,14 @@ function YaContainer({
|
|
|
7007
8676
|
"*"
|
|
7008
8677
|
);
|
|
7009
8678
|
}, [mode, fieldId, backgroundConfig]);
|
|
7010
|
-
const handleClearClick =
|
|
8679
|
+
const handleClearClick = useCallback23(() => {
|
|
7011
8680
|
if (mode !== "inline-edit") return;
|
|
7012
8681
|
const clearedConfig = { type: "none" };
|
|
7013
8682
|
const serialized = serializeBackgroundConfig(clearedConfig);
|
|
7014
8683
|
setValue(fieldId, serialized);
|
|
7015
8684
|
saveToWorker?.(fieldId, serialized);
|
|
7016
8685
|
}, [mode, fieldId, setValue, saveToWorker]);
|
|
7017
|
-
|
|
8686
|
+
useEffect22(() => {
|
|
7018
8687
|
if (mode !== "inline-edit") return;
|
|
7019
8688
|
const handleMessage2 = (event) => {
|
|
7020
8689
|
if (event.data?.type === "YA_CONTAINER_UPDATE_PREVIEW" && event.data.fieldId === fieldId) {
|
|
@@ -7035,7 +8704,7 @@ function YaContainer({
|
|
|
7035
8704
|
window.addEventListener("message", handleMessage2);
|
|
7036
8705
|
return () => window.removeEventListener("message", handleMessage2);
|
|
7037
8706
|
}, [mode, fieldId]);
|
|
7038
|
-
|
|
8707
|
+
useEffect22(() => {
|
|
7039
8708
|
if (mode !== "inline-edit") return;
|
|
7040
8709
|
const handleDropModeMessage = (event) => {
|
|
7041
8710
|
if (event.data?.type === "DROP_MODE_START") {
|
|
@@ -7049,7 +8718,7 @@ function YaContainer({
|
|
|
7049
8718
|
window.addEventListener("message", handleDropModeMessage);
|
|
7050
8719
|
return () => window.removeEventListener("message", handleDropModeMessage);
|
|
7051
8720
|
}, [mode]);
|
|
7052
|
-
const handleDragEnter =
|
|
8721
|
+
const handleDragEnter = useCallback23(
|
|
7053
8722
|
(e) => {
|
|
7054
8723
|
if (!isDropMode) return;
|
|
7055
8724
|
e.preventDefault();
|
|
@@ -7073,7 +8742,7 @@ function YaContainer({
|
|
|
7073
8742
|
},
|
|
7074
8743
|
[isDropMode, fieldId]
|
|
7075
8744
|
);
|
|
7076
|
-
const handleDragOver =
|
|
8745
|
+
const handleDragOver = useCallback23(
|
|
7077
8746
|
(e) => {
|
|
7078
8747
|
if (!isDropMode) return;
|
|
7079
8748
|
e.preventDefault();
|
|
@@ -7081,7 +8750,7 @@ function YaContainer({
|
|
|
7081
8750
|
},
|
|
7082
8751
|
[isDropMode]
|
|
7083
8752
|
);
|
|
7084
|
-
const handleDragLeave =
|
|
8753
|
+
const handleDragLeave = useCallback23(
|
|
7085
8754
|
(e) => {
|
|
7086
8755
|
if (!isDropMode) return;
|
|
7087
8756
|
e.preventDefault();
|
|
@@ -7095,7 +8764,7 @@ function YaContainer({
|
|
|
7095
8764
|
},
|
|
7096
8765
|
[isDropMode]
|
|
7097
8766
|
);
|
|
7098
|
-
const handleDrop =
|
|
8767
|
+
const handleDrop = useCallback23(
|
|
7099
8768
|
(e) => {
|
|
7100
8769
|
if (!isDropMode) return;
|
|
7101
8770
|
e.preventDefault();
|
|
@@ -7113,7 +8782,7 @@ function YaContainer({
|
|
|
7113
8782
|
},
|
|
7114
8783
|
[isDropMode, fieldId]
|
|
7115
8784
|
);
|
|
7116
|
-
|
|
8785
|
+
useEffect22(() => {
|
|
7117
8786
|
if (!isSelected || mode !== "inline-edit") return;
|
|
7118
8787
|
let lastRectKey = "";
|
|
7119
8788
|
let lastTime = 0;
|
|
@@ -7148,7 +8817,7 @@ function YaContainer({
|
|
|
7148
8817
|
return () => cancelAnimationFrame(rafId);
|
|
7149
8818
|
}, [isSelected, fieldId, mode]);
|
|
7150
8819
|
if (mode === "read-only") {
|
|
7151
|
-
return /* @__PURE__ */
|
|
8820
|
+
return /* @__PURE__ */ jsx22(
|
|
7152
8821
|
Tag,
|
|
7153
8822
|
{
|
|
7154
8823
|
className: `ya-container ${className || ""}`,
|
|
@@ -7172,7 +8841,7 @@ function YaContainer({
|
|
|
7172
8841
|
isDropHover ? "ya-container-drop-hover" : "",
|
|
7173
8842
|
className || ""
|
|
7174
8843
|
].filter(Boolean).join(" ");
|
|
7175
|
-
return /* @__PURE__ */
|
|
8844
|
+
return /* @__PURE__ */ jsxs14(
|
|
7176
8845
|
Tag,
|
|
7177
8846
|
{
|
|
7178
8847
|
ref: containerRef,
|
|
@@ -7191,7 +8860,7 @@ function YaContainer({
|
|
|
7191
8860
|
onDrop: handleDrop,
|
|
7192
8861
|
children: [
|
|
7193
8862
|
children,
|
|
7194
|
-
mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */
|
|
8863
|
+
mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */ jsx22(
|
|
7195
8864
|
Toolbar,
|
|
7196
8865
|
{
|
|
7197
8866
|
containerRef,
|
|
@@ -7208,10 +8877,10 @@ function YaContainer({
|
|
|
7208
8877
|
}
|
|
7209
8878
|
|
|
7210
8879
|
// src/components/StaticText.tsx
|
|
7211
|
-
import { jsx as
|
|
8880
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
7212
8881
|
function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
7213
8882
|
const content = getContent(fieldId) || (typeof children === "string" ? children : "");
|
|
7214
|
-
return /* @__PURE__ */
|
|
8883
|
+
return /* @__PURE__ */ jsx23(
|
|
7215
8884
|
Component,
|
|
7216
8885
|
{
|
|
7217
8886
|
className,
|
|
@@ -7222,7 +8891,7 @@ function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
|
7222
8891
|
}
|
|
7223
8892
|
|
|
7224
8893
|
// src/components/StaticImage.tsx
|
|
7225
|
-
import { jsx as
|
|
8894
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
7226
8895
|
function parseImageValue2(value) {
|
|
7227
8896
|
if (!value) {
|
|
7228
8897
|
return { src: "" };
|
|
@@ -7258,7 +8927,7 @@ function MpImage({
|
|
|
7258
8927
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
7259
8928
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
7260
8929
|
const objectPosition = getObjectPosition3(imageData) || propObjectPosition || "50% 50%";
|
|
7261
|
-
return /* @__PURE__ */
|
|
8930
|
+
return /* @__PURE__ */ jsx24(
|
|
7262
8931
|
"img",
|
|
7263
8932
|
{
|
|
7264
8933
|
src: resolveAssetUrl(src),
|
|
@@ -7275,8 +8944,8 @@ function MpImage({
|
|
|
7275
8944
|
}
|
|
7276
8945
|
|
|
7277
8946
|
// src/components/MarkdownText.tsx
|
|
7278
|
-
import { Fragment as
|
|
7279
|
-
import { jsx as
|
|
8947
|
+
import { Fragment as Fragment7 } from "react";
|
|
8948
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
7280
8949
|
function tokenize(text2) {
|
|
7281
8950
|
const tokens = [];
|
|
7282
8951
|
let remaining = text2;
|
|
@@ -7338,13 +9007,13 @@ function tokensToElements(tokens) {
|
|
|
7338
9007
|
return tokens.map((token, index) => {
|
|
7339
9008
|
switch (token.type) {
|
|
7340
9009
|
case "text":
|
|
7341
|
-
return /* @__PURE__ */
|
|
9010
|
+
return /* @__PURE__ */ jsx25(Fragment7, { children: token.content }, index);
|
|
7342
9011
|
case "bold":
|
|
7343
|
-
return /* @__PURE__ */
|
|
9012
|
+
return /* @__PURE__ */ jsx25("strong", { children: token.content }, index);
|
|
7344
9013
|
case "italic":
|
|
7345
|
-
return /* @__PURE__ */
|
|
9014
|
+
return /* @__PURE__ */ jsx25("em", { children: token.content }, index);
|
|
7346
9015
|
case "link":
|
|
7347
|
-
return /* @__PURE__ */
|
|
9016
|
+
return /* @__PURE__ */ jsx25(
|
|
7348
9017
|
"a",
|
|
7349
9018
|
{
|
|
7350
9019
|
href: token.url,
|
|
@@ -7356,7 +9025,7 @@ function tokensToElements(tokens) {
|
|
|
7356
9025
|
index
|
|
7357
9026
|
);
|
|
7358
9027
|
case "newline":
|
|
7359
|
-
return /* @__PURE__ */
|
|
9028
|
+
return /* @__PURE__ */ jsx25("br", {}, index);
|
|
7360
9029
|
default:
|
|
7361
9030
|
return null;
|
|
7362
9031
|
}
|
|
@@ -7368,14 +9037,14 @@ function parseMarkdownToElements(content) {
|
|
|
7368
9037
|
}
|
|
7369
9038
|
function MarkdownText({ content, className }) {
|
|
7370
9039
|
const elements = parseMarkdownToElements(content);
|
|
7371
|
-
return /* @__PURE__ */
|
|
9040
|
+
return /* @__PURE__ */ jsx25("span", { className, children: elements });
|
|
7372
9041
|
}
|
|
7373
9042
|
|
|
7374
9043
|
// src/components/CollectionPage.tsx
|
|
7375
9044
|
import { useParams } from "wouter";
|
|
7376
9045
|
|
|
7377
9046
|
// src/hooks/useCollection.ts
|
|
7378
|
-
import { useState as
|
|
9047
|
+
import { useState as useState23, useEffect as useEffect23, useCallback as useCallback24, useRef as useRef23 } from "react";
|
|
7379
9048
|
|
|
7380
9049
|
// src/lib/collection-client.ts
|
|
7381
9050
|
function getEnvVar(key) {
|
|
@@ -7541,13 +9210,13 @@ function useCollectionList(options) {
|
|
|
7541
9210
|
orderDir,
|
|
7542
9211
|
enabled = true
|
|
7543
9212
|
} = options;
|
|
7544
|
-
const [data, setData] =
|
|
7545
|
-
const [isLoading, setIsLoading] =
|
|
7546
|
-
const [error, setError] =
|
|
7547
|
-
const [totalCount, setTotalCount] =
|
|
7548
|
-
const [currentPage, setCurrentPage] =
|
|
7549
|
-
const fetchVersion =
|
|
7550
|
-
const fetchData =
|
|
9213
|
+
const [data, setData] = useState23(null);
|
|
9214
|
+
const [isLoading, setIsLoading] = useState23(true);
|
|
9215
|
+
const [error, setError] = useState23(null);
|
|
9216
|
+
const [totalCount, setTotalCount] = useState23(0);
|
|
9217
|
+
const [currentPage, setCurrentPage] = useState23(page);
|
|
9218
|
+
const fetchVersion = useRef23(0);
|
|
9219
|
+
const fetchData = useCallback24(async (pageNum) => {
|
|
7551
9220
|
if (!enabled) {
|
|
7552
9221
|
setIsLoading(false);
|
|
7553
9222
|
return;
|
|
@@ -7585,15 +9254,15 @@ function useCollectionList(options) {
|
|
|
7585
9254
|
}
|
|
7586
9255
|
}
|
|
7587
9256
|
}, [collection, JSON.stringify(filters), pageSize, orderBy, orderDir, enabled]);
|
|
7588
|
-
|
|
9257
|
+
useEffect23(() => {
|
|
7589
9258
|
fetchData(page);
|
|
7590
9259
|
}, [fetchData, page]);
|
|
7591
9260
|
const totalPages = Math.ceil(totalCount / pageSize);
|
|
7592
9261
|
const hasMore = currentPage < totalPages;
|
|
7593
|
-
const refetch =
|
|
9262
|
+
const refetch = useCallback24(() => {
|
|
7594
9263
|
fetchData(currentPage);
|
|
7595
9264
|
}, [fetchData, currentPage]);
|
|
7596
|
-
const goToPage =
|
|
9265
|
+
const goToPage = useCallback24((newPage) => {
|
|
7597
9266
|
if (newPage >= 1 && newPage <= Math.max(1, totalPages)) {
|
|
7598
9267
|
fetchData(newPage);
|
|
7599
9268
|
}
|
|
@@ -7617,12 +9286,12 @@ function useCollectionRecord(options) {
|
|
|
7617
9286
|
slugValue,
|
|
7618
9287
|
enabled = true
|
|
7619
9288
|
} = options;
|
|
7620
|
-
const [data, setData] =
|
|
7621
|
-
const [isLoading, setIsLoading] =
|
|
7622
|
-
const [error, setError] =
|
|
7623
|
-
const [notFound, setNotFound] =
|
|
7624
|
-
const fetchVersion =
|
|
7625
|
-
const fetchData =
|
|
9289
|
+
const [data, setData] = useState23(null);
|
|
9290
|
+
const [isLoading, setIsLoading] = useState23(true);
|
|
9291
|
+
const [error, setError] = useState23(null);
|
|
9292
|
+
const [notFound, setNotFound] = useState23(false);
|
|
9293
|
+
const fetchVersion = useRef23(0);
|
|
9294
|
+
const fetchData = useCallback24(async () => {
|
|
7626
9295
|
if (!enabled || !slugValue) {
|
|
7627
9296
|
setIsLoading(false);
|
|
7628
9297
|
return;
|
|
@@ -7660,10 +9329,10 @@ function useCollectionRecord(options) {
|
|
|
7660
9329
|
}
|
|
7661
9330
|
}
|
|
7662
9331
|
}, [collection, slugField, slugValue, enabled]);
|
|
7663
|
-
|
|
9332
|
+
useEffect23(() => {
|
|
7664
9333
|
fetchData();
|
|
7665
9334
|
}, [fetchData]);
|
|
7666
|
-
const refetch =
|
|
9335
|
+
const refetch = useCallback24(() => {
|
|
7667
9336
|
fetchData();
|
|
7668
9337
|
}, [fetchData]);
|
|
7669
9338
|
return {
|
|
@@ -7720,7 +9389,7 @@ function CollectionDetailPage({
|
|
|
7720
9389
|
}
|
|
7721
9390
|
|
|
7722
9391
|
// src/components/CollectionList.tsx
|
|
7723
|
-
import { Fragment as
|
|
9392
|
+
import { Fragment as Fragment8, jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
7724
9393
|
function CollectionList({
|
|
7725
9394
|
collection,
|
|
7726
9395
|
prefix,
|
|
@@ -7753,7 +9422,7 @@ function CollectionList({
|
|
|
7753
9422
|
{ length: skeletonCount },
|
|
7754
9423
|
(_, index) => skeleton({ index })
|
|
7755
9424
|
);
|
|
7756
|
-
return Wrapper ? /* @__PURE__ */
|
|
9425
|
+
return Wrapper ? /* @__PURE__ */ jsx26(Wrapper, { children: skeletonItems }) : /* @__PURE__ */ jsx26(Fragment8, { children: skeletonItems });
|
|
7757
9426
|
}
|
|
7758
9427
|
if (result.error) {
|
|
7759
9428
|
return error?.(result.error) ?? null;
|
|
@@ -7763,7 +9432,7 @@ function CollectionList({
|
|
|
7763
9432
|
}
|
|
7764
9433
|
const items = result.data.map((record, index) => {
|
|
7765
9434
|
const fieldPrefix = `${prefix}.${record.id}`;
|
|
7766
|
-
return /* @__PURE__ */
|
|
9435
|
+
return /* @__PURE__ */ jsx26(
|
|
7767
9436
|
CollectionContentProvider,
|
|
7768
9437
|
{
|
|
7769
9438
|
record: record.data,
|
|
@@ -7776,9 +9445,9 @@ function CollectionList({
|
|
|
7776
9445
|
record.id
|
|
7777
9446
|
);
|
|
7778
9447
|
});
|
|
7779
|
-
const content = Wrapper ? /* @__PURE__ */
|
|
9448
|
+
const content = Wrapper ? /* @__PURE__ */ jsx26(Wrapper, { children: items }) : /* @__PURE__ */ jsx26(Fragment8, { children: items });
|
|
7780
9449
|
if (pagination) {
|
|
7781
|
-
return /* @__PURE__ */
|
|
9450
|
+
return /* @__PURE__ */ jsxs15(Fragment8, { children: [
|
|
7782
9451
|
content,
|
|
7783
9452
|
pagination({
|
|
7784
9453
|
currentPage: result.currentPage,
|
|
@@ -7793,7 +9462,7 @@ function CollectionList({
|
|
|
7793
9462
|
}
|
|
7794
9463
|
|
|
7795
9464
|
// src/components/CollectionItem.tsx
|
|
7796
|
-
import { jsx as
|
|
9465
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
7797
9466
|
function CollectionItem({
|
|
7798
9467
|
collection,
|
|
7799
9468
|
prefix,
|
|
@@ -7823,7 +9492,7 @@ function CollectionItem({
|
|
|
7823
9492
|
if (result.error || result.notFound || !result.data) {
|
|
7824
9493
|
return children(renderProps);
|
|
7825
9494
|
}
|
|
7826
|
-
return /* @__PURE__ */
|
|
9495
|
+
return /* @__PURE__ */ jsx27(
|
|
7827
9496
|
CollectionContentProvider,
|
|
7828
9497
|
{
|
|
7829
9498
|
record: result.data.data,
|
|
@@ -7838,10 +9507,10 @@ function CollectionItem({
|
|
|
7838
9507
|
|
|
7839
9508
|
// src/router/Link.tsx
|
|
7840
9509
|
import { Link as WouterLink2 } from "wouter";
|
|
7841
|
-
import { jsx as
|
|
9510
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
7842
9511
|
function Link2({ to, href, children, className, onClick, replace, ...props }) {
|
|
7843
9512
|
const target = href ?? to ?? "/";
|
|
7844
|
-
return /* @__PURE__ */
|
|
9513
|
+
return /* @__PURE__ */ jsx28(WouterLink2, { href: target, className, onClick, replace, ...props, children });
|
|
7845
9514
|
}
|
|
7846
9515
|
|
|
7847
9516
|
// src/router/useNavigate.ts
|
|
@@ -7860,7 +9529,7 @@ function useNavigate() {
|
|
|
7860
9529
|
|
|
7861
9530
|
// src/router/Router.tsx
|
|
7862
9531
|
import { Router as WouterRouter } from "wouter";
|
|
7863
|
-
import { jsx as
|
|
9532
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
7864
9533
|
function detectBasename() {
|
|
7865
9534
|
if (typeof window === "undefined") return "";
|
|
7866
9535
|
const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
|
|
@@ -7875,11 +9544,11 @@ function detectBasename() {
|
|
|
7875
9544
|
}
|
|
7876
9545
|
function Router({ children, base }) {
|
|
7877
9546
|
const basename = base ?? detectBasename();
|
|
7878
|
-
return /* @__PURE__ */
|
|
9547
|
+
return /* @__PURE__ */ jsx29(WouterRouter, { base: basename, children });
|
|
7879
9548
|
}
|
|
7880
9549
|
|
|
7881
9550
|
// src/router/ScrollRestoration.tsx
|
|
7882
|
-
import { useEffect as
|
|
9551
|
+
import { useEffect as useEffect24, useRef as useRef24 } from "react";
|
|
7883
9552
|
import { useLocation as useLocation3 } from "wouter";
|
|
7884
9553
|
var SCROLL_POSITIONS_KEY = "yoamigo-scroll-positions";
|
|
7885
9554
|
var HISTORY_INDEX_KEY = "yoamigo-history-index";
|
|
@@ -7915,10 +9584,10 @@ function setHistoryIndex(index) {
|
|
|
7915
9584
|
var globalHistoryIndex = 0;
|
|
7916
9585
|
function ScrollRestoration() {
|
|
7917
9586
|
const [location] = useLocation3();
|
|
7918
|
-
const previousLocation =
|
|
7919
|
-
const isPopState =
|
|
7920
|
-
const scrollPositionsRef =
|
|
7921
|
-
|
|
9587
|
+
const previousLocation = useRef24(location);
|
|
9588
|
+
const isPopState = useRef24(false);
|
|
9589
|
+
const scrollPositionsRef = useRef24({});
|
|
9590
|
+
useEffect24(() => {
|
|
7922
9591
|
if (typeof history !== "undefined" && "scrollRestoration" in history) {
|
|
7923
9592
|
history.scrollRestoration = "manual";
|
|
7924
9593
|
}
|
|
@@ -7936,7 +9605,7 @@ function ScrollRestoration() {
|
|
|
7936
9605
|
window.addEventListener("popstate", handlePopState);
|
|
7937
9606
|
return () => window.removeEventListener("popstate", handlePopState);
|
|
7938
9607
|
}, []);
|
|
7939
|
-
|
|
9608
|
+
useEffect24(() => {
|
|
7940
9609
|
if (previousLocation.current === location) return;
|
|
7941
9610
|
const prevHistoryIndex = globalHistoryIndex;
|
|
7942
9611
|
const currentScrollY = window.scrollY;
|
|
@@ -7956,7 +9625,7 @@ function ScrollRestoration() {
|
|
|
7956
9625
|
}
|
|
7957
9626
|
previousLocation.current = location;
|
|
7958
9627
|
}, [location]);
|
|
7959
|
-
|
|
9628
|
+
useEffect24(() => {
|
|
7960
9629
|
let timeoutId;
|
|
7961
9630
|
const handleScroll = () => {
|
|
7962
9631
|
clearTimeout(timeoutId);
|
|
@@ -8060,12 +9729,15 @@ function video(config) {
|
|
|
8060
9729
|
function embed(config) {
|
|
8061
9730
|
return JSON.stringify(config);
|
|
8062
9731
|
}
|
|
9732
|
+
function link(href) {
|
|
9733
|
+
return href;
|
|
9734
|
+
}
|
|
8063
9735
|
|
|
8064
9736
|
// src/contexts/CartContext.tsx
|
|
8065
|
-
import { createContext as createContext5, useContext as useContext5, useEffect as
|
|
9737
|
+
import { createContext as createContext5, useContext as useContext5, useEffect as useEffect26 } from "react";
|
|
8066
9738
|
|
|
8067
9739
|
// src/hooks/useCart.ts
|
|
8068
|
-
import { useState as
|
|
9740
|
+
import { useState as useState24, useEffect as useEffect25, useCallback as useCallback25, useRef as useRef25 } from "react";
|
|
8069
9741
|
|
|
8070
9742
|
// src/lib/cart-storage.ts
|
|
8071
9743
|
var CART_STORAGE_KEY_PREFIX = "yoamigo_cart_";
|
|
@@ -8201,11 +9873,11 @@ function getConfig2(options) {
|
|
|
8201
9873
|
}
|
|
8202
9874
|
function useCart(options = {}) {
|
|
8203
9875
|
const { userToken } = options;
|
|
8204
|
-
const [items, setItems] =
|
|
8205
|
-
const [isLoading, setIsLoading] =
|
|
8206
|
-
const [error, setError] =
|
|
8207
|
-
const fetchVersion =
|
|
8208
|
-
const configRef =
|
|
9876
|
+
const [items, setItems] = useState24([]);
|
|
9877
|
+
const [isLoading, setIsLoading] = useState24(true);
|
|
9878
|
+
const [error, setError] = useState24(null);
|
|
9879
|
+
const fetchVersion = useRef25(0);
|
|
9880
|
+
const configRef = useRef25(null);
|
|
8209
9881
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8210
9882
|
try {
|
|
8211
9883
|
configRef.current = getConfig2(options);
|
|
@@ -8214,7 +9886,7 @@ function useCart(options = {}) {
|
|
|
8214
9886
|
}
|
|
8215
9887
|
const isAuthenticated = !!userToken;
|
|
8216
9888
|
const sessionId = typeof window !== "undefined" ? getSessionId() : null;
|
|
8217
|
-
const apiCall =
|
|
9889
|
+
const apiCall = useCallback25(async (endpoint, method = "GET", body) => {
|
|
8218
9890
|
const config = configRef.current;
|
|
8219
9891
|
if (!config) throw new Error("Cart not configured");
|
|
8220
9892
|
const headers = {
|
|
@@ -8235,7 +9907,7 @@ function useCart(options = {}) {
|
|
|
8235
9907
|
);
|
|
8236
9908
|
return response.json();
|
|
8237
9909
|
}, [userToken, isAuthenticated, sessionId]);
|
|
8238
|
-
const fetchCart =
|
|
9910
|
+
const fetchCart = useCallback25(async () => {
|
|
8239
9911
|
const config = configRef.current;
|
|
8240
9912
|
if (!config) {
|
|
8241
9913
|
setIsLoading(false);
|
|
@@ -8274,10 +9946,10 @@ function useCart(options = {}) {
|
|
|
8274
9946
|
}
|
|
8275
9947
|
}
|
|
8276
9948
|
}, [apiCall, isAuthenticated, sessionId]);
|
|
8277
|
-
|
|
9949
|
+
useEffect25(() => {
|
|
8278
9950
|
fetchCart();
|
|
8279
9951
|
}, [fetchCart]);
|
|
8280
|
-
const addItem =
|
|
9952
|
+
const addItem = useCallback25(async (productId, collectionSlug, quantity = 1, variantId, data) => {
|
|
8281
9953
|
const config = configRef.current;
|
|
8282
9954
|
if (!config) throw new Error("Cart not configured");
|
|
8283
9955
|
setError(null);
|
|
@@ -8305,7 +9977,7 @@ function useCart(options = {}) {
|
|
|
8305
9977
|
throw err;
|
|
8306
9978
|
}
|
|
8307
9979
|
}, [apiCall, isAuthenticated, sessionId]);
|
|
8308
|
-
const updateQuantity =
|
|
9980
|
+
const updateQuantity = useCallback25(async (itemId, quantity) => {
|
|
8309
9981
|
const config = configRef.current;
|
|
8310
9982
|
if (!config) throw new Error("Cart not configured");
|
|
8311
9983
|
setError(null);
|
|
@@ -8327,7 +9999,7 @@ function useCart(options = {}) {
|
|
|
8327
9999
|
throw err;
|
|
8328
10000
|
}
|
|
8329
10001
|
}, [apiCall, isAuthenticated, sessionId]);
|
|
8330
|
-
const removeItem =
|
|
10002
|
+
const removeItem = useCallback25(async (itemId) => {
|
|
8331
10003
|
const config = configRef.current;
|
|
8332
10004
|
if (!config) throw new Error("Cart not configured");
|
|
8333
10005
|
setError(null);
|
|
@@ -8349,7 +10021,7 @@ function useCart(options = {}) {
|
|
|
8349
10021
|
throw err;
|
|
8350
10022
|
}
|
|
8351
10023
|
}, [apiCall, isAuthenticated, sessionId]);
|
|
8352
|
-
const clearCart =
|
|
10024
|
+
const clearCart = useCallback25(async () => {
|
|
8353
10025
|
const config = configRef.current;
|
|
8354
10026
|
if (!config) throw new Error("Cart not configured");
|
|
8355
10027
|
setError(null);
|
|
@@ -8371,7 +10043,7 @@ function useCart(options = {}) {
|
|
|
8371
10043
|
throw err;
|
|
8372
10044
|
}
|
|
8373
10045
|
}, [apiCall, isAuthenticated, sessionId]);
|
|
8374
|
-
const mergeGuestCart =
|
|
10046
|
+
const mergeGuestCart = useCallback25(async () => {
|
|
8375
10047
|
if (!isAuthenticated || !sessionId) return;
|
|
8376
10048
|
setError(null);
|
|
8377
10049
|
try {
|
|
@@ -8408,7 +10080,7 @@ function useCart(options = {}) {
|
|
|
8408
10080
|
}
|
|
8409
10081
|
|
|
8410
10082
|
// src/contexts/CartContext.tsx
|
|
8411
|
-
import { jsx as
|
|
10083
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
8412
10084
|
var CartContext = createContext5(null);
|
|
8413
10085
|
function CartProvider({
|
|
8414
10086
|
children,
|
|
@@ -8417,13 +10089,13 @@ function CartProvider({
|
|
|
8417
10089
|
...options
|
|
8418
10090
|
}) {
|
|
8419
10091
|
const cart = useCart({ ...options, userToken });
|
|
8420
|
-
|
|
10092
|
+
useEffect26(() => {
|
|
8421
10093
|
if (userToken) {
|
|
8422
10094
|
cart.mergeGuestCart();
|
|
8423
10095
|
}
|
|
8424
10096
|
onUserTokenChange?.(!!userToken);
|
|
8425
10097
|
}, [userToken]);
|
|
8426
|
-
return /* @__PURE__ */
|
|
10098
|
+
return /* @__PURE__ */ jsx30(CartContext.Provider, { value: cart, children });
|
|
8427
10099
|
}
|
|
8428
10100
|
function useCartContext() {
|
|
8429
10101
|
const context = useContext5(CartContext);
|
|
@@ -8437,7 +10109,7 @@ function useOptionalCartContext() {
|
|
|
8437
10109
|
}
|
|
8438
10110
|
|
|
8439
10111
|
// src/hooks/useCheckout.ts
|
|
8440
|
-
import { useState as
|
|
10112
|
+
import { useState as useState25, useCallback as useCallback26, useRef as useRef26 } from "react";
|
|
8441
10113
|
function getConfig3(options) {
|
|
8442
10114
|
if (typeof window === "undefined") {
|
|
8443
10115
|
throw new Error("useCheckout requires browser environment");
|
|
@@ -8455,9 +10127,9 @@ function getConfig3(options) {
|
|
|
8455
10127
|
}
|
|
8456
10128
|
function useCheckout(options = {}) {
|
|
8457
10129
|
const { userToken } = options;
|
|
8458
|
-
const [isLoading, setIsLoading] =
|
|
8459
|
-
const [error, setError] =
|
|
8460
|
-
const configRef =
|
|
10130
|
+
const [isLoading, setIsLoading] = useState25(false);
|
|
10131
|
+
const [error, setError] = useState25(null);
|
|
10132
|
+
const configRef = useRef26(null);
|
|
8461
10133
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8462
10134
|
try {
|
|
8463
10135
|
configRef.current = getConfig3(options);
|
|
@@ -8466,7 +10138,7 @@ function useCheckout(options = {}) {
|
|
|
8466
10138
|
}
|
|
8467
10139
|
const isAuthenticated = !!userToken;
|
|
8468
10140
|
const sessionId = typeof window !== "undefined" ? getSessionId() : null;
|
|
8469
|
-
const initiateCheckout =
|
|
10141
|
+
const initiateCheckout = useCallback26(async (checkoutOptions) => {
|
|
8470
10142
|
const config = configRef.current;
|
|
8471
10143
|
if (!config) {
|
|
8472
10144
|
throw new Error("Checkout not configured");
|
|
@@ -8511,10 +10183,10 @@ function useCheckout(options = {}) {
|
|
|
8511
10183
|
}
|
|
8512
10184
|
function useCheckoutStatus(options) {
|
|
8513
10185
|
const { userToken, sessionId: checkoutSessionId, poll = false, pollInterval = 2e3 } = options;
|
|
8514
|
-
const [status, setStatus] =
|
|
8515
|
-
const [isLoading, setIsLoading] =
|
|
8516
|
-
const [error, setError] =
|
|
8517
|
-
const configRef =
|
|
10186
|
+
const [status, setStatus] = useState25(null);
|
|
10187
|
+
const [isLoading, setIsLoading] = useState25(true);
|
|
10188
|
+
const [error, setError] = useState25(null);
|
|
10189
|
+
const configRef = useRef26(null);
|
|
8518
10190
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8519
10191
|
try {
|
|
8520
10192
|
configRef.current = getConfig3(options);
|
|
@@ -8523,7 +10195,7 @@ function useCheckoutStatus(options) {
|
|
|
8523
10195
|
}
|
|
8524
10196
|
const isAuthenticated = !!userToken;
|
|
8525
10197
|
const guestSessionId = typeof window !== "undefined" ? getSessionId() : null;
|
|
8526
|
-
const fetchStatus =
|
|
10198
|
+
const fetchStatus = useCallback26(async () => {
|
|
8527
10199
|
const config = configRef.current;
|
|
8528
10200
|
if (!config || !checkoutSessionId) {
|
|
8529
10201
|
setIsLoading(false);
|
|
@@ -8555,7 +10227,7 @@ function useCheckoutStatus(options) {
|
|
|
8555
10227
|
setIsLoading(false);
|
|
8556
10228
|
}
|
|
8557
10229
|
}, [checkoutSessionId, userToken, isAuthenticated, guestSessionId]);
|
|
8558
|
-
|
|
10230
|
+
useState25(() => {
|
|
8559
10231
|
fetchStatus();
|
|
8560
10232
|
if (poll) {
|
|
8561
10233
|
const interval = setInterval(() => {
|
|
@@ -8647,7 +10319,7 @@ function useProduct(options) {
|
|
|
8647
10319
|
}
|
|
8648
10320
|
|
|
8649
10321
|
// src/hooks/useSubscription.ts
|
|
8650
|
-
import { useState as
|
|
10322
|
+
import { useState as useState26, useCallback as useCallback27, useRef as useRef27 } from "react";
|
|
8651
10323
|
function getConfig4(options) {
|
|
8652
10324
|
if (typeof window === "undefined") {
|
|
8653
10325
|
throw new Error("useSubscription requires browser environment");
|
|
@@ -8665,16 +10337,16 @@ function getConfig4(options) {
|
|
|
8665
10337
|
}
|
|
8666
10338
|
function useSubscription(options = {}) {
|
|
8667
10339
|
const { userToken } = options;
|
|
8668
|
-
const [isLoading, setIsLoading] =
|
|
8669
|
-
const [error, setError] =
|
|
8670
|
-
const configRef =
|
|
10340
|
+
const [isLoading, setIsLoading] = useState26(false);
|
|
10341
|
+
const [error, setError] = useState26(null);
|
|
10342
|
+
const configRef = useRef27(null);
|
|
8671
10343
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8672
10344
|
try {
|
|
8673
10345
|
configRef.current = getConfig4(options);
|
|
8674
10346
|
} catch {
|
|
8675
10347
|
}
|
|
8676
10348
|
}
|
|
8677
|
-
const subscribe =
|
|
10349
|
+
const subscribe = useCallback27(async (params) => {
|
|
8678
10350
|
const config = configRef.current;
|
|
8679
10351
|
if (!config) {
|
|
8680
10352
|
return {
|
|
@@ -8740,7 +10412,7 @@ function useSubscription(options = {}) {
|
|
|
8740
10412
|
}
|
|
8741
10413
|
|
|
8742
10414
|
// src/hooks/useSubscriptionTiers.ts
|
|
8743
|
-
import { useState as
|
|
10415
|
+
import { useState as useState27, useCallback as useCallback28, useEffect as useEffect27, useRef as useRef28 } from "react";
|
|
8744
10416
|
function getConfig5(options) {
|
|
8745
10417
|
if (typeof window === "undefined") {
|
|
8746
10418
|
throw new Error("useSubscriptionTiers requires browser environment");
|
|
@@ -8762,17 +10434,17 @@ function getConfig5(options) {
|
|
|
8762
10434
|
}
|
|
8763
10435
|
function useSubscriptionTiers(options = {}) {
|
|
8764
10436
|
const { fetchOnMount = true } = options;
|
|
8765
|
-
const [tiers, setTiers] =
|
|
8766
|
-
const [isLoading, setIsLoading] =
|
|
8767
|
-
const [error, setError] =
|
|
8768
|
-
const configRef =
|
|
10437
|
+
const [tiers, setTiers] = useState27([]);
|
|
10438
|
+
const [isLoading, setIsLoading] = useState27(false);
|
|
10439
|
+
const [error, setError] = useState27(null);
|
|
10440
|
+
const configRef = useRef28(null);
|
|
8769
10441
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8770
10442
|
try {
|
|
8771
10443
|
configRef.current = getConfig5(options);
|
|
8772
10444
|
} catch {
|
|
8773
10445
|
}
|
|
8774
10446
|
}
|
|
8775
|
-
const refresh =
|
|
10447
|
+
const refresh = useCallback28(async () => {
|
|
8776
10448
|
const config = configRef.current;
|
|
8777
10449
|
if (!config) {
|
|
8778
10450
|
setError("Subscription tiers not configured");
|
|
@@ -8804,7 +10476,7 @@ function useSubscriptionTiers(options = {}) {
|
|
|
8804
10476
|
setIsLoading(false);
|
|
8805
10477
|
}
|
|
8806
10478
|
}, []);
|
|
8807
|
-
|
|
10479
|
+
useEffect27(() => {
|
|
8808
10480
|
if (fetchOnMount && configRef.current) {
|
|
8809
10481
|
refresh();
|
|
8810
10482
|
}
|
|
@@ -8818,7 +10490,7 @@ function useSubscriptionTiers(options = {}) {
|
|
|
8818
10490
|
}
|
|
8819
10491
|
|
|
8820
10492
|
// src/hooks/useCustomerPortal.ts
|
|
8821
|
-
import { useState as
|
|
10493
|
+
import { useState as useState28, useCallback as useCallback29, useRef as useRef29 } from "react";
|
|
8822
10494
|
function getConfig6(options) {
|
|
8823
10495
|
if (typeof window === "undefined") {
|
|
8824
10496
|
throw new Error("useCustomerPortal requires browser environment");
|
|
@@ -8836,16 +10508,16 @@ function getConfig6(options) {
|
|
|
8836
10508
|
}
|
|
8837
10509
|
function useCustomerPortal(options) {
|
|
8838
10510
|
const { userToken } = options;
|
|
8839
|
-
const [isLoading, setIsLoading] =
|
|
8840
|
-
const [error, setError] =
|
|
8841
|
-
const configRef =
|
|
10511
|
+
const [isLoading, setIsLoading] = useState28(false);
|
|
10512
|
+
const [error, setError] = useState28(null);
|
|
10513
|
+
const configRef = useRef29(null);
|
|
8842
10514
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8843
10515
|
try {
|
|
8844
10516
|
configRef.current = getConfig6(options);
|
|
8845
10517
|
} catch {
|
|
8846
10518
|
}
|
|
8847
10519
|
}
|
|
8848
|
-
const openPortal =
|
|
10520
|
+
const openPortal = useCallback29(async (params) => {
|
|
8849
10521
|
const config = configRef.current;
|
|
8850
10522
|
if (!config) {
|
|
8851
10523
|
return {
|
|
@@ -8907,7 +10579,7 @@ function useCustomerPortal(options) {
|
|
|
8907
10579
|
}
|
|
8908
10580
|
|
|
8909
10581
|
// src/hooks/useSubscriptionStatus.ts
|
|
8910
|
-
import { useState as
|
|
10582
|
+
import { useState as useState29, useCallback as useCallback30, useRef as useRef30, useEffect as useEffect28 } from "react";
|
|
8911
10583
|
function getConfig7(options) {
|
|
8912
10584
|
if (typeof window === "undefined") {
|
|
8913
10585
|
throw new Error("useSubscriptionStatus requires browser environment");
|
|
@@ -8925,18 +10597,18 @@ function getConfig7(options) {
|
|
|
8925
10597
|
}
|
|
8926
10598
|
function useSubscriptionStatus(options) {
|
|
8927
10599
|
const { userToken, autoFetch = true, pollInterval = 0 } = options;
|
|
8928
|
-
const [status, setStatus] =
|
|
8929
|
-
const [subscriptions, setSubscriptions] =
|
|
8930
|
-
const [isLoading, setIsLoading] =
|
|
8931
|
-
const [error, setError] =
|
|
8932
|
-
const configRef =
|
|
10600
|
+
const [status, setStatus] = useState29(null);
|
|
10601
|
+
const [subscriptions, setSubscriptions] = useState29([]);
|
|
10602
|
+
const [isLoading, setIsLoading] = useState29(autoFetch);
|
|
10603
|
+
const [error, setError] = useState29(null);
|
|
10604
|
+
const configRef = useRef30(null);
|
|
8933
10605
|
if (!configRef.current && typeof window !== "undefined") {
|
|
8934
10606
|
try {
|
|
8935
10607
|
configRef.current = getConfig7(options);
|
|
8936
10608
|
} catch {
|
|
8937
10609
|
}
|
|
8938
10610
|
}
|
|
8939
|
-
const fetchStatus =
|
|
10611
|
+
const fetchStatus = useCallback30(async () => {
|
|
8940
10612
|
const config = configRef.current;
|
|
8941
10613
|
if (!config) {
|
|
8942
10614
|
setError("Subscription status not configured");
|
|
@@ -8975,12 +10647,12 @@ function useSubscriptionStatus(options) {
|
|
|
8975
10647
|
setIsLoading(false);
|
|
8976
10648
|
}
|
|
8977
10649
|
}, [userToken]);
|
|
8978
|
-
|
|
10650
|
+
useEffect28(() => {
|
|
8979
10651
|
if (autoFetch && userToken) {
|
|
8980
10652
|
fetchStatus();
|
|
8981
10653
|
}
|
|
8982
10654
|
}, [autoFetch, userToken, fetchStatus]);
|
|
8983
|
-
|
|
10655
|
+
useEffect28(() => {
|
|
8984
10656
|
if (pollInterval <= 0 || !userToken) {
|
|
8985
10657
|
return;
|
|
8986
10658
|
}
|
|
@@ -9008,6 +10680,10 @@ export {
|
|
|
9008
10680
|
CollectionListPage,
|
|
9009
10681
|
ContentStoreProvider,
|
|
9010
10682
|
ContentStoreProvider2 as ContentStoreProviderProd,
|
|
10683
|
+
DynamicIcon,
|
|
10684
|
+
ICON_CATEGORIES,
|
|
10685
|
+
ICON_METADATA,
|
|
10686
|
+
IconPicker,
|
|
9011
10687
|
Link2 as Link,
|
|
9012
10688
|
MarkdownText,
|
|
9013
10689
|
Route,
|
|
@@ -9021,8 +10697,10 @@ export {
|
|
|
9021
10697
|
Tooltip,
|
|
9022
10698
|
YaContainer,
|
|
9023
10699
|
YaEmbed,
|
|
10700
|
+
YaIcon,
|
|
9024
10701
|
YaImage,
|
|
9025
10702
|
YaLink,
|
|
10703
|
+
YaProtectedMedia,
|
|
9026
10704
|
YaText,
|
|
9027
10705
|
YaVideo,
|
|
9028
10706
|
background,
|
|
@@ -9040,6 +10718,11 @@ export {
|
|
|
9040
10718
|
getAllContent,
|
|
9041
10719
|
getCollectionClient,
|
|
9042
10720
|
getContent,
|
|
10721
|
+
getIcon,
|
|
10722
|
+
getIconLabel,
|
|
10723
|
+
getIconMeta,
|
|
10724
|
+
getIconPickerLabel,
|
|
10725
|
+
getIconsByCategory,
|
|
9043
10726
|
getLocalCartItemCount,
|
|
9044
10727
|
getLocalCartItems,
|
|
9045
10728
|
getSessionId,
|
|
@@ -9048,13 +10731,20 @@ export {
|
|
|
9048
10731
|
image,
|
|
9049
10732
|
imageCrossfadeStrategy,
|
|
9050
10733
|
initBuilderSelection,
|
|
10734
|
+
isIconLoaded,
|
|
10735
|
+
link,
|
|
9051
10736
|
linkTransitionStrategy,
|
|
10737
|
+
loadIcon,
|
|
9052
10738
|
parseBackgroundConfig,
|
|
9053
10739
|
parseEmbedUrl,
|
|
9054
10740
|
parseFieldValue,
|
|
10741
|
+
preloadIcons,
|
|
9055
10742
|
registerContent,
|
|
10743
|
+
registerIcon,
|
|
10744
|
+
registerIcons,
|
|
9056
10745
|
resetCollectionClient,
|
|
9057
10746
|
resolveAssetUrl,
|
|
10747
|
+
searchIcons,
|
|
9058
10748
|
serializeBackgroundConfig,
|
|
9059
10749
|
serializeEmbedValue,
|
|
9060
10750
|
serializeImageValue,
|