@ixo/editor 5.28.1 → 5.29.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.
@@ -26589,6 +26589,94 @@ import React262, { useCallback as useCallback93, useEffect as useEffect92, useMe
26589
26589
  import { ActionIcon as ActionIcon41, Alert as Alert48, Box as Box54, Group as Group98, Loader as Loader45, Stack as Stack178, Text as Text156 } from "@mantine/core";
26590
26590
  import { IconArrowLeft as IconArrowLeft9, IconCheck as IconCheck21, IconPlayerPlay as IconPlayerPlay4 } from "@tabler/icons-react";
26591
26591
  import { SurveyModel as SurveyModel10 } from "@ixo/surveys";
26592
+
26593
+ // src/mantine/blocks/action/actionTypes/evaluateClaim/resolveClaimFileRef.ts
26594
+ var IPFS_GATEWAY = "https://ipfs.gateway.ixo.world/ipfs/";
26595
+ var CID_REGEX = /(baf[a-z0-9]{20,})/i;
26596
+ function extractCid(source) {
26597
+ const m = source.match(CID_REGEX);
26598
+ return m ? m[1] : null;
26599
+ }
26600
+ function resolveClaimFileRef(raw) {
26601
+ if (raw == null) return null;
26602
+ if (typeof raw === "string") {
26603
+ const trimmed = raw.trim();
26604
+ if (!trimmed) return null;
26605
+ if (/^https?:/i.test(trimmed)) return trimmed;
26606
+ if (trimmed.startsWith("data:")) return trimmed;
26607
+ if (/^ipfs:/i.test(trimmed)) {
26608
+ const cid = extractCid(trimmed.replace(/^ipfs:\/*/i, ""));
26609
+ return cid ? `${IPFS_GATEWAY}${cid}` : null;
26610
+ }
26611
+ if (trimmed.startsWith("{")) {
26612
+ try {
26613
+ return resolveClaimFileRef(JSON.parse(trimmed));
26614
+ } catch {
26615
+ return null;
26616
+ }
26617
+ }
26618
+ if (/^did:/i.test(trimmed)) {
26619
+ const cid = extractCid(trimmed);
26620
+ return cid ? `${IPFS_GATEWAY}${cid}` : null;
26621
+ }
26622
+ if (/^baf[a-z0-9]/i.test(trimmed) && trimmed.length < 200 && !trimmed.includes(" ")) {
26623
+ const cid = extractCid(trimmed);
26624
+ return cid ? `${IPFS_GATEWAY}${cid}` : null;
26625
+ }
26626
+ return null;
26627
+ }
26628
+ if (typeof raw === "object") {
26629
+ const obj = raw;
26630
+ if (typeof obj.serviceEndpoint === "string" && /^https?:/i.test(obj.serviceEndpoint)) {
26631
+ return obj.serviceEndpoint;
26632
+ }
26633
+ if (typeof obj.proof === "string") {
26634
+ const cid = extractCid(obj.proof);
26635
+ if (cid) return `${IPFS_GATEWAY}${cid}`;
26636
+ }
26637
+ if (typeof obj.id === "string") {
26638
+ const hashIdx = obj.id.indexOf("#");
26639
+ const tail = hashIdx >= 0 ? obj.id.slice(hashIdx + 1) : obj.id;
26640
+ const cid = extractCid(tail);
26641
+ if (cid) return `${IPFS_GATEWAY}${cid}`;
26642
+ }
26643
+ if (typeof obj.content === "string") {
26644
+ return resolveClaimFileRef(obj.content);
26645
+ }
26646
+ if (typeof obj.url === "string" && /^https?:/i.test(obj.url)) {
26647
+ return obj.url;
26648
+ }
26649
+ }
26650
+ return null;
26651
+ }
26652
+ function isFileLike(value) {
26653
+ if (Array.isArray(value)) {
26654
+ return value.length > 0 && value.every((v) => v && typeof v === "object" && typeof v.content === "string");
26655
+ }
26656
+ return !!value && typeof value === "object" && typeof value.content === "string";
26657
+ }
26658
+ function resolveOneFileEntry(entry) {
26659
+ const resolved = resolveClaimFileRef(entry.content);
26660
+ if (resolved && resolved !== entry.content) {
26661
+ return { ...entry, content: resolved };
26662
+ }
26663
+ return entry;
26664
+ }
26665
+ function resolveFilesInCredentialSubject(subject) {
26666
+ if (!subject || typeof subject !== "object") return subject;
26667
+ const out = Array.isArray(subject) ? [...subject] : { ...subject };
26668
+ for (const [key, value] of Object.entries(subject)) {
26669
+ if (!isFileLike(value)) continue;
26670
+ if (Array.isArray(value)) {
26671
+ out[key] = value.map((v) => resolveOneFileEntry(v));
26672
+ } else {
26673
+ out[key] = resolveOneFileEntry(value);
26674
+ }
26675
+ }
26676
+ return out;
26677
+ }
26678
+
26679
+ // src/mantine/blocks/action/actionTypes/claim/ClaimFlowDetail.tsx
26592
26680
  function getTimeAgo2(dateString) {
26593
26681
  if (!dateString) return "";
26594
26682
  try {
@@ -26686,11 +26774,38 @@ var ClaimFlowDetail = ({
26686
26774
  const reviewMsg = model.getQuestionByName("reviewMessage");
26687
26775
  if (reviewMsg) reviewMsg.visible = false;
26688
26776
  }
26777
+ if (handlersRef.current.uploadClaimFile) {
26778
+ for (const q of model.getAllQuestions()) {
26779
+ if (q.getType?.() === "file") {
26780
+ q.storeDataAsText = false;
26781
+ }
26782
+ }
26783
+ model.onUploadFiles.add((_sender, options) => {
26784
+ const uploader = handlersRef.current.uploadClaimFile;
26785
+ if (!uploader) {
26786
+ options.callback([], ["File upload is not supported"]);
26787
+ return;
26788
+ }
26789
+ Promise.all(options.files.map((file) => uploader(file, collectionId, { entityDid: deedDid }))).then((results) => {
26790
+ options.callback(options.files.map((file, i) => ({ file, content: results[i].content })));
26791
+ }).catch((err) => {
26792
+ console.error("[Claim] file upload failed", err);
26793
+ options.callback([], [err instanceof Error ? err.message : "File upload failed"]);
26794
+ });
26795
+ });
26796
+ }
26689
26797
  if (prefillData) {
26690
26798
  model.data = prefillData?.credentialSubject ?? prefillData;
26691
26799
  }
26692
26800
  return model;
26693
- }, [surveyJson, provideSigningHandler, prefillData]);
26801
+ }, [surveyJson, provideSigningHandler, prefillData, collectionId, deedDid]);
26802
+ const mediaBlobCacheRef = useRef29(/* @__PURE__ */ new Map());
26803
+ useEffect92(() => {
26804
+ return () => {
26805
+ for (const blobUrl of mediaBlobCacheRef.current.values()) URL.revokeObjectURL(blobUrl);
26806
+ mediaBlobCacheRef.current.clear();
26807
+ };
26808
+ }, []);
26694
26809
  const detailSurveyModel = useMemo102(() => {
26695
26810
  if (!surveyJson || !selectedClaimData) return null;
26696
26811
  const model = new SurveyModel10(surveyJson);
@@ -26698,9 +26813,39 @@ var ClaimFlowDetail = ({
26698
26813
  model.showQuestionNumbers = "off";
26699
26814
  model.questionsOnPageMode = "singlePage";
26700
26815
  model.mode = "display";
26701
- model.data = selectedClaimData?.credentialSubject ?? selectedClaimData;
26816
+ const fetcher = handlersRef.current.fetchClaimMedia;
26817
+ if (fetcher) {
26818
+ const cache = mediaBlobCacheRef.current;
26819
+ for (const q of model.getAllQuestions()) {
26820
+ if (q.getType?.() === "file") {
26821
+ q.storeDataAsText = false;
26822
+ }
26823
+ }
26824
+ model.onDownloadFile.add((_sender, options) => {
26825
+ const src = options?.content;
26826
+ if (typeof src !== "string" || !/^https?:/i.test(src)) {
26827
+ options.callback("success", src);
26828
+ return;
26829
+ }
26830
+ const cached = cache.get(src);
26831
+ if (cached) {
26832
+ options.callback("success", cached);
26833
+ return;
26834
+ }
26835
+ fetcher(src, { entityDid: deedDid }).then((blob) => {
26836
+ const blobUrl = URL.createObjectURL(blob);
26837
+ cache.set(src, blobUrl);
26838
+ options.callback("success", blobUrl);
26839
+ }).catch((err) => {
26840
+ console.error("[Claim] fetchClaimMedia failed", src, err);
26841
+ options.callback("error");
26842
+ });
26843
+ });
26844
+ }
26845
+ const cs = selectedClaimData?.credentialSubject ?? selectedClaimData;
26846
+ model.data = cs && typeof cs === "object" ? resolveFilesInCredentialSubject(cs) : cs;
26702
26847
  return model;
26703
- }, [surveyJson, selectedClaimData]);
26848
+ }, [surveyJson, selectedClaimData, deedDid]);
26704
26849
  useRegisterOpenSurvey({
26705
26850
  id: `claim-action:${block.id}:new`,
26706
26851
  title: `Submit Claim${block?.props?.title ? ` \u2014 ${block.props.title}` : ""}`,
@@ -29079,92 +29224,6 @@ var MediaPreviewModal = ({ file, onClose }) => {
29079
29224
  );
29080
29225
  };
29081
29226
 
29082
- // src/mantine/blocks/action/actionTypes/evaluateClaim/resolveClaimFileRef.ts
29083
- var IPFS_GATEWAY = "https://ipfs.gateway.ixo.world/ipfs/";
29084
- var CID_REGEX = /(baf[a-z0-9]{20,})/i;
29085
- function extractCid(source) {
29086
- const m = source.match(CID_REGEX);
29087
- return m ? m[1] : null;
29088
- }
29089
- function resolveClaimFileRef(raw) {
29090
- if (raw == null) return null;
29091
- if (typeof raw === "string") {
29092
- const trimmed = raw.trim();
29093
- if (!trimmed) return null;
29094
- if (/^https?:/i.test(trimmed)) return trimmed;
29095
- if (trimmed.startsWith("data:")) return trimmed;
29096
- if (/^ipfs:/i.test(trimmed)) {
29097
- const cid = extractCid(trimmed.replace(/^ipfs:\/*/i, ""));
29098
- return cid ? `${IPFS_GATEWAY}${cid}` : null;
29099
- }
29100
- if (trimmed.startsWith("{")) {
29101
- try {
29102
- return resolveClaimFileRef(JSON.parse(trimmed));
29103
- } catch {
29104
- return null;
29105
- }
29106
- }
29107
- if (/^did:/i.test(trimmed)) {
29108
- const cid = extractCid(trimmed);
29109
- return cid ? `${IPFS_GATEWAY}${cid}` : null;
29110
- }
29111
- if (/^baf[a-z0-9]/i.test(trimmed) && trimmed.length < 200 && !trimmed.includes(" ")) {
29112
- const cid = extractCid(trimmed);
29113
- return cid ? `${IPFS_GATEWAY}${cid}` : null;
29114
- }
29115
- return null;
29116
- }
29117
- if (typeof raw === "object") {
29118
- const obj = raw;
29119
- if (typeof obj.serviceEndpoint === "string" && /^https?:/i.test(obj.serviceEndpoint)) {
29120
- return obj.serviceEndpoint;
29121
- }
29122
- if (typeof obj.proof === "string") {
29123
- const cid = extractCid(obj.proof);
29124
- if (cid) return `${IPFS_GATEWAY}${cid}`;
29125
- }
29126
- if (typeof obj.id === "string") {
29127
- const hashIdx = obj.id.indexOf("#");
29128
- const tail = hashIdx >= 0 ? obj.id.slice(hashIdx + 1) : obj.id;
29129
- const cid = extractCid(tail);
29130
- if (cid) return `${IPFS_GATEWAY}${cid}`;
29131
- }
29132
- if (typeof obj.content === "string") {
29133
- return resolveClaimFileRef(obj.content);
29134
- }
29135
- if (typeof obj.url === "string" && /^https?:/i.test(obj.url)) {
29136
- return obj.url;
29137
- }
29138
- }
29139
- return null;
29140
- }
29141
- function isFileLike(value) {
29142
- if (Array.isArray(value)) {
29143
- return value.length > 0 && value.every((v) => v && typeof v === "object" && typeof v.content === "string");
29144
- }
29145
- return !!value && typeof value === "object" && typeof value.content === "string";
29146
- }
29147
- function resolveOneFileEntry(entry) {
29148
- const resolved = resolveClaimFileRef(entry.content);
29149
- if (resolved && resolved !== entry.content) {
29150
- return { ...entry, content: resolved };
29151
- }
29152
- return entry;
29153
- }
29154
- function resolveFilesInCredentialSubject(subject) {
29155
- if (!subject || typeof subject !== "object") return subject;
29156
- const out = Array.isArray(subject) ? [...subject] : { ...subject };
29157
- for (const [key, value] of Object.entries(subject)) {
29158
- if (!isFileLike(value)) continue;
29159
- if (Array.isArray(value)) {
29160
- out[key] = value.map((v) => resolveOneFileEntry(v));
29161
- } else {
29162
- out[key] = resolveOneFileEntry(value);
29163
- }
29164
- }
29165
- return out;
29166
- }
29167
-
29168
29227
  // src/mantine/blocks/action/actionTypes/evaluateClaim/ClaimAttachments.tsx
29169
29228
  function toMediaFile(raw) {
29170
29229
  if (!raw) return null;
@@ -29577,6 +29636,26 @@ var EvaluateClaimFlowDetail = ({
29577
29636
  model.applyTheme(surveyTheme);
29578
29637
  model.showQuestionNumbers = "off";
29579
29638
  model.questionsOnPageMode = "singlePage";
29639
+ if (handlersRef.current.uploadClaimFile) {
29640
+ for (const q of model.getAllQuestions()) {
29641
+ if (q.getType?.() === "file") {
29642
+ q.storeDataAsText = false;
29643
+ }
29644
+ }
29645
+ model.onUploadFiles.add((_sender, options) => {
29646
+ const uploader = handlersRef.current.uploadClaimFile;
29647
+ if (!uploader) {
29648
+ options.callback([], ["File upload is not supported"]);
29649
+ return;
29650
+ }
29651
+ Promise.all(options.files.map((file) => uploader(file, collectionId, { entityDid: deedDid }))).then((results) => {
29652
+ options.callback(options.files.map((file, i) => ({ file, content: results[i].content })));
29653
+ }).catch((err) => {
29654
+ console.error("[EvaluateClaim] outcome file upload failed", err);
29655
+ options.callback([], [err instanceof Error ? err.message : "File upload failed"]);
29656
+ });
29657
+ });
29658
+ }
29580
29659
  model.onValueChanged.add((sender, options) => {
29581
29660
  console.log("[outcome-patch] SurveyJS onValueChanged", {
29582
29661
  question: options?.name,
@@ -29596,7 +29675,7 @@ var EvaluateClaimFlowDetail = ({
29596
29675
  setOutcomeComplete(true);
29597
29676
  });
29598
29677
  return model;
29599
- }, [outcomeTemplateJson]);
29678
+ }, [outcomeTemplateJson, collectionId, deedDid]);
29600
29679
  useEffect99(() => {
29601
29680
  if (!outcomeSurveyModel) return;
29602
29681
  const evaluated = selectedClaim ? isClaimEvaluated(selectedClaim) : false;
@@ -46706,4 +46785,4 @@ export {
46706
46785
  getExtraSlashMenuItems,
46707
46786
  useCreateIxoEditor
46708
46787
  };
46709
- //# sourceMappingURL=chunk-I2OZHN6S.mjs.map
46788
+ //# sourceMappingURL=chunk-LWKZRDZO.mjs.map