@tecof/theme-editor 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -27,6 +27,13 @@ import ReactDOM__default from 'react-dom';
27
27
  // src/api.ts
28
28
  var TecofApiClient = class {
29
29
  constructor(apiUrl, secretKey, customCdnUrl) {
30
+ /**
31
+ * Get a component preview screenshot as a Blob URL.
32
+ * Calls POST /api/store/component-preview with domain + componentName.
33
+ * Returns a blob:// URL that can be used as an img src.
34
+ * Results are cached client-side in a Map.
35
+ */
36
+ this.previewBlobCache = /* @__PURE__ */ new Map();
30
37
  this.apiUrl = apiUrl.replace(/\/+$/, "");
31
38
  this.secretKey = secretKey;
32
39
  this.customCdnUrl = customCdnUrl ? customCdnUrl.replace(/\/+$/, "") : void 0;
@@ -190,6 +197,30 @@ var TecofApiClient = class {
190
197
  };
191
198
  }
192
199
  }
200
+ async getComponentPreview(domain, componentName) {
201
+ const cacheKey = `${domain}:${componentName}`;
202
+ if (this.previewBlobCache.has(cacheKey)) {
203
+ return this.previewBlobCache.get(cacheKey);
204
+ }
205
+ try {
206
+ const res2 = await fetch(`${this.apiUrl}/api/store/component-preview`, {
207
+ method: "POST",
208
+ headers: {
209
+ "x-secret-key": this.secretKey,
210
+ Accept: "image/png",
211
+ "Content-Type": "application/json"
212
+ },
213
+ body: JSON.stringify({ domain, componentName })
214
+ });
215
+ if (!res2.ok) return null;
216
+ const blob2 = await res2.blob();
217
+ const blobUrl = URL.createObjectURL(blob2);
218
+ this.previewBlobCache.set(cacheKey, blobUrl);
219
+ return blobUrl;
220
+ } catch {
221
+ return null;
222
+ }
223
+ }
193
224
  /** CDN base URL (defaults to apiUrl if not set) */
194
225
  get cdnUrl() {
195
226
  return this.customCdnUrl || this.apiUrl;
@@ -216,6 +247,55 @@ function useTecof() {
216
247
  return ctx;
217
248
  }
218
249
  var EMPTY_PAGE = { content: [], root: { props: {} }, zones: {} };
250
+ var ComponentDrawerItem = ({
251
+ name: name3,
252
+ apiClient,
253
+ children
254
+ }) => {
255
+ const [imgSrc, setImgSrc] = useState(null);
256
+ const [loading, setLoading] = useState(false);
257
+ const [error2, setError] = useState(false);
258
+ const fetchedRef = useRef(false);
259
+ const handleMouseEnter = useCallback(async () => {
260
+ if (fetchedRef.current) return;
261
+ fetchedRef.current = true;
262
+ setLoading(true);
263
+ try {
264
+ const domain = typeof window !== "undefined" ? window.location.hostname : "";
265
+ const blobUrl = await apiClient.getComponentPreview(domain, name3);
266
+ if (blobUrl) {
267
+ setImgSrc(blobUrl);
268
+ } else {
269
+ setError(true);
270
+ }
271
+ } catch {
272
+ setError(true);
273
+ } finally {
274
+ setLoading(false);
275
+ }
276
+ }, [name3, apiClient]);
277
+ return /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-item-group group", onMouseEnter: handleMouseEnter, children: [
278
+ children,
279
+ /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover", children: [
280
+ /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-header", children: [
281
+ name3,
282
+ " \xD6nizleme"
283
+ ] }),
284
+ /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-body", children: [
285
+ (loading || !imgSrc && !error2) && /* @__PURE__ */ jsx("div", { className: "tecof-drawer-skeleton" }),
286
+ imgSrc && /* @__PURE__ */ jsx(
287
+ "img",
288
+ {
289
+ src: imgSrc,
290
+ alt: `${name3} preview`,
291
+ className: "tecof-drawer-img"
292
+ }
293
+ ),
294
+ error2 && /* @__PURE__ */ jsx("div", { className: "tecof-drawer-preview-error", children: "\xD6nizleme y\xFCklenemedi" })
295
+ ] })
296
+ ] })
297
+ ] });
298
+ };
219
299
  var TecofEditor = ({
220
300
  pageId,
221
301
  config: config3,
@@ -357,36 +437,7 @@ var TecofEditor = ({
357
437
  const mergedOverrides = {
358
438
  header: () => /* @__PURE__ */ jsx(Fragment, {}),
359
439
  drawerItem: ({ children, name: name3 }) => {
360
- const token = secretKey;
361
- return /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-item-group group", children: [
362
- children,
363
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover", children: [
364
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-header", children: [
365
- name3,
366
- " \xD6nizleme"
367
- ] }),
368
- /* @__PURE__ */ jsxs("div", { className: "tecof-drawer-popover-body", children: [
369
- /* @__PURE__ */ jsx("div", { className: "tecof-drawer-skeleton" }),
370
- /* @__PURE__ */ jsx(
371
- "img",
372
- {
373
- src: `/api/screenshot?componentName=${name3}&token=${token}`,
374
- alt: `${name3} preview`,
375
- className: "tecof-drawer-img",
376
- onLoad: (e3) => {
377
- const loader2 = e3.currentTarget.previousElementSibling;
378
- if (loader2) loader2.remove();
379
- },
380
- onError: (e3) => {
381
- const loader2 = e3.currentTarget.previousElementSibling;
382
- if (loader2) loader2.remove();
383
- e3.currentTarget.style.display = "none";
384
- }
385
- }
386
- )
387
- ] })
388
- ] })
389
- ] });
440
+ return /* @__PURE__ */ jsx(ComponentDrawerItem, { name: name3, apiClient, children });
390
441
  },
391
442
  ...overrides || {}
392
443
  };
@@ -895,8 +946,11 @@ var LanguageField = ({
895
946
  return existing || { code, value: "" };
896
947
  });
897
948
  }, [value, merchantInfo]);
949
+ const valuesRef = useRef(values);
950
+ valuesRef.current = values;
898
951
  const handleChange = useCallback((code, newVal) => {
899
- const updated = [...values];
952
+ const current = valuesRef.current;
953
+ const updated = [...current];
900
954
  const idx = updated.findIndex((v2) => v2.code === code);
901
955
  if (idx >= 0) {
902
956
  updated[idx] = { ...updated[idx], value: newVal };
@@ -904,10 +958,10 @@ var LanguageField = ({
904
958
  updated.push({ code, value: newVal });
905
959
  }
906
960
  onChange(updated);
907
- }, [values, onChange]);
961
+ }, [onChange]);
908
962
  const getCurrentText = useCallback(() => {
909
- return values.find((v2) => v2.code === activeTab)?.value || "";
910
- }, [values, activeTab]);
963
+ return valuesRef.current.find((v2) => v2.code === activeTab)?.value || "";
964
+ }, [activeTab]);
911
965
  const handleFastFill = useCallback(() => {
912
966
  const text2 = getCurrentText();
913
967
  if (!text2) return;
@@ -930,7 +984,7 @@ var LanguageField = ({
930
984
  try {
931
985
  const res2 = await apiClient.translate(text2, activeTab, otherLocales, isHtml);
932
986
  if (res2.success && Array.isArray(res2.data)) {
933
- const updated = [...values];
987
+ const updated = [...valuesRef.current];
934
988
  for (const t2 of res2.data) {
935
989
  const idx = updated.findIndex((v2) => v2.code === t2.code);
936
990
  if (idx >= 0) {
@@ -950,7 +1004,7 @@ var LanguageField = ({
950
1004
  setTranslating(false);
951
1005
  setTimeout(() => setStatusMsg(null), 3e3);
952
1006
  }
953
- }, [getCurrentText, merchantInfo, activeTab, values, onChange, apiClient, isHtml]);
1007
+ }, [getCurrentText, merchantInfo, activeTab, onChange, apiClient, isHtml]);
954
1008
  if (loading) return /* @__PURE__ */ jsx(FieldLoading, {});
955
1009
  if (error2 && !merchantInfo) return /* @__PURE__ */ jsx("div", { className: "tecof-lang-error", children: error2 });
956
1010
  if (!merchantInfo) return null;