@ixo/editor 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12719,25 +12719,25 @@ var MatrixMetadataManager = class {
12719
12719
  }
12720
12720
  try {
12721
12721
  const promises = [];
12722
- if (metadata.cover !== void 0) {
12722
+ if ("cover" in metadata) {
12723
12723
  promises.push(
12724
12724
  this.matrixClient.sendStateEvent(
12725
12725
  this.roomId,
12726
12726
  COVER_IMAGE_EVENT_TYPE,
12727
12727
  { url: metadata.cover || null },
12728
- // Wrap in object - Matrix requires JSON content
12728
+ // Wrap in object - null means removed
12729
12729
  ""
12730
12730
  // Empty state key
12731
12731
  )
12732
12732
  );
12733
12733
  }
12734
- if (metadata.icon !== void 0) {
12734
+ if ("icon" in metadata) {
12735
12735
  promises.push(
12736
12736
  this.matrixClient.sendStateEvent(
12737
12737
  this.roomId,
12738
12738
  COVER_ICON_EVENT_TYPE,
12739
12739
  { url: metadata.icon || null },
12740
- // Wrap in object - Matrix requires JSON content
12740
+ // Wrap in object - null means removed
12741
12741
  ""
12742
12742
  // Empty state key
12743
12743
  )
@@ -13041,6 +13041,138 @@ function useCreateCollaborativeIxoEditor(options) {
13041
13041
  // src/mantine/components/CoverImage.tsx
13042
13042
  import React149, { useState as useState48, useRef as useRef8, useEffect as useEffect38 } from "react";
13043
13043
  import { Box as Box24, Button as Button32, Group as Group44 } from "@mantine/core";
13044
+
13045
+ // src/core/lib/imageTransform.ts
13046
+ var CLOUDFLARE_CDN_BASE = "https://www.ixo.earth/cdn-cgi/image";
13047
+ var ImagePresets = {
13048
+ /**
13049
+ * Cover image preset (Notion-style)
13050
+ * Wide banner images that fill the width of the page
13051
+ */
13052
+ cover: {
13053
+ desktop: {
13054
+ width: 1920,
13055
+ fit: "cover",
13056
+ quality: 80,
13057
+ format: "auto",
13058
+ metadata: "none"
13059
+ },
13060
+ tablet: {
13061
+ width: 960,
13062
+ fit: "cover",
13063
+ quality: 80,
13064
+ format: "auto",
13065
+ metadata: "none"
13066
+ },
13067
+ mobile: {
13068
+ width: 640,
13069
+ fit: "cover",
13070
+ quality: 80,
13071
+ format: "auto",
13072
+ metadata: "none"
13073
+ }
13074
+ },
13075
+ /**
13076
+ * Icon/Logo preset (Notion-style)
13077
+ * Small, square profile/icon images
13078
+ */
13079
+ icon: {
13080
+ default: {
13081
+ width: 240,
13082
+ // 2x for retina (120px display size)
13083
+ height: 240,
13084
+ fit: "cover",
13085
+ gravity: "auto",
13086
+ // Focus on faces for profile pictures
13087
+ quality: 85,
13088
+ format: "auto",
13089
+ metadata: "none"
13090
+ },
13091
+ thumbnail: {
13092
+ width: 120,
13093
+ height: 120,
13094
+ fit: "cover",
13095
+ gravity: "auto",
13096
+ quality: 85,
13097
+ format: "auto",
13098
+ metadata: "none"
13099
+ }
13100
+ }
13101
+ };
13102
+ function buildOptionsString(options) {
13103
+ const parts = [];
13104
+ if (options.width !== void 0) {
13105
+ parts.push(`width=${options.width}`);
13106
+ }
13107
+ if (options.height !== void 0) {
13108
+ parts.push(`height=${options.height}`);
13109
+ }
13110
+ if (options.fit) {
13111
+ parts.push(`fit=${options.fit}`);
13112
+ }
13113
+ if (options.gravity) {
13114
+ parts.push(`gravity=${options.gravity}`);
13115
+ }
13116
+ if (options.quality !== void 0) {
13117
+ parts.push(`quality=${options.quality}`);
13118
+ }
13119
+ if (options.format) {
13120
+ parts.push(`format=${options.format}`);
13121
+ }
13122
+ if (options.dpr !== void 0) {
13123
+ parts.push(`dpr=${options.dpr}`);
13124
+ }
13125
+ if (options.sharpen !== void 0) {
13126
+ parts.push(`sharpen=${options.sharpen}`);
13127
+ }
13128
+ if (options.blur !== void 0) {
13129
+ parts.push(`blur=${options.blur}`);
13130
+ }
13131
+ if (options.brightness !== void 0) {
13132
+ parts.push(`brightness=${options.brightness}`);
13133
+ }
13134
+ if (options.metadata) {
13135
+ parts.push(`metadata=${options.metadata}`);
13136
+ }
13137
+ if (options.anim !== void 0) {
13138
+ parts.push(`anim=${options.anim}`);
13139
+ }
13140
+ return parts.join(",");
13141
+ }
13142
+ function isAllowedOrigin(url) {
13143
+ const allowedOrigins = ["ipfs.gateway.ixo.world", "mx.ixo.earth", "testmx.ixo.earth", "devmx.ixo.earth"];
13144
+ try {
13145
+ const urlObj = new URL(url);
13146
+ return allowedOrigins.some((origin) => urlObj.hostname.includes(origin));
13147
+ } catch {
13148
+ return false;
13149
+ }
13150
+ }
13151
+ function transformImage(sourceUrl, options) {
13152
+ if (!sourceUrl) {
13153
+ return sourceUrl;
13154
+ }
13155
+ if (sourceUrl.includes("/cdn-cgi/image/")) {
13156
+ return sourceUrl;
13157
+ }
13158
+ if (!isAllowedOrigin(sourceUrl)) {
13159
+ return sourceUrl;
13160
+ }
13161
+ const optionsString = buildOptionsString(options);
13162
+ return `${CLOUDFLARE_CDN_BASE}/${optionsString}/${sourceUrl}`;
13163
+ }
13164
+ function transformCoverImage(sourceUrl, deviceType = "desktop", customOptions) {
13165
+ const preset = ImagePresets.cover[deviceType];
13166
+ const options = { ...preset, ...customOptions };
13167
+ return transformImage(sourceUrl, options);
13168
+ }
13169
+ function transformIconImage(sourceUrl, size = "default", customOptions) {
13170
+ const preset = ImagePresets.icon[size];
13171
+ const options = { ...preset, ...customOptions };
13172
+ return transformImage(sourceUrl, options);
13173
+ }
13174
+
13175
+ // src/mantine/components/CoverImage.tsx
13044
13176
  function CoverImage({ coverImageUrl, logoUrl }) {
13045
13177
  const { editor, handlers, editable } = useBlocknoteContext();
13046
13178
  const [isHovering, setIsHovering] = useState48(false);
@@ -13060,8 +13192,10 @@ function CoverImage({ coverImageUrl, logoUrl }) {
13060
13192
  });
13061
13193
  return unsubscribe;
13062
13194
  }, [editor]);
13063
- const coverUrl = metadata?.cover || coverImageUrl;
13064
- const logoSrc = metadata?.icon || logoUrl;
13195
+ const rawCoverUrl = metadata?.cover || coverImageUrl;
13196
+ const rawLogoUrl = metadata?.icon || logoUrl;
13197
+ const coverUrl = rawCoverUrl ? transformCoverImage(rawCoverUrl, "desktop") : void 0;
13198
+ const logoSrc = rawLogoUrl ? transformIconImage(rawLogoUrl, "default") : void 0;
13065
13199
  const hasCover = !!coverUrl;
13066
13200
  const hasLogo = !!logoSrc;
13067
13201
  const handleFileSelect = async (event, type) => {
@@ -13745,4 +13879,4 @@ export {
13745
13879
  ixoGraphQLClient,
13746
13880
  getEntity
13747
13881
  };
13748
- //# sourceMappingURL=chunk-SKLD5WWM.mjs.map
13882
+ //# sourceMappingURL=chunk-DYUWLMSF.mjs.map