@medialane/ui 0.152.0 → 0.153.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/ipfs.ts"],"sourcesContent":["export const DEFAULT_GATEWAY = \"https://gateway.pinata.cloud/ipfs/\";\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"ipfs:\"]);\n\nconst KNOWN_IPFS_GATEWAY_HOSTS = /(^|\\.)(mypinata\\.cloud|pinata\\.cloud|ipfs\\.io|dweb\\.link|cloudflare-ipfs\\.com|nftstorage\\.link|w3s\\.link)$/i;\n\nconst DEFAULT_WIDTH = 1200;\n\nfunction withSize(url: string, gateway: string, width: number | null): string {\n if (!width || !url.startsWith(gateway)) return url;\n const sep = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${sep}img-width=${width}&img-format=webp&img-quality=80`;\n}\n\nexport function ipfsToHttp(\n uri: string | null | undefined,\n opts: { gateway?: string; width?: number | null } = {}\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const width = opts.width === undefined ? DEFAULT_WIDTH : opts.width;\n\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) {\n return withSize(uri.replace(\"ipfs://\", gateway), gateway, width);\n }\n if (uri.startsWith(\"data:image/\")) {\n return uri;\n }\n try {\n const parsed = new URL(uri);\n if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) return \"\";\n\n if (KNOWN_IPFS_GATEWAY_HOSTS.test(parsed.hostname)) {\n const match = parsed.pathname.match(/\\/ipfs\\/(.+)$/);\n if (match) return withSize(`${gateway}${match[1]}`, gateway, width);\n }\n } catch {\n return \"\";\n }\n return uri;\n}\n\nexport interface DisplayUrlOptions {\n gateway?: string;\n proxyPath?: string;\n placeholder?: string;\n}\n\nexport function toDisplayUrl(\n uri: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const placeholder = opts.placeholder ?? \"/placeholder.svg\";\n const proxyPath = opts.proxyPath ?? \"/api/img\";\n\n if (!uri) return placeholder;\n if (uri.startsWith(\"data:image/\")) return uri;\n\n const resolved = ipfsToHttp(uri, { gateway });\n if (resolved.startsWith(gateway)) return resolved;\n\n if (uri.startsWith(\"https://\") || uri.startsWith(\"http://\")) {\n return `${proxyPath}?url=${encodeURIComponent(uri)}`;\n }\n\n return placeholder;\n}\n\nexport function toDisplayUrlOrNull(\n raw: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string | null {\n if (!raw) return null;\n if (raw.startsWith(\"/\")) return raw;\n return toDisplayUrl(raw, opts);\n}\n\n/**\n * Absolute URL for a crawler: og:image and twitter:image are fetched by\n * Facebook, X and Slack with our app nowhere in the path, so the result must\n * resolve on its own. Pointing these at an app route is how every social\n * preview once 404'd. Empty string means \"no image\", which is what the\n * metadata APIs expect in place of a broken URL.\n */\nexport function toAbsoluteImageUrl(uri: string | null | undefined): string {\n if (!uri) return \"\";\n return ipfsToHttp(uri) || \"\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,kBAAkB;AAE/B,MAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,OAAO,CAAC;AAE9D,MAAM,2BAA2B;AAEjC,MAAM,gBAAgB;AAEtB,SAAS,SAAS,KAAa,SAAiB,OAA8B;AAC5E,MAAI,CAAC,SAAS,CAAC,IAAI,WAAW,OAAO,EAAG,QAAO;AAC/C,QAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM;AACtC,SAAO,GAAG,GAAG,GAAG,GAAG,aAAa,KAAK;AACvC;AAEO,SAAS,WACd,KACA,OAAoD,CAAC,GAC7C;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,QAAQ,KAAK,UAAU,SAAY,gBAAgB,KAAK;AAE9D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,WAAO,SAAS,IAAI,QAAQ,WAAW,OAAO,GAAG,SAAS,KAAK;AAAA,EACjE;AACA,MAAI,IAAI,WAAW,aAAa,GAAG;AACjC,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,CAAC,kBAAkB,IAAI,OAAO,QAAQ,EAAG,QAAO;AAEpD,QAAI,yBAAyB,KAAK,OAAO,QAAQ,GAAG;AAClD,YAAM,QAAQ,OAAO,SAAS,MAAM,eAAe;AACnD,UAAI,MAAO,QAAO,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,IAAI,SAAS,KAAK;AAAA,IACpE;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQO,SAAS,aACd,KACA,OAA0B,CAAC,GACnB;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,YAAY,KAAK,aAAa;AAEpC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,aAAa,EAAG,QAAO;AAE1C,QAAM,WAAW,WAAW,KAAK,EAAE,QAAQ,CAAC;AAC5C,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO;AAEzC,MAAI,IAAI,WAAW,UAAU,KAAK,IAAI,WAAW,SAAS,GAAG;AAC3D,WAAO,GAAG,SAAS,QAAQ,mBAAmB,GAAG,CAAC;AAAA,EACpD;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,OAA0B,CAAC,GACZ;AACf,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,GAAG,EAAG,QAAO;AAChC,SAAO,aAAa,KAAK,IAAI;AAC/B;AASO,SAAS,mBAAmB,KAAwC;AACzE,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,WAAW,GAAG,KAAK;AAC5B;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/ipfs.ts"],"sourcesContent":["export const DEFAULT_GATEWAY = \"https://gateway.pinata.cloud/ipfs/\";\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"ipfs:\"]);\n\nconst KNOWN_IPFS_GATEWAY_HOSTS = /(^|\\.)(mypinata\\.cloud|pinata\\.cloud|ipfs\\.io|dweb\\.link|cloudflare-ipfs\\.com|nftstorage\\.link|w3s\\.link)$/i;\n\nconst DEFAULT_WIDTH = 1200;\n\nfunction withSize(url: string, gateway: string, width: number | null): string {\n if (!width || !url.startsWith(gateway)) return url;\n const sep = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${sep}img-width=${width}&img-format=webp&img-quality=80`;\n}\n\nexport function ipfsToHttp(\n uri: string | null | undefined,\n opts: { gateway?: string; width?: number | null } = {}\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const width = opts.width === undefined ? DEFAULT_WIDTH : opts.width;\n\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) {\n return withSize(uri.replace(\"ipfs://\", gateway), gateway, width);\n }\n if (uri.startsWith(\"data:image/\")) {\n return uri;\n }\n try {\n const parsed = new URL(uri);\n if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) return \"\";\n\n if (KNOWN_IPFS_GATEWAY_HOSTS.test(parsed.hostname)) {\n const match = parsed.pathname.match(/\\/ipfs\\/(.+)$/);\n if (match) return withSize(`${gateway}${match[1]}`, gateway, width);\n }\n } catch {\n return \"\";\n }\n return uri;\n}\n\nexport interface DisplayUrlOptions {\n gateway?: string;\n proxyPath?: string;\n placeholder?: string;\n}\n\nexport function toDisplayUrl(\n uri: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const placeholder = opts.placeholder ?? \"/placeholder.svg\";\n const proxyPath = opts.proxyPath ?? \"/api/img\";\n\n if (!uri) return placeholder;\n if (uri.startsWith(\"data:image/\")) return uri;\n\n const resolved = ipfsToHttp(uri, { gateway });\n if (resolved.startsWith(gateway)) return resolved;\n\n if (uri.startsWith(\"https://\") || uri.startsWith(\"http://\")) {\n return `${proxyPath}?url=${encodeURIComponent(uri)}`;\n }\n\n return placeholder;\n}\n\nexport function toDisplayUrlOrNull(\n raw: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string | null {\n if (!raw) return null;\n if (raw.startsWith(\"/\")) return raw;\n return toDisplayUrl(raw, opts);\n}\n\nexport function toAbsoluteImageUrl(uri: string | null | undefined): string {\n if (!uri) return \"\";\n return ipfsToHttp(uri) || \"\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,kBAAkB;AAE/B,MAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,OAAO,CAAC;AAE9D,MAAM,2BAA2B;AAEjC,MAAM,gBAAgB;AAEtB,SAAS,SAAS,KAAa,SAAiB,OAA8B;AAC5E,MAAI,CAAC,SAAS,CAAC,IAAI,WAAW,OAAO,EAAG,QAAO;AAC/C,QAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM;AACtC,SAAO,GAAG,GAAG,GAAG,GAAG,aAAa,KAAK;AACvC;AAEO,SAAS,WACd,KACA,OAAoD,CAAC,GAC7C;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,QAAQ,KAAK,UAAU,SAAY,gBAAgB,KAAK;AAE9D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,WAAO,SAAS,IAAI,QAAQ,WAAW,OAAO,GAAG,SAAS,KAAK;AAAA,EACjE;AACA,MAAI,IAAI,WAAW,aAAa,GAAG;AACjC,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,CAAC,kBAAkB,IAAI,OAAO,QAAQ,EAAG,QAAO;AAEpD,QAAI,yBAAyB,KAAK,OAAO,QAAQ,GAAG;AAClD,YAAM,QAAQ,OAAO,SAAS,MAAM,eAAe;AACnD,UAAI,MAAO,QAAO,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,IAAI,SAAS,KAAK;AAAA,IACpE;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQO,SAAS,aACd,KACA,OAA0B,CAAC,GACnB;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,YAAY,KAAK,aAAa;AAEpC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,aAAa,EAAG,QAAO;AAE1C,QAAM,WAAW,WAAW,KAAK,EAAE,QAAQ,CAAC;AAC5C,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO;AAEzC,MAAI,IAAI,WAAW,UAAU,KAAK,IAAI,WAAW,SAAS,GAAG;AAC3D,WAAO,GAAG,SAAS,QAAQ,mBAAmB,GAAG,CAAC;AAAA,EACpD;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,OAA0B,CAAC,GACZ;AACf,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,GAAG,EAAG,QAAO;AAChC,SAAO,aAAa,KAAK,IAAI;AAC/B;AAEO,SAAS,mBAAmB,KAAwC;AACzE,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,WAAW,GAAG,KAAK;AAC5B;","names":[]}
@@ -10,13 +10,6 @@ interface DisplayUrlOptions {
10
10
  }
11
11
  declare function toDisplayUrl(uri: string | null | undefined, opts?: DisplayUrlOptions): string;
12
12
  declare function toDisplayUrlOrNull(raw: string | null | undefined, opts?: DisplayUrlOptions): string | null;
13
- /**
14
- * Absolute URL for a crawler: og:image and twitter:image are fetched by
15
- * Facebook, X and Slack with our app nowhere in the path, so the result must
16
- * resolve on its own. Pointing these at an app route is how every social
17
- * preview once 404'd. Empty string means "no image", which is what the
18
- * metadata APIs expect in place of a broken URL.
19
- */
20
13
  declare function toAbsoluteImageUrl(uri: string | null | undefined): string;
21
14
 
22
15
  export { DEFAULT_GATEWAY, type DisplayUrlOptions, ipfsToHttp, toAbsoluteImageUrl, toDisplayUrl, toDisplayUrlOrNull };
@@ -10,13 +10,6 @@ interface DisplayUrlOptions {
10
10
  }
11
11
  declare function toDisplayUrl(uri: string | null | undefined, opts?: DisplayUrlOptions): string;
12
12
  declare function toDisplayUrlOrNull(raw: string | null | undefined, opts?: DisplayUrlOptions): string | null;
13
- /**
14
- * Absolute URL for a crawler: og:image and twitter:image are fetched by
15
- * Facebook, X and Slack with our app nowhere in the path, so the result must
16
- * resolve on its own. Pointing these at an app route is how every social
17
- * preview once 404'd. Empty string means "no image", which is what the
18
- * metadata APIs expect in place of a broken URL.
19
- */
20
13
  declare function toAbsoluteImageUrl(uri: string | null | undefined): string;
21
14
 
22
15
  export { DEFAULT_GATEWAY, type DisplayUrlOptions, ipfsToHttp, toAbsoluteImageUrl, toDisplayUrl, toDisplayUrlOrNull };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/ipfs.ts"],"sourcesContent":["export const DEFAULT_GATEWAY = \"https://gateway.pinata.cloud/ipfs/\";\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"ipfs:\"]);\n\nconst KNOWN_IPFS_GATEWAY_HOSTS = /(^|\\.)(mypinata\\.cloud|pinata\\.cloud|ipfs\\.io|dweb\\.link|cloudflare-ipfs\\.com|nftstorage\\.link|w3s\\.link)$/i;\n\nconst DEFAULT_WIDTH = 1200;\n\nfunction withSize(url: string, gateway: string, width: number | null): string {\n if (!width || !url.startsWith(gateway)) return url;\n const sep = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${sep}img-width=${width}&img-format=webp&img-quality=80`;\n}\n\nexport function ipfsToHttp(\n uri: string | null | undefined,\n opts: { gateway?: string; width?: number | null } = {}\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const width = opts.width === undefined ? DEFAULT_WIDTH : opts.width;\n\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) {\n return withSize(uri.replace(\"ipfs://\", gateway), gateway, width);\n }\n if (uri.startsWith(\"data:image/\")) {\n return uri;\n }\n try {\n const parsed = new URL(uri);\n if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) return \"\";\n\n if (KNOWN_IPFS_GATEWAY_HOSTS.test(parsed.hostname)) {\n const match = parsed.pathname.match(/\\/ipfs\\/(.+)$/);\n if (match) return withSize(`${gateway}${match[1]}`, gateway, width);\n }\n } catch {\n return \"\";\n }\n return uri;\n}\n\nexport interface DisplayUrlOptions {\n gateway?: string;\n proxyPath?: string;\n placeholder?: string;\n}\n\nexport function toDisplayUrl(\n uri: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const placeholder = opts.placeholder ?? \"/placeholder.svg\";\n const proxyPath = opts.proxyPath ?? \"/api/img\";\n\n if (!uri) return placeholder;\n if (uri.startsWith(\"data:image/\")) return uri;\n\n const resolved = ipfsToHttp(uri, { gateway });\n if (resolved.startsWith(gateway)) return resolved;\n\n if (uri.startsWith(\"https://\") || uri.startsWith(\"http://\")) {\n return `${proxyPath}?url=${encodeURIComponent(uri)}`;\n }\n\n return placeholder;\n}\n\nexport function toDisplayUrlOrNull(\n raw: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string | null {\n if (!raw) return null;\n if (raw.startsWith(\"/\")) return raw;\n return toDisplayUrl(raw, opts);\n}\n\n/**\n * Absolute URL for a crawler: og:image and twitter:image are fetched by\n * Facebook, X and Slack with our app nowhere in the path, so the result must\n * resolve on its own. Pointing these at an app route is how every social\n * preview once 404'd. Empty string means \"no image\", which is what the\n * metadata APIs expect in place of a broken URL.\n */\nexport function toAbsoluteImageUrl(uri: string | null | undefined): string {\n if (!uri) return \"\";\n return ipfsToHttp(uri) || \"\";\n}\n"],"mappings":"AAAO,MAAM,kBAAkB;AAE/B,MAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,OAAO,CAAC;AAE9D,MAAM,2BAA2B;AAEjC,MAAM,gBAAgB;AAEtB,SAAS,SAAS,KAAa,SAAiB,OAA8B;AAC5E,MAAI,CAAC,SAAS,CAAC,IAAI,WAAW,OAAO,EAAG,QAAO;AAC/C,QAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM;AACtC,SAAO,GAAG,GAAG,GAAG,GAAG,aAAa,KAAK;AACvC;AAEO,SAAS,WACd,KACA,OAAoD,CAAC,GAC7C;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,QAAQ,KAAK,UAAU,SAAY,gBAAgB,KAAK;AAE9D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,WAAO,SAAS,IAAI,QAAQ,WAAW,OAAO,GAAG,SAAS,KAAK;AAAA,EACjE;AACA,MAAI,IAAI,WAAW,aAAa,GAAG;AACjC,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,CAAC,kBAAkB,IAAI,OAAO,QAAQ,EAAG,QAAO;AAEpD,QAAI,yBAAyB,KAAK,OAAO,QAAQ,GAAG;AAClD,YAAM,QAAQ,OAAO,SAAS,MAAM,eAAe;AACnD,UAAI,MAAO,QAAO,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,IAAI,SAAS,KAAK;AAAA,IACpE;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQO,SAAS,aACd,KACA,OAA0B,CAAC,GACnB;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,YAAY,KAAK,aAAa;AAEpC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,aAAa,EAAG,QAAO;AAE1C,QAAM,WAAW,WAAW,KAAK,EAAE,QAAQ,CAAC;AAC5C,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO;AAEzC,MAAI,IAAI,WAAW,UAAU,KAAK,IAAI,WAAW,SAAS,GAAG;AAC3D,WAAO,GAAG,SAAS,QAAQ,mBAAmB,GAAG,CAAC;AAAA,EACpD;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,OAA0B,CAAC,GACZ;AACf,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,GAAG,EAAG,QAAO;AAChC,SAAO,aAAa,KAAK,IAAI;AAC/B;AASO,SAAS,mBAAmB,KAAwC;AACzE,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,WAAW,GAAG,KAAK;AAC5B;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/ipfs.ts"],"sourcesContent":["export const DEFAULT_GATEWAY = \"https://gateway.pinata.cloud/ipfs/\";\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"ipfs:\"]);\n\nconst KNOWN_IPFS_GATEWAY_HOSTS = /(^|\\.)(mypinata\\.cloud|pinata\\.cloud|ipfs\\.io|dweb\\.link|cloudflare-ipfs\\.com|nftstorage\\.link|w3s\\.link)$/i;\n\nconst DEFAULT_WIDTH = 1200;\n\nfunction withSize(url: string, gateway: string, width: number | null): string {\n if (!width || !url.startsWith(gateway)) return url;\n const sep = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${sep}img-width=${width}&img-format=webp&img-quality=80`;\n}\n\nexport function ipfsToHttp(\n uri: string | null | undefined,\n opts: { gateway?: string; width?: number | null } = {}\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const width = opts.width === undefined ? DEFAULT_WIDTH : opts.width;\n\n if (!uri) return \"\";\n if (uri.startsWith(\"ipfs://\")) {\n return withSize(uri.replace(\"ipfs://\", gateway), gateway, width);\n }\n if (uri.startsWith(\"data:image/\")) {\n return uri;\n }\n try {\n const parsed = new URL(uri);\n if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) return \"\";\n\n if (KNOWN_IPFS_GATEWAY_HOSTS.test(parsed.hostname)) {\n const match = parsed.pathname.match(/\\/ipfs\\/(.+)$/);\n if (match) return withSize(`${gateway}${match[1]}`, gateway, width);\n }\n } catch {\n return \"\";\n }\n return uri;\n}\n\nexport interface DisplayUrlOptions {\n gateway?: string;\n proxyPath?: string;\n placeholder?: string;\n}\n\nexport function toDisplayUrl(\n uri: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string {\n const gateway = opts.gateway ?? DEFAULT_GATEWAY;\n const placeholder = opts.placeholder ?? \"/placeholder.svg\";\n const proxyPath = opts.proxyPath ?? \"/api/img\";\n\n if (!uri) return placeholder;\n if (uri.startsWith(\"data:image/\")) return uri;\n\n const resolved = ipfsToHttp(uri, { gateway });\n if (resolved.startsWith(gateway)) return resolved;\n\n if (uri.startsWith(\"https://\") || uri.startsWith(\"http://\")) {\n return `${proxyPath}?url=${encodeURIComponent(uri)}`;\n }\n\n return placeholder;\n}\n\nexport function toDisplayUrlOrNull(\n raw: string | null | undefined,\n opts: DisplayUrlOptions = {},\n): string | null {\n if (!raw) return null;\n if (raw.startsWith(\"/\")) return raw;\n return toDisplayUrl(raw, opts);\n}\n\nexport function toAbsoluteImageUrl(uri: string | null | undefined): string {\n if (!uri) return \"\";\n return ipfsToHttp(uri) || \"\";\n}\n"],"mappings":"AAAO,MAAM,kBAAkB;AAE/B,MAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,UAAU,OAAO,CAAC;AAE9D,MAAM,2BAA2B;AAEjC,MAAM,gBAAgB;AAEtB,SAAS,SAAS,KAAa,SAAiB,OAA8B;AAC5E,MAAI,CAAC,SAAS,CAAC,IAAI,WAAW,OAAO,EAAG,QAAO;AAC/C,QAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM;AACtC,SAAO,GAAG,GAAG,GAAG,GAAG,aAAa,KAAK;AACvC;AAEO,SAAS,WACd,KACA,OAAoD,CAAC,GAC7C;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,QAAQ,KAAK,UAAU,SAAY,gBAAgB,KAAK;AAE9D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,WAAO,SAAS,IAAI,QAAQ,WAAW,OAAO,GAAG,SAAS,KAAK;AAAA,EACjE;AACA,MAAI,IAAI,WAAW,aAAa,GAAG;AACjC,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,CAAC,kBAAkB,IAAI,OAAO,QAAQ,EAAG,QAAO;AAEpD,QAAI,yBAAyB,KAAK,OAAO,QAAQ,GAAG;AAClD,YAAM,QAAQ,OAAO,SAAS,MAAM,eAAe;AACnD,UAAI,MAAO,QAAO,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,IAAI,SAAS,KAAK;AAAA,IACpE;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAQO,SAAS,aACd,KACA,OAA0B,CAAC,GACnB;AACR,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,YAAY,KAAK,aAAa;AAEpC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,aAAa,EAAG,QAAO;AAE1C,QAAM,WAAW,WAAW,KAAK,EAAE,QAAQ,CAAC;AAC5C,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO;AAEzC,MAAI,IAAI,WAAW,UAAU,KAAK,IAAI,WAAW,SAAS,GAAG;AAC3D,WAAO,GAAG,SAAS,QAAQ,mBAAmB,GAAG,CAAC;AAAA,EACpD;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,OAA0B,CAAC,GACZ;AACf,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,WAAW,GAAG,EAAG,QAAO;AAChC,SAAO,aAAa,KAAK,IAAI;AAC/B;AAEO,SAAS,mBAAmB,KAAwC;AACzE,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,WAAW,GAAG,KAAK;AAC5B;","names":[]}
@@ -24,7 +24,7 @@ module.exports = __toCommonJS(profile_identity_exports);
24
24
  var import_address = require("./address.js");
25
25
  function profileIdentity(source) {
26
26
  const username = source.username?.trim() || null;
27
- const name = source.displayName?.trim() || null;
27
+ const name = source.name?.trim() || null;
28
28
  const address = source.walletAddress?.trim() || null;
29
29
  return {
30
30
  identity: username ? `@${username}` : address ? (0, import_address.shortenAddress)(address) : "Unknown account",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/profile-identity.ts"],"sourcesContent":["import { shortenAddress } from \"./address.js\";\n\nexport interface ProfileIdentitySource {\n username?: string | null;\n displayName?: string | null;\n walletAddress?: string | null;\n}\n\nexport interface ProfileIdentity {\n identity: string;\n name: string | null;\n hasUsername: boolean;\n}\n\n/**\n * Splits a profile into what identifies an account and what merely labels it.\n *\n * `identity` only ever comes from a claimed username or the wallet address.\n * Both are governed: a username is unique, charset-restricted, blocked against\n * a reserved list and reviewed before approval; an address is the account\n * itself. `name` is free text the account typed, so it can say anything and\n * cannot identify anyone.\n *\n * Keeping them apart is the point. A profile that set its name to a platform\n * or a rival's handle rendered as that handle everywhere the two were merged.\n */\nexport function profileIdentity(source: ProfileIdentitySource): ProfileIdentity {\n const username = source.username?.trim() || null;\n const name = source.displayName?.trim() || null;\n const address = source.walletAddress?.trim() || null;\n\n return {\n identity: username ? `@${username}` : address ? shortenAddress(address) : \"Unknown account\",\n name,\n hasUsername: Boolean(username),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA+B;AA0BxB,SAAS,gBAAgB,QAAgD;AAC9E,QAAM,WAAW,OAAO,UAAU,KAAK,KAAK;AAC5C,QAAM,OAAO,OAAO,aAAa,KAAK,KAAK;AAC3C,QAAM,UAAU,OAAO,eAAe,KAAK,KAAK;AAEhD,SAAO;AAAA,IACL,UAAU,WAAW,IAAI,QAAQ,KAAK,cAAU,+BAAe,OAAO,IAAI;AAAA,IAC1E;AAAA,IACA,aAAa,QAAQ,QAAQ;AAAA,EAC/B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/profile-identity.ts"],"sourcesContent":["import { shortenAddress } from \"./address.js\";\n\nexport interface ProfileIdentitySource {\n username?: string | null;\n name?: string | null;\n walletAddress?: string | null;\n}\n\nexport interface ProfileIdentity {\n identity: string;\n name: string | null;\n hasUsername: boolean;\n}\n\nexport function profileIdentity(source: ProfileIdentitySource): ProfileIdentity {\n const username = source.username?.trim() || null;\n const name = source.name?.trim() || null;\n const address = source.walletAddress?.trim() || null;\n\n return {\n identity: username ? `@${username}` : address ? shortenAddress(address) : \"Unknown account\",\n name,\n hasUsername: Boolean(username),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA+B;AAcxB,SAAS,gBAAgB,QAAgD;AAC9E,QAAM,WAAW,OAAO,UAAU,KAAK,KAAK;AAC5C,QAAM,OAAO,OAAO,MAAM,KAAK,KAAK;AACpC,QAAM,UAAU,OAAO,eAAe,KAAK,KAAK;AAEhD,SAAO;AAAA,IACL,UAAU,WAAW,IAAI,QAAQ,KAAK,cAAU,+BAAe,OAAO,IAAI;AAAA,IAC1E;AAAA,IACA,aAAa,QAAQ,QAAQ;AAAA,EAC/B;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  interface ProfileIdentitySource {
2
2
  username?: string | null;
3
- displayName?: string | null;
3
+ name?: string | null;
4
4
  walletAddress?: string | null;
5
5
  }
6
6
  interface ProfileIdentity {
@@ -8,18 +8,6 @@ interface ProfileIdentity {
8
8
  name: string | null;
9
9
  hasUsername: boolean;
10
10
  }
11
- /**
12
- * Splits a profile into what identifies an account and what merely labels it.
13
- *
14
- * `identity` only ever comes from a claimed username or the wallet address.
15
- * Both are governed: a username is unique, charset-restricted, blocked against
16
- * a reserved list and reviewed before approval; an address is the account
17
- * itself. `name` is free text the account typed, so it can say anything and
18
- * cannot identify anyone.
19
- *
20
- * Keeping them apart is the point. A profile that set its name to a platform
21
- * or a rival's handle rendered as that handle everywhere the two were merged.
22
- */
23
11
  declare function profileIdentity(source: ProfileIdentitySource): ProfileIdentity;
24
12
 
25
13
  export { type ProfileIdentity, type ProfileIdentitySource, profileIdentity };
@@ -1,6 +1,6 @@
1
1
  interface ProfileIdentitySource {
2
2
  username?: string | null;
3
- displayName?: string | null;
3
+ name?: string | null;
4
4
  walletAddress?: string | null;
5
5
  }
6
6
  interface ProfileIdentity {
@@ -8,18 +8,6 @@ interface ProfileIdentity {
8
8
  name: string | null;
9
9
  hasUsername: boolean;
10
10
  }
11
- /**
12
- * Splits a profile into what identifies an account and what merely labels it.
13
- *
14
- * `identity` only ever comes from a claimed username or the wallet address.
15
- * Both are governed: a username is unique, charset-restricted, blocked against
16
- * a reserved list and reviewed before approval; an address is the account
17
- * itself. `name` is free text the account typed, so it can say anything and
18
- * cannot identify anyone.
19
- *
20
- * Keeping them apart is the point. A profile that set its name to a platform
21
- * or a rival's handle rendered as that handle everywhere the two were merged.
22
- */
23
11
  declare function profileIdentity(source: ProfileIdentitySource): ProfileIdentity;
24
12
 
25
13
  export { type ProfileIdentity, type ProfileIdentitySource, profileIdentity };
@@ -1,7 +1,7 @@
1
1
  import { shortenAddress } from "./address.js";
2
2
  function profileIdentity(source) {
3
3
  const username = source.username?.trim() || null;
4
- const name = source.displayName?.trim() || null;
4
+ const name = source.name?.trim() || null;
5
5
  const address = source.walletAddress?.trim() || null;
6
6
  return {
7
7
  identity: username ? `@${username}` : address ? shortenAddress(address) : "Unknown account",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/profile-identity.ts"],"sourcesContent":["import { shortenAddress } from \"./address.js\";\n\nexport interface ProfileIdentitySource {\n username?: string | null;\n displayName?: string | null;\n walletAddress?: string | null;\n}\n\nexport interface ProfileIdentity {\n identity: string;\n name: string | null;\n hasUsername: boolean;\n}\n\n/**\n * Splits a profile into what identifies an account and what merely labels it.\n *\n * `identity` only ever comes from a claimed username or the wallet address.\n * Both are governed: a username is unique, charset-restricted, blocked against\n * a reserved list and reviewed before approval; an address is the account\n * itself. `name` is free text the account typed, so it can say anything and\n * cannot identify anyone.\n *\n * Keeping them apart is the point. A profile that set its name to a platform\n * or a rival's handle rendered as that handle everywhere the two were merged.\n */\nexport function profileIdentity(source: ProfileIdentitySource): ProfileIdentity {\n const username = source.username?.trim() || null;\n const name = source.displayName?.trim() || null;\n const address = source.walletAddress?.trim() || null;\n\n return {\n identity: username ? `@${username}` : address ? shortenAddress(address) : \"Unknown account\",\n name,\n hasUsername: Boolean(username),\n };\n}\n"],"mappings":"AAAA,SAAS,sBAAsB;AA0BxB,SAAS,gBAAgB,QAAgD;AAC9E,QAAM,WAAW,OAAO,UAAU,KAAK,KAAK;AAC5C,QAAM,OAAO,OAAO,aAAa,KAAK,KAAK;AAC3C,QAAM,UAAU,OAAO,eAAe,KAAK,KAAK;AAEhD,SAAO;AAAA,IACL,UAAU,WAAW,IAAI,QAAQ,KAAK,UAAU,eAAe,OAAO,IAAI;AAAA,IAC1E;AAAA,IACA,aAAa,QAAQ,QAAQ;AAAA,EAC/B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/profile-identity.ts"],"sourcesContent":["import { shortenAddress } from \"./address.js\";\n\nexport interface ProfileIdentitySource {\n username?: string | null;\n name?: string | null;\n walletAddress?: string | null;\n}\n\nexport interface ProfileIdentity {\n identity: string;\n name: string | null;\n hasUsername: boolean;\n}\n\nexport function profileIdentity(source: ProfileIdentitySource): ProfileIdentity {\n const username = source.username?.trim() || null;\n const name = source.name?.trim() || null;\n const address = source.walletAddress?.trim() || null;\n\n return {\n identity: username ? `@${username}` : address ? shortenAddress(address) : \"Unknown account\",\n name,\n hasUsername: Boolean(username),\n };\n}\n"],"mappings":"AAAA,SAAS,sBAAsB;AAcxB,SAAS,gBAAgB,QAAgD;AAC9E,QAAM,WAAW,OAAO,UAAU,KAAK,KAAK;AAC5C,QAAM,OAAO,OAAO,MAAM,KAAK,KAAK;AACpC,QAAM,UAAU,OAAO,eAAe,KAAK,KAAK;AAEhD,SAAO;AAAA,IACL,UAAU,WAAW,IAAI,QAAQ,KAAK,UAAU,eAAe,OAAO,IAAI;AAAA,IAC1E;AAAA,IACA,aAAa,QAAQ,QAAQ;AAAA,EAC/B;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medialane/ui",
3
- "version": "0.152.0",
3
+ "version": "0.153.0",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "sideEffects": false,