@ixo/editor 3.0.0 → 3.2.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,4 +1,5 @@
1
1
  import {
2
+ LATEST_VERSION,
2
3
  buildDomainCardLinkedResource,
3
4
  buildFlowNodeFromBlock,
4
5
  buildGovernanceGroupLinkedEntities,
@@ -19,7 +20,7 @@ import {
19
20
  resolveActionType,
20
21
  sendDirectMessage,
21
22
  transformSurveyToCredentialSubject
22
- } from "./chunk-5D26UG3I.mjs";
23
+ } from "./chunk-3EZI42YS.mjs";
23
24
 
24
25
  // src/mantine/hooks/useCreateIxoEditor.ts
25
26
  import { useCreateBlockNote } from "@blocknote/react";
@@ -1498,6 +1499,7 @@ function initializeHookedActions() {
1498
1499
  // src/mantine/context/BlocknoteContext.tsx
1499
1500
  var BlocknoteContext = createContext({
1500
1501
  docType: "flow",
1502
+ flowVersion: "0.3",
1501
1503
  sharedProposals: {},
1502
1504
  fetchSharedProposal: async () => {
1503
1505
  throw new Error("BlocknoteContext not initialized");
@@ -1534,6 +1536,7 @@ var BlocknoteProvider = ({
1534
1536
  const [activeDrawerId, setActiveDrawerId] = useState3(null);
1535
1537
  const [drawerContent, setDrawerContent] = useState3(null);
1536
1538
  const docType = editor?.docType || "flow";
1539
+ const flowVersion = editor?.getFlowMetadata?.()?.schema_version || "0.3";
1537
1540
  useEffect4(() => {
1538
1541
  initializeHookedActions();
1539
1542
  }, []);
@@ -1617,6 +1620,7 @@ var BlocknoteProvider = ({
1617
1620
  blockRequirements,
1618
1621
  editable,
1619
1622
  docType,
1623
+ flowVersion,
1620
1624
  sharedProposals,
1621
1625
  fetchSharedProposal,
1622
1626
  invalidateProposal,
@@ -6741,6 +6745,7 @@ function useBlockAuthorization({ editor, blockId, actorDid, ucanService, flowUri
6741
6745
  const metadata = editor.getFlowMetadata?.();
6742
6746
  return metadata?.doc_id ? `ixo:flow:${metadata.doc_id}` : "";
6743
6747
  }, [flowUri, editor]);
6748
+ const schemaVersion = useMemo25(() => editor.getFlowMetadata?.()?.schema_version || "0.3", [editor]);
6744
6749
  useEffect23(() => {
6745
6750
  const checkAuthorization = async () => {
6746
6751
  setLoading(true);
@@ -6760,7 +6765,7 @@ function useBlockAuthorization({ editor, blockId, actorDid, ucanService, flowUri
6760
6765
  return;
6761
6766
  }
6762
6767
  try {
6763
- const authResult = await isAuthorized(blockId, actorDid, ucanService, resolvedFlowUri);
6768
+ const authResult = await isAuthorized(blockId, actorDid, ucanService, resolvedFlowUri, schemaVersion);
6764
6769
  setResult(authResult);
6765
6770
  } catch (error) {
6766
6771
  setResult({
@@ -6772,7 +6777,7 @@ function useBlockAuthorization({ editor, blockId, actorDid, ucanService, flowUri
6772
6777
  }
6773
6778
  };
6774
6779
  checkAuthorization();
6775
- }, [blockId, actorDid, ucanService, resolvedFlowUri, checkTrigger]);
6780
+ }, [blockId, actorDid, ucanService, resolvedFlowUri, schemaVersion, checkTrigger]);
6776
6781
  const recheck = () => setCheckTrigger((prev) => prev + 1);
6777
6782
  return {
6778
6783
  isAuthorized: result.authorized,
@@ -30997,7 +31002,7 @@ var MatrixMetadataManager = class {
30997
31002
  this.eventHandler = (event) => {
30998
31003
  if (event.getRoomId() === this.roomId) {
30999
31004
  const eventType = event.getType();
31000
- if (eventType === COVER_IMAGE_EVENT_TYPE || eventType === COVER_ICON_EVENT_TYPE) {
31005
+ if (eventType === COVER_IMAGE_EVENT_TYPE || eventType === COVER_ICON_EVENT_TYPE || eventType === "m.room.name") {
31001
31006
  const metadata = this.getMetadata();
31002
31007
  if (metadata) {
31003
31008
  this.notifySubscribers(metadata);
@@ -31063,6 +31068,17 @@ var MatrixMetadataManager = class {
31063
31068
  )
31064
31069
  );
31065
31070
  }
31071
+ if ("title" in metadata) {
31072
+ promises.push(
31073
+ this.matrixClient.sendStateEvent(
31074
+ this.roomId,
31075
+ "m.room.name",
31076
+ { name: metadata.title || "" },
31077
+ ""
31078
+ // Empty state key
31079
+ )
31080
+ );
31081
+ }
31066
31082
  await Promise.all(promises);
31067
31083
  } catch (error) {
31068
31084
  console.error("Failed to set page metadata:", error);
@@ -31096,10 +31112,13 @@ var MatrixMetadataManager = class {
31096
31112
  );
31097
31113
  const iconContent = iconEvent ? iconEvent.getContent() : null;
31098
31114
  const iconUrl = iconContent?.url || null;
31099
- if (!coverUrl && !iconUrl) {
31115
+ const nameEvent = room.currentState.getStateEvents("m.room.name", "");
31116
+ const roomName = nameEvent ? nameEvent.getContent()?.name || null : null;
31117
+ if (!coverUrl && !iconUrl && !roomName) {
31100
31118
  return null;
31101
31119
  }
31102
31120
  return {
31121
+ title: roomName || void 0,
31103
31122
  cover: coverUrl || void 0,
31104
31123
  icon: iconUrl || void 0,
31105
31124
  coverPosition: coverPos ?? void 0
@@ -31546,6 +31565,7 @@ function useCreateCollaborativeIxoEditor(options) {
31546
31565
  const runtimeMap = useMemo118(() => yDoc.getMap("runtime"), [yDoc]);
31547
31566
  const delegationsMap = useMemo118(() => yDoc.getMap("delegations"), [yDoc]);
31548
31567
  const invocationsMap = useMemo118(() => yDoc.getMap("invocations"), [yDoc]);
31568
+ const migrationMap = useMemo118(() => yDoc.getMap("migration"), [yDoc]);
31549
31569
  const ucanDelegationStore = useMemo118(() => {
31550
31570
  const store = createUcanDelegationStore(delegationsMap);
31551
31571
  const originalSet = store.set;
@@ -31662,6 +31682,7 @@ function useCreateCollaborativeIxoEditor(options) {
31662
31682
  ixoEditor._yInvocations = invocationsMap;
31663
31683
  ixoEditor._ucanDelegationStore = ucanDelegationStore;
31664
31684
  ixoEditor._invocationStore = invocationStore;
31685
+ ixoEditor._yMigration = migrationMap;
31665
31686
  ixoEditor.getUcanService = () => {
31666
31687
  return null;
31667
31688
  };
@@ -31802,9 +31823,9 @@ function useCreateCollaborativeIxoEditor(options) {
31802
31823
  if (!permissions.write) {
31803
31824
  return;
31804
31825
  }
31805
- root.set("@context", "https://ixo.world/flow/0.3");
31826
+ root.set("@context", `https://ixo.world/flow/${LATEST_VERSION}`);
31806
31827
  root.set("_type", "ixo.flow.crdt");
31807
- root.set("schema_version", "0.3");
31828
+ root.set("schema_version", LATEST_VERSION);
31808
31829
  root.set("doc_id", options.docId || `flow_${Date.now()}`);
31809
31830
  root.set("createdAt", (/* @__PURE__ */ new Date()).toISOString());
31810
31831
  root.set("createdBy", memoizedUser.id || "anonymous");
@@ -31876,7 +31897,7 @@ function useCreateCollaborativeIxoEditor(options) {
31876
31897
  }
31877
31898
 
31878
31899
  // src/mantine/IxoEditor.tsx
31879
- import React299, { useState as useState138, useEffect as useEffect113, useCallback as useCallback111 } from "react";
31900
+ import React299 from "react";
31880
31901
  import { SuggestionMenuController } from "@blocknote/react";
31881
31902
  import { BlockNoteView } from "@blocknote/mantine";
31882
31903
  import { filterSuggestionItems } from "@blocknote/core";
@@ -31933,8 +31954,9 @@ function PanelContent({ theme }) {
31933
31954
  }
31934
31955
 
31935
31956
  // src/mantine/components/CoverImage.tsx
31936
- import React296, { useState as useState135, useRef as useRef29, useEffect as useEffect110, useMemo as useMemo121 } from "react";
31937
- import { Box as Box62, Group as Group108 } from "@mantine/core";
31957
+ import React296, { useState as useState136, useRef as useRef29, useEffect as useEffect110, useMemo as useMemo121 } from "react";
31958
+ import { Box as Box62, Group as Group109 } from "@mantine/core";
31959
+ import { IconMoodSmile, IconPhoto as IconPhoto4, IconSettings as IconSettings22, IconArrowsMove, IconTrash as IconTrash11, IconRefresh as IconRefresh5 } from "@tabler/icons-react";
31938
31960
 
31939
31961
  // src/core/lib/imageTransform.ts
31940
31962
  var CLOUDFLARE_CDN_BASE = "https://www.ixo.earth/cdn-cgi/image";
@@ -32067,33 +32089,53 @@ function transformIconImage(sourceUrl, size = "default", customOptions) {
32067
32089
  }
32068
32090
 
32069
32091
  // src/mantine/components/Base/CoverImageButton.tsx
32070
- import React292, { forwardRef } from "react";
32071
- import { Button as Button55 } from "@mantine/core";
32072
- var CoverImageButton = forwardRef(({ isActive = false, onClick, children, style, ...props }, ref) => /* @__PURE__ */ React292.createElement(
32073
- Button55,
32074
- {
32075
- ref,
32076
- variant: "filled",
32077
- onClick,
32078
- size: "xs",
32079
- style: {
32080
- backgroundColor: isActive ? "rgba(55, 53, 47, 0.9)" : "rgba(255, 255, 255, 0.9)",
32081
- color: isActive ? "white" : "#37352f",
32082
- fontSize: "12px",
32083
- fontWeight: 500,
32084
- padding: "4px 8px",
32085
- height: "auto",
32086
- ...style
32087
- },
32088
- ...props
32089
- },
32090
- children
32091
- ));
32092
- CoverImageButton.displayName = "CoverImageButton";
32092
+ import React292, { forwardRef, useState as useState133 } from "react";
32093
+ import { UnstyledButton as UnstyledButton6, Group as Group106, Text as Text170 } from "@mantine/core";
32094
+ var CoverImageButton = forwardRef(function CoverImageButton2({ isActive = false, onClick, icon: icon2, children, style }, ref) {
32095
+ const [hovered, setHovered] = useState133(false);
32096
+ return /* @__PURE__ */ React292.createElement(
32097
+ UnstyledButton6,
32098
+ {
32099
+ ref,
32100
+ onClick,
32101
+ onMouseEnter: () => setHovered(true),
32102
+ onMouseLeave: () => setHovered(false),
32103
+ style: {
32104
+ padding: "4px 8px",
32105
+ borderRadius: "4px",
32106
+ border: "none",
32107
+ background: isActive || hovered ? "var(--mantine-color-neutralColor-5)" : "transparent",
32108
+ transition: "background 0.15s ease",
32109
+ ...style
32110
+ }
32111
+ },
32112
+ /* @__PURE__ */ React292.createElement(Group106, { gap: 4, wrap: "nowrap" }, icon2 && /* @__PURE__ */ React292.createElement(
32113
+ "span",
32114
+ {
32115
+ style: {
32116
+ display: "flex",
32117
+ alignItems: "center",
32118
+ color: "var(--mantine-color-neutralColor-7)"
32119
+ }
32120
+ },
32121
+ icon2
32122
+ ), /* @__PURE__ */ React292.createElement(
32123
+ Text170,
32124
+ {
32125
+ fz: 12,
32126
+ style: {
32127
+ color: "var(--mantine-color-neutralColor-7) !important",
32128
+ whiteSpace: "nowrap"
32129
+ }
32130
+ },
32131
+ children
32132
+ ))
32133
+ );
32134
+ });
32093
32135
 
32094
32136
  // src/mantine/components/Base/BaseIconPicker.tsx
32095
- import React293, { useState as useState133, useMemo as useMemo119, useEffect as useEffect108 } from "react";
32096
- import { TextInput as TextInput7, Tabs as Tabs4, Box as Box59, Stack as Stack196, UnstyledButton as UnstyledButton6, Text as Text170, Center as Center14, ScrollArea as ScrollArea9, Group as Group106, Popover as Popover6 } from "@mantine/core";
32137
+ import React293, { useState as useState134, useMemo as useMemo119, useEffect as useEffect108 } from "react";
32138
+ import { TextInput as TextInput7, Tabs as Tabs4, Box as Box59, Stack as Stack196, UnstyledButton as UnstyledButton7, Text as Text171, Center as Center14, ScrollArea as ScrollArea9, Group as Group107, Popover as Popover6 } from "@mantine/core";
32097
32139
  import * as TablerIcons from "@tabler/icons-react";
32098
32140
  import { IconSearch as IconSearch7, IconX as IconX13, IconChevronLeft, IconChevronRight as IconChevronRight13 } from "@tabler/icons-react";
32099
32141
 
@@ -32124,10 +32166,10 @@ var localStorageService = {
32124
32166
  // src/mantine/components/Base/BaseIconPicker.tsx
32125
32167
  var iconsKey = "editor_recent_icons";
32126
32168
  var ICONS_PER_PAGE = 500;
32127
- function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children, currentIcon }) {
32128
- const [searchQuery, setSearchQuery] = useState133("");
32129
- const [activeTab, setActiveTab] = useState133("icons");
32130
- const [currentPage, setCurrentPage] = useState133(1);
32169
+ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, onRemove, children, currentIcon }) {
32170
+ const [searchQuery, setSearchQuery] = useState134("");
32171
+ const [activeTab, setActiveTab] = useState134("icons");
32172
+ const [currentPage, setCurrentPage] = useState134(1);
32131
32173
  const allIcons = useMemo119(() => {
32132
32174
  const iconEntries = Object.entries(TablerIcons).filter(([name]) => name.startsWith("Icon") && name !== "IconProps");
32133
32175
  return iconEntries;
@@ -32161,7 +32203,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32161
32203
  };
32162
32204
  const renderIconGrid = (icons) => {
32163
32205
  if (icons.length === 0) {
32164
- return /* @__PURE__ */ React293.createElement(Center14, { py: "xl" }, /* @__PURE__ */ React293.createElement(Text170, { c: "dimmed", size: "sm" }, "No icons found"));
32206
+ return /* @__PURE__ */ React293.createElement(Center14, { py: "xl" }, /* @__PURE__ */ React293.createElement(Text171, { c: "dimmed", size: "sm" }, "No icons found"));
32165
32207
  }
32166
32208
  return /* @__PURE__ */ React293.createElement(
32167
32209
  Box59,
@@ -32176,7 +32218,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32176
32218
  icons.map(([name, IconComponent]) => {
32177
32219
  const isSelected = currentIcon === name.replace("Icon", "").replace(/([A-Z])/g, "-$1").toLowerCase().slice(1);
32178
32220
  return /* @__PURE__ */ React293.createElement(
32179
- UnstyledButton6,
32221
+ UnstyledButton7,
32180
32222
  {
32181
32223
  key: name,
32182
32224
  onClick: () => handleIconClick(name),
@@ -32201,7 +32243,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32201
32243
  }
32202
32244
  }
32203
32245
  },
32204
- /* @__PURE__ */ React293.createElement(IconComponent, { color: "white", size: 24, stroke: 1.5 })
32246
+ /* @__PURE__ */ React293.createElement(IconComponent, { size: 24, stroke: 1.5, style: { color: "var(--mantine-color-neutralColor-8) !important" } })
32205
32247
  );
32206
32248
  })
32207
32249
  );
@@ -32210,12 +32252,32 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32210
32252
  Popover6.Dropdown,
32211
32253
  {
32212
32254
  style: {
32213
- backgroundColor: "#1a1a1a",
32214
- border: "1px solid rgba(255, 255, 255, 0.1)",
32255
+ backgroundColor: "var(--mantine-color-neutralColor-3)",
32256
+ border: "1px solid var(--mantine-color-neutralColor-5)",
32215
32257
  borderRadius: "12px"
32216
32258
  },
32217
32259
  p: 0
32218
32260
  },
32261
+ onRemove && /* @__PURE__ */ React293.createElement(
32262
+ UnstyledButton7,
32263
+ {
32264
+ onClick: () => {
32265
+ onRemove();
32266
+ onClose();
32267
+ },
32268
+ style: {
32269
+ position: "absolute",
32270
+ top: 12,
32271
+ right: 12,
32272
+ zIndex: 10,
32273
+ padding: "4px 8px",
32274
+ borderRadius: "4px",
32275
+ color: "var(--mantine-color-neutralColor-7)",
32276
+ transition: "background 0.15s ease"
32277
+ }
32278
+ },
32279
+ /* @__PURE__ */ React293.createElement(Group107, { gap: 4, wrap: "nowrap" }, /* @__PURE__ */ React293.createElement(IconX13, { size: 14 }), /* @__PURE__ */ React293.createElement(Text171, { fz: 12, style: { color: "var(--mantine-color-neutralColor-7) !important", whiteSpace: "nowrap" } }, "Remove"))
32280
+ ),
32219
32281
  /* @__PURE__ */ React293.createElement(Stack196, { gap: "md", p: "md" }, /* @__PURE__ */ React293.createElement(Tabs4, { value: activeTab, onChange: setActiveTab, variant: "pills" }, /* @__PURE__ */ React293.createElement(Tabs4.List, null, /* @__PURE__ */ React293.createElement(Tabs4.Tab, { value: "icons" }, "Icons"), /* @__PURE__ */ React293.createElement(Tabs4.Tab, { value: "upload" }, "Upload")), /* @__PURE__ */ React293.createElement(Tabs4.Panel, { value: "icons", pt: "md" }, /* @__PURE__ */ React293.createElement(
32220
32282
  TextInput7,
32221
32283
  {
@@ -32224,7 +32286,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32224
32286
  leftSection: /* @__PURE__ */ React293.createElement(IconSearch7, { size: 18 }),
32225
32287
  value: searchQuery,
32226
32288
  onChange: (e) => setSearchQuery(e.currentTarget.value),
32227
- rightSection: searchQuery && /* @__PURE__ */ React293.createElement(UnstyledButton6, { onClick: () => setSearchQuery("") }, /* @__PURE__ */ React293.createElement(IconX13, { size: 18 })),
32289
+ rightSection: searchQuery && /* @__PURE__ */ React293.createElement(UnstyledButton7, { onClick: () => setSearchQuery("") }, /* @__PURE__ */ React293.createElement(IconX13, { size: 18 })),
32228
32290
  style: { flex: 1 },
32229
32291
  styles: {
32230
32292
  input: {
@@ -32234,7 +32296,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32234
32296
  }
32235
32297
  }
32236
32298
  }
32237
- ), !searchQuery && /* @__PURE__ */ React293.createElement(Box59, { mb: "md" }, /* @__PURE__ */ React293.createElement(Text170, { size: "sm", fw: 500, mb: "xs", px: "xs" }, "Recent"), /* @__PURE__ */ React293.createElement(ScrollArea9.Autosize, { scrollbarSize: 0, mah: 60 }, renderIconGrid(recentIcons))), /* @__PURE__ */ React293.createElement(Box59, null, /* @__PURE__ */ React293.createElement(Group106, { justify: "space-between", mb: "xs", px: "xs" }, /* @__PURE__ */ React293.createElement(Text170, { size: "sm", fw: 500 }, searchQuery ? "Results" : "Icons"), totalPages > 1 && /* @__PURE__ */ React293.createElement(Group106, { gap: "xs" }, /* @__PURE__ */ React293.createElement(Text170, { size: "xs", c: "dimmed" }, "Page ", currentPage, " of ", totalPages, " (", filteredIcons.length, " total)"), /* @__PURE__ */ React293.createElement(BaseButton, { size: "xs", onClick: () => setCurrentPage((p) => Math.max(1, p - 1)), disabled: currentPage === 1, leftSection: /* @__PURE__ */ React293.createElement(IconChevronLeft, { size: 14 }) }, "Prev"), /* @__PURE__ */ React293.createElement(
32299
+ ), !searchQuery && /* @__PURE__ */ React293.createElement(Box59, { mb: "md" }, /* @__PURE__ */ React293.createElement(Text171, { size: "sm", fw: 500, mb: "xs", px: "xs" }, "Recent"), /* @__PURE__ */ React293.createElement(ScrollArea9.Autosize, { scrollbarSize: 0, mah: 60 }, renderIconGrid(recentIcons))), /* @__PURE__ */ React293.createElement(Box59, null, /* @__PURE__ */ React293.createElement(Group107, { justify: "space-between", mb: "xs", px: "xs" }, /* @__PURE__ */ React293.createElement(Text171, { size: "sm", fw: 500 }, searchQuery ? "Results" : "Icons"), totalPages > 1 && /* @__PURE__ */ React293.createElement(Group107, { gap: "xs" }, /* @__PURE__ */ React293.createElement(Text171, { size: "xs", c: "dimmed" }, "Page ", currentPage, " of ", totalPages, " (", filteredIcons.length, " total)"), /* @__PURE__ */ React293.createElement(BaseButton, { size: "xs", onClick: () => setCurrentPage((p) => Math.max(1, p - 1)), disabled: currentPage === 1, leftSection: /* @__PURE__ */ React293.createElement(IconChevronLeft, { size: 14 }) }, "Prev"), /* @__PURE__ */ React293.createElement(
32238
32300
  BaseButton,
32239
32301
  {
32240
32302
  size: "xs",
@@ -32243,7 +32305,7 @@ function BaseIconPicker({ opened, onClose, onSelectIcon, onUploadClick, children
32243
32305
  leftSection: /* @__PURE__ */ React293.createElement(IconChevronRight13, { size: 14 })
32244
32306
  },
32245
32307
  "Next"
32246
- ))), /* @__PURE__ */ React293.createElement(ScrollArea9.Autosize, { scrollbarSize: 0, mah: 200 }, renderIconGrid(paginatedIcons)))), /* @__PURE__ */ React293.createElement(Tabs4.Panel, { value: "upload", pt: "md" }, /* @__PURE__ */ React293.createElement(Center14, { py: "xl" }, /* @__PURE__ */ React293.createElement(Stack196, { align: "center", gap: "md" }, /* @__PURE__ */ React293.createElement(Text170, { size: "sm", c: "dimmed", ta: "center" }, "Upload a custom icon image", /* @__PURE__ */ React293.createElement("br", null), "(PNG, JPG, SVG)"), /* @__PURE__ */ React293.createElement(CoverImageButton, { onClick: onUploadClick }, "Choose File"))))))
32308
+ ))), /* @__PURE__ */ React293.createElement(ScrollArea9.Autosize, { scrollbarSize: 0, mah: 200 }, renderIconGrid(paginatedIcons)))), /* @__PURE__ */ React293.createElement(Tabs4.Panel, { value: "upload", pt: "md" }, /* @__PURE__ */ React293.createElement(Center14, { py: "xl" }, /* @__PURE__ */ React293.createElement(Stack196, { align: "center", gap: "md" }, /* @__PURE__ */ React293.createElement(Text171, { size: "sm", c: "dimmed", ta: "center" }, "Upload a custom icon image", /* @__PURE__ */ React293.createElement("br", null), "(PNG, JPG, SVG)"), /* @__PURE__ */ React293.createElement(CoverImageButton, { onClick: onUploadClick }, "Choose File"))))))
32247
32309
  ));
32248
32310
  }
32249
32311
 
@@ -32276,7 +32338,7 @@ function PageIcon({ src, iconSize = 64, useCenter = false, style }) {
32276
32338
  ...style
32277
32339
  }
32278
32340
  },
32279
- /* @__PURE__ */ React294.createElement(IconComponent, { size: iconSize, color: "white", stroke: 1.5 })
32341
+ /* @__PURE__ */ React294.createElement(IconComponent, { size: iconSize, stroke: 1.5, style: { color: "var(--mantine-color-neutralColor-8) !important" } })
32280
32342
  );
32281
32343
  }
32282
32344
  return /* @__PURE__ */ React294.createElement(
@@ -32300,13 +32362,13 @@ function PageIcon({ src, iconSize = 64, useCenter = false, style }) {
32300
32362
  import { useDisclosure as useDisclosure7 } from "@mantine/hooks";
32301
32363
 
32302
32364
  // src/mantine/components/FlowSettingsPanel.tsx
32303
- import React295, { useState as useState134, useEffect as useEffect109, useCallback as useCallback109 } from "react";
32304
- import { Stack as Stack197, Group as Group107, Button as Button56, ActionIcon as ActionIcon37, Text as Text171, Box as Box61 } from "@mantine/core";
32365
+ import React295, { useState as useState135, useEffect as useEffect109, useCallback as useCallback109 } from "react";
32366
+ import { Stack as Stack197, Group as Group108, Button as Button55, ActionIcon as ActionIcon37, Text as Text172, Box as Box61 } from "@mantine/core";
32305
32367
  import { IconPlus as IconPlus10, IconTrash as IconTrash10 } from "@tabler/icons-react";
32306
32368
  var SYSTEM_KEYS = /* @__PURE__ */ new Set(["@context", "_type", "schema_version", "doc_id", "title", "createdAt", "createdBy", "flowOwnerDid"]);
32307
32369
  var FlowSettingsPanel = ({ editor }) => {
32308
32370
  const { closePanel } = usePanelStore();
32309
- const [rows, setRows] = useState134([]);
32371
+ const [rows, setRows] = useState135([]);
32310
32372
  const loadSettings = useCallback109(() => {
32311
32373
  const metadata = editor.getFlowMetadata?.();
32312
32374
  if (!metadata) return;
@@ -32367,20 +32429,20 @@ var FlowSettingsPanel = ({ editor }) => {
32367
32429
  },
32368
32430
  [editor]
32369
32431
  );
32370
- const subtitle = /* @__PURE__ */ React295.createElement(Box61, { px: 40, mb: "md" }, /* @__PURE__ */ React295.createElement(Text171, { size: "sm", c: "dimmed" }, "Add key-value settings for this flow. These are available to oracles and action blocks at runtime."));
32371
- return /* @__PURE__ */ React295.createElement(BaseRightPanelLayout, { title: "Flow Settings", onClose: closePanel, isTemplate: true, captionContent: subtitle }, /* @__PURE__ */ React295.createElement(Stack197, { gap: "lg" }, rows.map((row, index) => /* @__PURE__ */ React295.createElement(Stack197, { key: index, gap: "xs" }, /* @__PURE__ */ React295.createElement(Group107, { gap: "xs", align: "center", wrap: "nowrap" }, /* @__PURE__ */ React295.createElement(BaseTextInput, { placeholder: "Key (e.g. protocolDid)", value: row.key, onChange: (e) => handleKeyChange(index, e.currentTarget.value), style: { flex: 1 } }), /* @__PURE__ */ React295.createElement(ActionIcon37, { variant: "subtle", color: "red", onClick: () => handleDelete(index), size: "lg" }, /* @__PURE__ */ React295.createElement(IconTrash10, { size: 16 }))), /* @__PURE__ */ React295.createElement(BaseTextArea, { placeholder: "Value", value: row.value, onChange: (e) => handleValueChange(index, e.currentTarget.value), minRows: 1, maxRows: 8 }))), /* @__PURE__ */ React295.createElement(Button56, { variant: "subtle", leftSection: /* @__PURE__ */ React295.createElement(IconPlus10, { size: 16 }), onClick: handleAdd, size: "sm" }, "Add setting")));
32432
+ const subtitle = /* @__PURE__ */ React295.createElement(Box61, { px: 40, mb: "md" }, /* @__PURE__ */ React295.createElement(Text172, { size: "sm", c: "dimmed" }, "Add key-value settings for this flow. These are available to oracles and action blocks at runtime."));
32433
+ return /* @__PURE__ */ React295.createElement(BaseRightPanelLayout, { title: "Flow Details", onClose: closePanel, isTemplate: true, captionContent: subtitle }, /* @__PURE__ */ React295.createElement(Stack197, { gap: "lg" }, rows.map((row, index) => /* @__PURE__ */ React295.createElement(Stack197, { key: index, gap: "xs" }, /* @__PURE__ */ React295.createElement(Group108, { gap: "xs", align: "center", wrap: "nowrap" }, /* @__PURE__ */ React295.createElement(BaseTextInput, { placeholder: "Key (e.g. protocolDid)", value: row.key, onChange: (e) => handleKeyChange(index, e.currentTarget.value), style: { flex: 1 } }), /* @__PURE__ */ React295.createElement(ActionIcon37, { variant: "subtle", color: "red", onClick: () => handleDelete(index), size: "lg" }, /* @__PURE__ */ React295.createElement(IconTrash10, { size: 16 }))), /* @__PURE__ */ React295.createElement(BaseTextArea, { placeholder: "Value", value: row.value, onChange: (e) => handleValueChange(index, e.currentTarget.value), minRows: 1, maxRows: 8 }))), /* @__PURE__ */ React295.createElement(Button55, { variant: "subtle", leftSection: /* @__PURE__ */ React295.createElement(IconPlus10, { size: 16 }), onClick: handleAdd, size: "sm" }, "Add detail")));
32372
32434
  };
32373
32435
 
32374
32436
  // src/mantine/components/CoverImage.tsx
32375
32437
  function CoverImage({ coverImageUrl, logoUrl }) {
32376
32438
  const { editor, handlers, editable } = useBlocknoteContext();
32377
- const [isHovering, setIsHovering] = useState135(false);
32378
- const [isRepositioning, setIsRepositioning] = useState135(false);
32379
- const [coverPosition, setCoverPosition] = useState135(() => editor?.getPageMetadata?.()?.coverPosition ?? 50);
32439
+ const [isHovering, setIsHovering] = useState136(false);
32440
+ const [isRepositioning, setIsRepositioning] = useState136(false);
32441
+ const [coverPosition, setCoverPosition] = useState136(() => editor?.getPageMetadata?.()?.coverPosition ?? 50);
32380
32442
  const coverFileInputRef = useRef29(null);
32381
32443
  const logoFileInputRef = useRef29(null);
32382
32444
  const [opened, { open, close }] = useDisclosure7(false);
32383
- const [metadata, setMetadata] = useState135(() => editor?.getPageMetadata?.() || null);
32445
+ const [metadata, setMetadata] = useState136(() => editor?.getPageMetadata?.() || null);
32384
32446
  const settingsPanelContent = useMemo121(() => editor ? /* @__PURE__ */ React296.createElement(FlowSettingsPanel, { editor }) : null, [editor]);
32385
32447
  const { open: openSettings } = usePanel("flow-settings-panel", settingsPanelContent);
32386
32448
  useEffect110(() => {
@@ -32477,38 +32539,13 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32477
32539
  style: {
32478
32540
  position: "relative",
32479
32541
  width: "100%",
32480
- minHeight: hasLogo ? "140px" : "48px",
32481
- backgroundColor: "transparent",
32482
- marginBottom: "0"
32542
+ minHeight: hasLogo ? "140px" : editable ? "28px" : "0",
32543
+ backgroundColor: "transparent"
32483
32544
  },
32484
32545
  onMouseEnter: () => editable && setIsHovering(true),
32485
32546
  onMouseLeave: () => editable && setIsHovering(false)
32486
32547
  },
32487
- /* @__PURE__ */ React296.createElement("div", { style: { maxWidth: "900px", margin: "0 auto", position: "relative", height: "100%" } }, /* @__PURE__ */ React296.createElement("input", { ref: coverFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "cover") }), /* @__PURE__ */ React296.createElement("input", { ref: logoFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "logo") }), editable && isHovering && !logoSrc && /* @__PURE__ */ React296.createElement(
32488
- Group108,
32489
- {
32490
- gap: "xs",
32491
- style: {
32492
- position: "absolute",
32493
- top: "12px",
32494
- left: "0",
32495
- zIndex: 10
32496
- }
32497
- },
32498
- /* @__PURE__ */ React296.createElement(
32499
- BaseIconPicker,
32500
- {
32501
- opened,
32502
- onClose: close,
32503
- currentIcon: metadata?.icon ?? "",
32504
- onSelectIcon: (name) => handleSelectLogoIcon(name),
32505
- onUploadClick: () => logoFileInputRef.current?.click()
32506
- },
32507
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: open }, "Add icon")
32508
- ),
32509
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: () => coverFileInputRef.current?.click() }, "Add cover"),
32510
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: openSettings }, "Settings")
32511
- ), logoSrc && /* @__PURE__ */ React296.createElement(
32548
+ /* @__PURE__ */ React296.createElement("div", { style: { maxWidth: "900px", margin: "0 auto", position: "relative", minHeight: "inherit" } }, /* @__PURE__ */ React296.createElement("input", { ref: coverFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "cover") }), /* @__PURE__ */ React296.createElement("input", { ref: logoFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "logo") }), logoSrc && /* @__PURE__ */ React296.createElement(
32512
32549
  Box62,
32513
32550
  {
32514
32551
  style: {
@@ -32516,44 +32553,46 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32516
32553
  insetInlineStart: "0",
32517
32554
  width: "120px",
32518
32555
  height: "120px",
32519
- left: -20,
32520
32556
  marginTop: "16px",
32521
32557
  padding: 12,
32522
32558
  zIndex: 11
32523
32559
  }
32524
32560
  },
32525
32561
  /* @__PURE__ */ React296.createElement(PageIcon, { src: logoSrc, useCenter: true, iconSize: 64 }),
32526
- editable && isHovering && /* @__PURE__ */ React296.createElement(
32527
- "div",
32562
+ editable && /* @__PURE__ */ React296.createElement(
32563
+ BaseIconPicker,
32528
32564
  {
32529
- style: {
32530
- position: "absolute",
32531
- bottom: "-32px",
32532
- left: "50%",
32533
- transform: "translateX(-50%)",
32534
- zIndex: 12,
32535
- display: "flex",
32536
- flexDirection: "row",
32537
- gap: "4px",
32538
- alignItems: "center"
32539
- }
32565
+ opened,
32566
+ onClose: close,
32567
+ currentIcon: metadata?.icon ?? "",
32568
+ onSelectIcon: (name) => handleSelectLogoIcon(name),
32569
+ onUploadClick: () => logoFileInputRef.current?.click(),
32570
+ onRemove: handleRemoveLogo
32540
32571
  },
32541
32572
  /* @__PURE__ */ React296.createElement(
32542
- BaseIconPicker,
32573
+ Box62,
32543
32574
  {
32544
- opened,
32545
- onClose: close,
32546
- currentIcon: metadata?.icon ?? "",
32547
- onSelectIcon: (name) => handleSelectLogoIcon(name),
32548
- onUploadClick: () => logoFileInputRef.current?.click()
32549
- },
32550
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: open }, "Change")
32551
- ),
32552
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: handleRemoveLogo }, "Remove"),
32553
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: () => coverFileInputRef.current?.click() }, "Add cover"),
32554
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: openSettings }, "Settings")
32575
+ onClick: open,
32576
+ style: {
32577
+ position: "absolute",
32578
+ inset: 12,
32579
+ cursor: "pointer",
32580
+ borderRadius: "100%"
32581
+ }
32582
+ }
32583
+ )
32555
32584
  )
32556
- ))
32585
+ ), editable && (isHovering || opened) && /* @__PURE__ */ React296.createElement(Group109, { gap: 4, style: { position: "absolute", bottom: hasLogo ? -18 : 0, left: 0, zIndex: 10 } }, !logoSrc && /* @__PURE__ */ React296.createElement(
32586
+ BaseIconPicker,
32587
+ {
32588
+ opened,
32589
+ onClose: close,
32590
+ currentIcon: metadata?.icon ?? "",
32591
+ onSelectIcon: (name) => handleSelectLogoIcon(name),
32592
+ onUploadClick: () => logoFileInputRef.current?.click()
32593
+ },
32594
+ /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: open, icon: /* @__PURE__ */ React296.createElement(IconMoodSmile, { size: 14 }) }, "Add icon")
32595
+ ), /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: () => coverFileInputRef.current?.click(), icon: /* @__PURE__ */ React296.createElement(IconPhoto4, { size: 14 }) }, "Add cover"), /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: openSettings, icon: /* @__PURE__ */ React296.createElement(IconSettings22, { size: 14 }) }, "Details")))
32557
32596
  );
32558
32597
  }
32559
32598
  return /* @__PURE__ */ React296.createElement(
@@ -32603,7 +32642,7 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32603
32642
  }
32604
32643
  ),
32605
32644
  editable && isHovering && /* @__PURE__ */ React296.createElement(
32606
- Group108,
32645
+ Group109,
32607
32646
  {
32608
32647
  gap: "xs",
32609
32648
  style: {
@@ -32613,7 +32652,7 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32613
32652
  zIndex: 10
32614
32653
  }
32615
32654
  },
32616
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: () => coverFileInputRef.current?.click() }, "Change cover"),
32655
+ /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: () => coverFileInputRef.current?.click(), icon: /* @__PURE__ */ React296.createElement(IconRefresh5, { size: 14 }) }, "Change cover"),
32617
32656
  /* @__PURE__ */ React296.createElement(
32618
32657
  CoverImageButton,
32619
32658
  {
@@ -32623,12 +32662,12 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32623
32662
  }
32624
32663
  setIsRepositioning(!isRepositioning);
32625
32664
  },
32626
- isActive: isRepositioning
32665
+ isActive: isRepositioning,
32666
+ icon: /* @__PURE__ */ React296.createElement(IconArrowsMove, { size: 14 })
32627
32667
  },
32628
32668
  isRepositioning ? "Done" : "Reposition"
32629
32669
  ),
32630
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: handleRemoveCover }, "Remove"),
32631
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: openSettings }, "Settings")
32670
+ /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: handleRemoveCover, icon: /* @__PURE__ */ React296.createElement(IconTrash11, { size: 14 }) }, "Remove")
32632
32671
  ),
32633
32672
  /* @__PURE__ */ React296.createElement("div", { style: { maxWidth: "900px", margin: "0 auto", position: "absolute", bottom: 0, left: 0, right: 0, height: "70px" } }, /* @__PURE__ */ React296.createElement(
32634
32673
  Box62,
@@ -32642,31 +32681,29 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32642
32681
  zIndex: 11
32643
32682
  }
32644
32683
  },
32645
- logoSrc && /* @__PURE__ */ React296.createElement(PageIcon, { src: logoSrc, useCenter: true, iconSize: 64 }),
32646
- editable && isHovering && /* @__PURE__ */ React296.createElement(React296.Fragment, null, logoSrc ? /* @__PURE__ */ React296.createElement(
32647
- Group108,
32684
+ logoSrc ? /* @__PURE__ */ React296.createElement(React296.Fragment, null, /* @__PURE__ */ React296.createElement(PageIcon, { src: logoSrc, useCenter: true, iconSize: 64 }), editable && /* @__PURE__ */ React296.createElement(
32685
+ BaseIconPicker,
32648
32686
  {
32649
- gap: "xs",
32650
- style: {
32651
- position: "absolute",
32652
- top: "0",
32653
- left: "130px",
32654
- zIndex: 12
32655
- }
32687
+ opened,
32688
+ onClose: close,
32689
+ currentIcon: metadata?.icon ?? "",
32690
+ onSelectIcon: (name) => handleSelectLogoIcon(name),
32691
+ onUploadClick: () => logoFileInputRef.current?.click(),
32692
+ onRemove: handleRemoveLogo
32656
32693
  },
32657
32694
  /* @__PURE__ */ React296.createElement(
32658
- BaseIconPicker,
32695
+ Box62,
32659
32696
  {
32660
- opened,
32661
- onClose: close,
32662
- currentIcon: metadata?.icon ?? "",
32663
- onSelectIcon: (name) => handleSelectLogoIcon(name),
32664
- onUploadClick: () => logoFileInputRef.current?.click()
32665
- },
32666
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: open }, "Change")
32667
- ),
32668
- /* @__PURE__ */ React296.createElement(CoverImageButton, { onClick: handleRemoveLogo }, "Remove")
32669
- ) : /* @__PURE__ */ React296.createElement(
32697
+ onClick: open,
32698
+ style: {
32699
+ position: "absolute",
32700
+ inset: 0,
32701
+ cursor: "pointer",
32702
+ borderRadius: "100%"
32703
+ }
32704
+ }
32705
+ )
32706
+ )) : editable && isHovering && /* @__PURE__ */ React296.createElement(
32670
32707
  BaseIconPicker,
32671
32708
  {
32672
32709
  opened,
@@ -32679,6 +32716,7 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32679
32716
  CoverImageButton,
32680
32717
  {
32681
32718
  onClick: open,
32719
+ icon: /* @__PURE__ */ React296.createElement(IconMoodSmile, { size: 14 }),
32682
32720
  style: {
32683
32721
  position: "absolute",
32684
32722
  top: "50%",
@@ -32689,230 +32727,185 @@ function CoverImage({ coverImageUrl, logoUrl }) {
32689
32727
  },
32690
32728
  "Add icon"
32691
32729
  )
32692
- ))
32730
+ )
32693
32731
  )),
32694
32732
  /* @__PURE__ */ React296.createElement("input", { ref: coverFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "cover") }),
32695
32733
  /* @__PURE__ */ React296.createElement("input", { ref: logoFileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: (e) => handleFileSelect(e, "logo") })
32696
32734
  );
32697
32735
  }
32698
32736
 
32699
- // src/mantine/components/PageHeader.tsx
32700
- import React297, { useState as useState136, useRef as useRef30, useEffect as useEffect111 } from "react";
32701
- function PageHeader({
32702
- title = "New page",
32703
- icon: icon2,
32704
- isPrivate = true,
32705
- onPrivacyChange,
32706
- lastEdited,
32707
- onShare,
32708
- onFavorite,
32709
- isFavorited = false,
32710
- menuItems = []
32711
- }) {
32712
- const [isMenuOpen, setIsMenuOpen] = useState136(false);
32713
- const [isPrivacyOpen, setIsPrivacyOpen] = useState136(false);
32714
- const menuRef = useRef30(null);
32715
- const privacyRef = useRef30(null);
32737
+ // src/mantine/components/PageTitle.tsx
32738
+ import React297, { useState as useState137, useEffect as useEffect111, useRef as useRef30, useCallback as useCallback110 } from "react";
32739
+ import { Box as Box63 } from "@mantine/core";
32740
+ var DEFAULT_TITLE = "New page";
32741
+ function isUserTitle(name) {
32742
+ if (!name) return "";
32743
+ if (name.startsWith("#") || name.startsWith("!")) return "";
32744
+ if (name === DEFAULT_TITLE) return "";
32745
+ return name;
32746
+ }
32747
+ function cleanEmptyEditable(el) {
32748
+ const text = el.textContent?.trim() || "";
32749
+ if (!text) {
32750
+ el.innerHTML = "";
32751
+ }
32752
+ }
32753
+ function PageTitle({ editor, editable }) {
32754
+ const [title, setTitle] = useState137("");
32755
+ const [hasIcon, setHasIcon] = useState137(false);
32756
+ const titleRef = useRef30(null);
32757
+ const isComposing = useRef30(false);
32716
32758
  useEffect111(() => {
32717
- function handleClickOutside(event) {
32718
- if (menuRef.current && !menuRef.current.contains(event.target)) {
32719
- setIsMenuOpen(false);
32720
- }
32721
- if (privacyRef.current && !privacyRef.current.contains(event.target)) {
32722
- setIsPrivacyOpen(false);
32759
+ if (!editor?._metadataManager) return;
32760
+ const metadata = editor._metadataManager.getMetadata();
32761
+ const initial = isUserTitle(metadata?.title);
32762
+ if (initial) {
32763
+ setTitle(initial);
32764
+ }
32765
+ setHasIcon(!!metadata?.icon);
32766
+ const unsubscribe = editor._metadataManager.subscribe((newMetadata) => {
32767
+ if (newMetadata.title !== void 0) {
32768
+ const resolved = isUserTitle(newMetadata.title);
32769
+ setTitle(resolved);
32770
+ if (titleRef.current && titleRef.current.textContent !== resolved) {
32771
+ titleRef.current.textContent = resolved;
32772
+ }
32723
32773
  }
32774
+ setHasIcon(!!newMetadata.icon);
32775
+ });
32776
+ return unsubscribe;
32777
+ }, [editor]);
32778
+ useEffect111(() => {
32779
+ if (titleRef.current && title && !titleRef.current.textContent) {
32780
+ titleRef.current.textContent = title;
32724
32781
  }
32725
- if (isMenuOpen || isPrivacyOpen) {
32726
- document.addEventListener("mousedown", handleClickOutside);
32782
+ }, [title]);
32783
+ const saveTitle = useCallback110(
32784
+ async (newTitle) => {
32785
+ const trimmed = newTitle.trim();
32786
+ const toSave = trimmed || DEFAULT_TITLE;
32787
+ setTitle(trimmed);
32788
+ try {
32789
+ await editor.setPageMetadata?.({ title: toSave });
32790
+ } catch {
32791
+ const current = editor.getPageMetadata?.();
32792
+ if (current?.title !== void 0) {
32793
+ setTitle(isUserTitle(current.title));
32794
+ }
32795
+ }
32796
+ },
32797
+ [editor]
32798
+ );
32799
+ const handleInput = useCallback110(() => {
32800
+ if (titleRef.current) {
32801
+ cleanEmptyEditable(titleRef.current);
32802
+ setTitle(titleRef.current.textContent || "");
32727
32803
  }
32728
- return () => {
32729
- document.removeEventListener("mousedown", handleClickOutside);
32730
- };
32731
- }, [isMenuOpen, isPrivacyOpen]);
32732
- const handleMenuItemClick = (item) => {
32733
- if (!item.disabled) {
32734
- item.onClick();
32735
- setIsMenuOpen(false);
32804
+ }, []);
32805
+ const handleBlur = useCallback110(() => {
32806
+ if (titleRef.current) {
32807
+ cleanEmptyEditable(titleRef.current);
32808
+ saveTitle(titleRef.current.textContent || "");
32736
32809
  }
32737
- };
32738
- return /* @__PURE__ */ React297.createElement("div", { style: styles.container }, /* @__PURE__ */ React297.createElement("div", { style: styles.leftSection }, /* @__PURE__ */ React297.createElement("span", { style: styles.icon }, icon2 || "\u{1F4C4}"), /* @__PURE__ */ React297.createElement("span", { style: styles.title }, title), /* @__PURE__ */ React297.createElement("div", { style: styles.privacyContainer, ref: privacyRef }, /* @__PURE__ */ React297.createElement("button", { style: styles.privacyBadge, onClick: () => onPrivacyChange && setIsPrivacyOpen(!isPrivacyOpen) }, /* @__PURE__ */ React297.createElement("span", { style: styles.lockIcon }, isPrivate ? "\u{1F512}" : "\u{1F310}"), /* @__PURE__ */ React297.createElement("span", null, isPrivate ? "Private" : "Public"), onPrivacyChange && /* @__PURE__ */ React297.createElement("span", { style: styles.chevron }, "\u25BE")), isPrivacyOpen && onPrivacyChange && /* @__PURE__ */ React297.createElement("div", { style: styles.dropdown }, /* @__PURE__ */ React297.createElement(
32739
- "button",
32740
- {
32741
- style: {
32742
- ...styles.menuItem,
32743
- ...isPrivate ? styles.menuItemActive : {}
32744
- },
32745
- onClick: () => {
32746
- onPrivacyChange(true);
32747
- setIsPrivacyOpen(false);
32810
+ }, [saveTitle]);
32811
+ const handleKeyDown = useCallback110(
32812
+ (e) => {
32813
+ if (isComposing.current) return;
32814
+ if (e.key === "Enter" || e.key === "ArrowDown") {
32815
+ e.preventDefault();
32816
+ saveTitle(titleRef.current?.textContent || "");
32817
+ editor.focus?.();
32748
32818
  }
32749
32819
  },
32750
- /* @__PURE__ */ React297.createElement("span", { style: styles.menuItemIcon }, "\u{1F512}"),
32751
- /* @__PURE__ */ React297.createElement("span", null, "Private")
32752
- ), /* @__PURE__ */ React297.createElement(
32753
- "button",
32754
- {
32755
- style: {
32756
- ...styles.menuItem,
32757
- ...!isPrivate ? styles.menuItemActive : {}
32758
- },
32759
- onClick: () => {
32760
- onPrivacyChange(false);
32761
- setIsPrivacyOpen(false);
32820
+ [editor, saveTitle]
32821
+ );
32822
+ useEffect111(() => {
32823
+ const handleEditorKeyDown = (e) => {
32824
+ if (e.key !== "ArrowUp" || !titleRef.current) return;
32825
+ try {
32826
+ const pos = editor.getTextCursorPosition?.();
32827
+ if (pos && !pos.prevBlock) {
32828
+ e.preventDefault();
32829
+ titleRef.current.focus();
32830
+ const sel = window.getSelection();
32831
+ if (sel && titleRef.current.childNodes.length > 0) {
32832
+ sel.selectAllChildren(titleRef.current);
32833
+ sel.collapseToEnd();
32834
+ }
32835
+ }
32836
+ } catch {
32762
32837
  }
32763
- },
32764
- /* @__PURE__ */ React297.createElement("span", { style: styles.menuItemIcon }, "\u{1F310}"),
32765
- /* @__PURE__ */ React297.createElement("span", null, "Public")
32766
- )))), /* @__PURE__ */ React297.createElement("div", { style: styles.rightSection }, lastEdited && /* @__PURE__ */ React297.createElement("span", { style: styles.editedText }, lastEdited), onShare && /* @__PURE__ */ React297.createElement("button", { style: styles.shareButton, onClick: onShare }, "Share"), onFavorite && /* @__PURE__ */ React297.createElement("button", { style: styles.iconButton, onClick: onFavorite }, isFavorited ? "\u2605" : "\u2606"), menuItems.length > 0 && /* @__PURE__ */ React297.createElement("div", { style: styles.menuContainer, ref: menuRef }, /* @__PURE__ */ React297.createElement("button", { style: styles.menuButton, onClick: () => setIsMenuOpen(!isMenuOpen), "aria-label": "Menu" }, /* @__PURE__ */ React297.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor" }, /* @__PURE__ */ React297.createElement("circle", { cx: "3", cy: "8", r: "1.5" }), /* @__PURE__ */ React297.createElement("circle", { cx: "8", cy: "8", r: "1.5" }), /* @__PURE__ */ React297.createElement("circle", { cx: "13", cy: "8", r: "1.5" }))), isMenuOpen && /* @__PURE__ */ React297.createElement("div", { style: styles.dropdown }, menuItems.map((item, index) => /* @__PURE__ */ React297.createElement(React297.Fragment, { key: index }, item.divider && index > 0 && /* @__PURE__ */ React297.createElement("div", { style: styles.divider }), /* @__PURE__ */ React297.createElement(
32767
- "button",
32838
+ };
32839
+ const container = titleRef.current?.closest(".ixo-editor");
32840
+ container?.addEventListener("keydown", handleEditorKeyDown, true);
32841
+ return () => {
32842
+ container?.removeEventListener("keydown", handleEditorKeyDown, true);
32843
+ };
32844
+ }, [editor]);
32845
+ const handlePaste = useCallback110((e) => {
32846
+ e.preventDefault();
32847
+ const text = e.clipboardData.getData("text/plain").replace(/\n/g, " ");
32848
+ document.execCommand("insertText", false, text);
32849
+ }, []);
32850
+ return /* @__PURE__ */ React297.createElement(Box63, { maw: 900, mx: "auto", w: "100%" }, /* @__PURE__ */ React297.createElement(
32851
+ Box63,
32768
32852
  {
32853
+ ref: titleRef,
32854
+ component: "div",
32855
+ contentEditable: editable !== false,
32856
+ suppressContentEditableWarning: true,
32857
+ role: "textbox",
32858
+ "aria-label": "Page title",
32859
+ "data-placeholder": "New page",
32860
+ fz: 40,
32861
+ fw: 700,
32862
+ lh: 1.2,
32863
+ mih: "1em",
32864
+ pt: hasIcon ? 24 : 0,
32865
+ pb: 24,
32866
+ px: 0,
32769
32867
  style: {
32770
- ...styles.menuItem,
32771
- ...item.disabled ? styles.menuItemDisabled : {}
32772
- },
32773
- onClick: () => handleMenuItemClick(item),
32774
- disabled: item.disabled
32775
- },
32776
- item.icon && /* @__PURE__ */ React297.createElement("span", { style: styles.menuItemIcon }, item.icon),
32777
- /* @__PURE__ */ React297.createElement("span", null, item.label)
32778
- )))))));
32868
+ color: "var(--mantine-color-neutralColor-8) !important",
32869
+ caretColor: "var(--mantine-color-neutralColor-8) !important",
32870
+ outline: "none",
32871
+ border: "none",
32872
+ wordBreak: "break-word",
32873
+ whiteSpace: "pre-wrap",
32874
+ cursor: editable === false ? "default" : void 0
32875
+ },
32876
+ onInput: handleInput,
32877
+ onBlur: handleBlur,
32878
+ onKeyDown: handleKeyDown,
32879
+ onPaste: handlePaste,
32880
+ onCompositionStart: () => {
32881
+ isComposing.current = true;
32882
+ },
32883
+ onCompositionEnd: () => {
32884
+ isComposing.current = false;
32885
+ },
32886
+ spellCheck: false
32887
+ }
32888
+ ));
32779
32889
  }
32780
- var styles = {
32781
- container: {
32782
- display: "flex",
32783
- alignItems: "center",
32784
- justifyContent: "space-between",
32785
- padding: "8px 12px",
32786
- borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
32787
- backgroundColor: "transparent",
32788
- fontSize: "14px",
32789
- minHeight: "44px",
32790
- color: "rgba(255, 255, 255, 0.9)"
32791
- },
32792
- leftSection: {
32793
- display: "flex",
32794
- alignItems: "center",
32795
- gap: "8px"
32796
- },
32797
- icon: {
32798
- fontSize: "16px"
32799
- },
32800
- title: {
32801
- fontWeight: 500,
32802
- color: "rgba(255, 255, 255, 0.9)"
32803
- },
32804
- privacyContainer: {
32805
- position: "relative"
32806
- },
32807
- privacyBadge: {
32808
- display: "flex",
32809
- alignItems: "center",
32810
- gap: "4px",
32811
- padding: "2px 6px",
32812
- border: "none",
32813
- backgroundColor: "transparent",
32814
- color: "rgba(255, 255, 255, 0.5)",
32815
- fontSize: "12px",
32816
- cursor: "pointer",
32817
- borderRadius: "3px"
32818
- },
32819
- lockIcon: {
32820
- fontSize: "12px"
32821
- },
32822
- chevron: {
32823
- fontSize: "10px",
32824
- marginLeft: "2px"
32825
- },
32826
- rightSection: {
32827
- display: "flex",
32828
- alignItems: "center",
32829
- gap: "8px"
32830
- },
32831
- editedText: {
32832
- color: "rgba(255, 255, 255, 0.4)",
32833
- fontSize: "12px"
32834
- },
32835
- shareButton: {
32836
- padding: "4px 10px",
32837
- border: "none",
32838
- backgroundColor: "transparent",
32839
- color: "rgba(255, 255, 255, 0.9)",
32840
- fontSize: "14px",
32841
- cursor: "pointer",
32842
- borderRadius: "3px",
32843
- fontWeight: 500
32844
- },
32845
- iconButton: {
32846
- padding: "4px 8px",
32847
- border: "none",
32848
- backgroundColor: "transparent",
32849
- color: "rgba(255, 255, 255, 0.5)",
32850
- fontSize: "16px",
32851
- cursor: "pointer",
32852
- borderRadius: "3px"
32853
- },
32854
- menuContainer: {
32855
- position: "relative"
32856
- },
32857
- menuButton: {
32858
- display: "flex",
32859
- alignItems: "center",
32860
- justifyContent: "center",
32861
- padding: "4px 8px",
32862
- border: "none",
32863
- backgroundColor: "transparent",
32864
- color: "rgba(255, 255, 255, 0.5)",
32865
- cursor: "pointer",
32866
- borderRadius: "3px"
32867
- },
32868
- dropdown: {
32869
- position: "absolute",
32870
- top: "100%",
32871
- right: 0,
32872
- marginTop: "4px",
32873
- minWidth: "180px",
32874
- backgroundColor: "rgb(37, 37, 37)",
32875
- borderRadius: "6px",
32876
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.4)",
32877
- border: "1px solid rgba(255, 255, 255, 0.1)",
32878
- padding: "4px 0",
32879
- zIndex: 1e3
32880
- },
32881
- menuItem: {
32882
- display: "flex",
32883
- alignItems: "center",
32884
- gap: "8px",
32885
- width: "100%",
32886
- padding: "8px 12px",
32887
- border: "none",
32888
- backgroundColor: "transparent",
32889
- color: "rgba(255, 255, 255, 0.9)",
32890
- fontSize: "14px",
32891
- cursor: "pointer",
32892
- textAlign: "left"
32893
- },
32894
- menuItemDisabled: {
32895
- color: "rgba(255, 255, 255, 0.3)",
32896
- cursor: "not-allowed"
32897
- },
32898
- menuItemActive: {
32899
- backgroundColor: "rgba(255, 255, 255, 0.08)"
32900
- },
32901
- menuItemIcon: {
32902
- display: "flex",
32903
- alignItems: "center",
32904
- fontSize: "16px"
32905
- },
32906
- divider: {
32907
- height: "1px",
32908
- backgroundColor: "rgba(255, 255, 255, 0.1)",
32909
- margin: "4px 0"
32890
+ if (typeof document !== "undefined") {
32891
+ const styleId = "ixo-page-title-styles";
32892
+ if (!document.getElementById(styleId)) {
32893
+ const style = document.createElement("style");
32894
+ style.id = styleId;
32895
+ style.textContent = `
32896
+ [data-placeholder]:empty::before {
32897
+ content: attr(data-placeholder);
32898
+ color: var(--mantine-color-neutralColor-7) !important;
32899
+ pointer-events: none;
32900
+ }
32901
+ `;
32902
+ document.head.appendChild(style);
32910
32903
  }
32911
- };
32904
+ }
32912
32905
 
32913
32906
  // src/mantine/components/ExternalDropZone.tsx
32914
- import React298, { useCallback as useCallback110, useEffect as useEffect112, useRef as useRef31, useState as useState137 } from "react";
32915
- import { Box as Box63 } from "@mantine/core";
32907
+ import React298, { useCallback as useCallback111, useEffect as useEffect112, useRef as useRef31, useState as useState138 } from "react";
32908
+ import { Box as Box64 } from "@mantine/core";
32916
32909
  var SCROLL_ZONE_SIZE = 80;
32917
32910
  var SCROLL_SPEED = 12;
32918
32911
  var ExternalDropZone = ({
@@ -32925,19 +32918,19 @@ var ExternalDropZone = ({
32925
32918
  children
32926
32919
  }) => {
32927
32920
  const containerRef = useRef31(null);
32928
- const [isValidDrag, setIsValidDrag] = useState137(false);
32929
- const [isHoveringInPlacementMode, setIsHoveringInPlacementMode] = useState137(false);
32930
- const [indicatorStyle, setIndicatorStyle] = useState137({});
32921
+ const [isValidDrag, setIsValidDrag] = useState138(false);
32922
+ const [isHoveringInPlacementMode, setIsHoveringInPlacementMode] = useState138(false);
32923
+ const [indicatorStyle, setIndicatorStyle] = useState138({});
32931
32924
  const dropPositionRef = useRef31(null);
32932
32925
  const scrollAnimationRef = useRef31(null);
32933
32926
  const scrollDirectionRef = useRef31(null);
32934
32927
  const scrollContainerRef = useRef31(null);
32935
- const getBlockElements = useCallback110(() => {
32928
+ const getBlockElements = useCallback111(() => {
32936
32929
  if (!containerRef.current) return [];
32937
32930
  const blocks = containerRef.current.querySelectorAll('[data-node-type="blockContainer"]');
32938
32931
  return Array.from(blocks);
32939
32932
  }, []);
32940
- const getScrollContainer = useCallback110(() => {
32933
+ const getScrollContainer = useCallback111(() => {
32941
32934
  if (scrollContainerRef.current) return scrollContainerRef.current;
32942
32935
  let element = containerRef.current;
32943
32936
  while (element) {
@@ -32952,7 +32945,7 @@ var ExternalDropZone = ({
32952
32945
  scrollContainerRef.current = window;
32953
32946
  return window;
32954
32947
  }, []);
32955
- const performScroll = useCallback110(() => {
32948
+ const performScroll = useCallback111(() => {
32956
32949
  const container = getScrollContainer();
32957
32950
  const direction = scrollDirectionRef.current;
32958
32951
  if (!direction) {
@@ -32967,7 +32960,7 @@ var ExternalDropZone = ({
32967
32960
  }
32968
32961
  scrollAnimationRef.current = requestAnimationFrame(performScroll);
32969
32962
  }, [getScrollContainer]);
32970
- const startAutoScroll = useCallback110(
32963
+ const startAutoScroll = useCallback111(
32971
32964
  (direction) => {
32972
32965
  if (scrollDirectionRef.current === direction) return;
32973
32966
  scrollDirectionRef.current = direction;
@@ -32977,14 +32970,14 @@ var ExternalDropZone = ({
32977
32970
  },
32978
32971
  [performScroll]
32979
32972
  );
32980
- const stopAutoScroll = useCallback110(() => {
32973
+ const stopAutoScroll = useCallback111(() => {
32981
32974
  scrollDirectionRef.current = null;
32982
32975
  if (scrollAnimationRef.current) {
32983
32976
  cancelAnimationFrame(scrollAnimationRef.current);
32984
32977
  scrollAnimationRef.current = null;
32985
32978
  }
32986
32979
  }, []);
32987
- const checkAutoScroll = useCallback110(
32980
+ const checkAutoScroll = useCallback111(
32988
32981
  (clientY) => {
32989
32982
  const container = getScrollContainer();
32990
32983
  let containerTop;
@@ -33007,7 +33000,7 @@ var ExternalDropZone = ({
33007
33000
  },
33008
33001
  [getScrollContainer, startAutoScroll, stopAutoScroll]
33009
33002
  );
33010
- const findDropPosition = useCallback110(
33003
+ const findDropPosition = useCallback111(
33011
33004
  (clientY) => {
33012
33005
  const blocks = getBlockElements();
33013
33006
  if (blocks.length === 0 || !editor?.document) return null;
@@ -33040,7 +33033,7 @@ var ExternalDropZone = ({
33040
33033
  },
33041
33034
  [getBlockElements, editor]
33042
33035
  );
33043
- const handleDragOver = useCallback110(
33036
+ const handleDragOver = useCallback111(
33044
33037
  (e) => {
33045
33038
  if (!e.dataTransfer.types.includes(acceptedType)) return;
33046
33039
  e.preventDefault();
@@ -33063,7 +33056,7 @@ var ExternalDropZone = ({
33063
33056
  },
33064
33057
  [acceptedType, findDropPosition, checkAutoScroll]
33065
33058
  );
33066
- const handleDragLeave = useCallback110(
33059
+ const handleDragLeave = useCallback111(
33067
33060
  (e) => {
33068
33061
  if (containerRef.current && !containerRef.current.contains(e.relatedTarget)) {
33069
33062
  setIsValidDrag(false);
@@ -33073,7 +33066,7 @@ var ExternalDropZone = ({
33073
33066
  },
33074
33067
  [stopAutoScroll]
33075
33068
  );
33076
- const handleDrop = useCallback110(
33069
+ const handleDrop = useCallback111(
33077
33070
  (e) => {
33078
33071
  e.preventDefault();
33079
33072
  e.stopPropagation();
@@ -33096,7 +33089,7 @@ var ExternalDropZone = ({
33096
33089
  window.addEventListener("dragend", handleGlobalDragEnd);
33097
33090
  return () => window.removeEventListener("dragend", handleGlobalDragEnd);
33098
33091
  }, [stopAutoScroll]);
33099
- const handleOverlayMouseMove = useCallback110(
33092
+ const handleOverlayMouseMove = useCallback111(
33100
33093
  (e) => {
33101
33094
  setIsHoveringInPlacementMode(true);
33102
33095
  checkAutoScroll(e.clientY);
@@ -33115,12 +33108,12 @@ var ExternalDropZone = ({
33115
33108
  },
33116
33109
  [findDropPosition, checkAutoScroll]
33117
33110
  );
33118
- const handleOverlayMouseLeave = useCallback110(() => {
33111
+ const handleOverlayMouseLeave = useCallback111(() => {
33119
33112
  setIsHoveringInPlacementMode(false);
33120
33113
  dropPositionRef.current = null;
33121
33114
  stopAutoScroll();
33122
33115
  }, [stopAutoScroll]);
33123
- const handleOverlayClick = useCallback110(
33116
+ const handleOverlayClick = useCallback111(
33124
33117
  (e) => {
33125
33118
  e.preventDefault();
33126
33119
  e.stopPropagation();
@@ -33134,7 +33127,7 @@ var ExternalDropZone = ({
33134
33127
  },
33135
33128
  [onDrop, stopAutoScroll]
33136
33129
  );
33137
- const handleOverlayWheel = useCallback110(
33130
+ const handleOverlayWheel = useCallback111(
33138
33131
  (e) => {
33139
33132
  const container = getScrollContainer();
33140
33133
  if (container === window) {
@@ -33197,7 +33190,7 @@ var ExternalDropZone = ({
33197
33190
  }) : dropIndicator;
33198
33191
  const shouldShowIndicator = isValidDrag || isPlacementMode && isHoveringInPlacementMode;
33199
33192
  return /* @__PURE__ */ React298.createElement(
33200
- Box63,
33193
+ Box64,
33201
33194
  {
33202
33195
  ref: containerRef,
33203
33196
  style: {
@@ -33213,7 +33206,7 @@ var ExternalDropZone = ({
33213
33206
  },
33214
33207
  children,
33215
33208
  isPlacementMode && /* @__PURE__ */ React298.createElement(
33216
- Box63,
33209
+ Box64,
33217
33210
  {
33218
33211
  style: {
33219
33212
  position: "absolute",
@@ -33232,7 +33225,7 @@ var ExternalDropZone = ({
33232
33225
  onWheel: handleOverlayWheel
33233
33226
  }
33234
33227
  ),
33235
- shouldShowIndicator && indicatorWithPosition && /* @__PURE__ */ React298.createElement(Box63, { style: { ...indicatorStyle, background: "none", border: "none", boxShadow: "none" } }, indicatorWithPosition)
33228
+ shouldShowIndicator && indicatorWithPosition && /* @__PURE__ */ React298.createElement(Box64, { style: { ...indicatorStyle, background: "none", border: "none", boxShadow: "none" } }, indicatorWithPosition)
33236
33229
  );
33237
33230
  };
33238
33231
 
@@ -33248,8 +33241,6 @@ function IxoEditorContent({
33248
33241
  children,
33249
33242
  coverImageUrl,
33250
33243
  logoUrl,
33251
- selfNav = false,
33252
- pageHeaderProps,
33253
33244
  onExternalDrop,
33254
33245
  externalDropType,
33255
33246
  dropIndicator,
@@ -33258,44 +33249,6 @@ function IxoEditorContent({
33258
33249
  }) {
33259
33250
  const { activePanel } = usePanelStore();
33260
33251
  const isPanelOpen = activePanel !== null;
33261
- const [isRoomPrivate, setIsRoomPrivate] = useState138(pageHeaderProps?.isPrivate ?? true);
33262
- useEffect113(() => {
33263
- const matrixClient = editor.getMatrixClient?.();
33264
- const roomId = editor.getRoomId?.();
33265
- if (!matrixClient || !roomId) return;
33266
- try {
33267
- const room = matrixClient.getRoom(roomId);
33268
- if (room) {
33269
- const joinRules = room.currentState.getStateEvents("m.room.join_rules", "");
33270
- if (joinRules) {
33271
- const rule = joinRules.getContent?.()?.join_rule;
33272
- setIsRoomPrivate(rule !== "public");
33273
- }
33274
- }
33275
- } catch {
33276
- }
33277
- }, [editor]);
33278
- const handlePrivacyChange = useCallback111(
33279
- async (makePrivate) => {
33280
- const matrixClient = editor.getMatrixClient?.();
33281
- const roomId = editor.getRoomId?.();
33282
- if (!matrixClient || !roomId) return;
33283
- try {
33284
- await matrixClient.sendStateEvent(
33285
- roomId,
33286
- "m.room.join_rules",
33287
- {
33288
- join_rule: makePrivate ? "invite" : "public"
33289
- },
33290
- ""
33291
- );
33292
- setIsRoomPrivate(makePrivate);
33293
- } catch (err) {
33294
- console.error("Failed to update room privacy:", err);
33295
- }
33296
- },
33297
- [editor]
33298
- );
33299
33252
  const editorContent = /* @__PURE__ */ React299.createElement(
33300
33253
  BlockNoteView,
33301
33254
  {
@@ -33338,8 +33291,8 @@ function IxoEditorContent({
33338
33291
  transition: "width 0.2s ease"
33339
33292
  }
33340
33293
  },
33341
- selfNav && /* @__PURE__ */ React299.createElement(PageHeader, { ...pageHeaderProps, isPrivate: isRoomPrivate, onPrivacyChange: handlePrivacyChange }),
33342
33294
  /* @__PURE__ */ React299.createElement(CoverImage, { coverImageUrl, logoUrl }),
33295
+ /* @__PURE__ */ React299.createElement(PageTitle, { editor, editable: isEditable }),
33343
33296
  (onExternalDrop || isPlacementMode) && isEditable ? /* @__PURE__ */ React299.createElement(
33344
33297
  ExternalDropZone,
33345
33298
  {
@@ -33368,8 +33321,6 @@ function IxoEditor({
33368
33321
  isPanelVisible,
33369
33322
  coverImageUrl,
33370
33323
  logoUrl,
33371
- selfNav = false,
33372
- pageHeaderProps,
33373
33324
  visualizationRenderer,
33374
33325
  getDynamicListData,
33375
33326
  dynamicListPanelRenderer,
@@ -33423,8 +33374,6 @@ function IxoEditor({
33423
33374
  onSelectionChange,
33424
33375
  coverImageUrl,
33425
33376
  logoUrl,
33426
- selfNav,
33427
- pageHeaderProps,
33428
33377
  onExternalDrop,
33429
33378
  externalDropType,
33430
33379
  dropIndicator,
@@ -33493,16 +33442,230 @@ function DebugButton({ editor }) {
33493
33442
  );
33494
33443
  }
33495
33444
 
33445
+ // src/mantine/components/PageHeader.tsx
33446
+ import React301, { useState as useState139, useRef as useRef32, useEffect as useEffect113 } from "react";
33447
+ function PageHeader({
33448
+ title = "New page",
33449
+ icon: icon2,
33450
+ isPrivate = true,
33451
+ onPrivacyChange,
33452
+ lastEdited,
33453
+ onShare,
33454
+ onFavorite,
33455
+ isFavorited = false,
33456
+ menuItems = []
33457
+ }) {
33458
+ const [isMenuOpen, setIsMenuOpen] = useState139(false);
33459
+ const [isPrivacyOpen, setIsPrivacyOpen] = useState139(false);
33460
+ const menuRef = useRef32(null);
33461
+ const privacyRef = useRef32(null);
33462
+ useEffect113(() => {
33463
+ function handleClickOutside(event) {
33464
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
33465
+ setIsMenuOpen(false);
33466
+ }
33467
+ if (privacyRef.current && !privacyRef.current.contains(event.target)) {
33468
+ setIsPrivacyOpen(false);
33469
+ }
33470
+ }
33471
+ if (isMenuOpen || isPrivacyOpen) {
33472
+ document.addEventListener("mousedown", handleClickOutside);
33473
+ }
33474
+ return () => {
33475
+ document.removeEventListener("mousedown", handleClickOutside);
33476
+ };
33477
+ }, [isMenuOpen, isPrivacyOpen]);
33478
+ const handleMenuItemClick = (item) => {
33479
+ if (!item.disabled) {
33480
+ item.onClick();
33481
+ setIsMenuOpen(false);
33482
+ }
33483
+ };
33484
+ return /* @__PURE__ */ React301.createElement("div", { style: styles.container }, /* @__PURE__ */ React301.createElement("div", { style: styles.leftSection }, /* @__PURE__ */ React301.createElement("span", { style: styles.icon }, icon2 || "\u{1F4C4}"), /* @__PURE__ */ React301.createElement("span", { style: styles.title }, title), /* @__PURE__ */ React301.createElement("div", { style: styles.privacyContainer, ref: privacyRef }, /* @__PURE__ */ React301.createElement("button", { style: styles.privacyBadge, onClick: () => onPrivacyChange && setIsPrivacyOpen(!isPrivacyOpen) }, /* @__PURE__ */ React301.createElement("span", { style: styles.lockIcon }, isPrivate ? "\u{1F512}" : "\u{1F310}"), /* @__PURE__ */ React301.createElement("span", null, isPrivate ? "Private" : "Public"), onPrivacyChange && /* @__PURE__ */ React301.createElement("span", { style: styles.chevron }, "\u25BE")), isPrivacyOpen && onPrivacyChange && /* @__PURE__ */ React301.createElement("div", { style: styles.dropdown }, /* @__PURE__ */ React301.createElement(
33485
+ "button",
33486
+ {
33487
+ style: {
33488
+ ...styles.menuItem,
33489
+ ...isPrivate ? styles.menuItemActive : {}
33490
+ },
33491
+ onClick: () => {
33492
+ onPrivacyChange(true);
33493
+ setIsPrivacyOpen(false);
33494
+ }
33495
+ },
33496
+ /* @__PURE__ */ React301.createElement("span", { style: styles.menuItemIcon }, "\u{1F512}"),
33497
+ /* @__PURE__ */ React301.createElement("span", null, "Private")
33498
+ ), /* @__PURE__ */ React301.createElement(
33499
+ "button",
33500
+ {
33501
+ style: {
33502
+ ...styles.menuItem,
33503
+ ...!isPrivate ? styles.menuItemActive : {}
33504
+ },
33505
+ onClick: () => {
33506
+ onPrivacyChange(false);
33507
+ setIsPrivacyOpen(false);
33508
+ }
33509
+ },
33510
+ /* @__PURE__ */ React301.createElement("span", { style: styles.menuItemIcon }, "\u{1F310}"),
33511
+ /* @__PURE__ */ React301.createElement("span", null, "Public")
33512
+ )))), /* @__PURE__ */ React301.createElement("div", { style: styles.rightSection }, lastEdited && /* @__PURE__ */ React301.createElement("span", { style: styles.editedText }, lastEdited), onShare && /* @__PURE__ */ React301.createElement("button", { style: styles.shareButton, onClick: onShare }, "Share"), onFavorite && /* @__PURE__ */ React301.createElement("button", { style: styles.iconButton, onClick: onFavorite }, isFavorited ? "\u2605" : "\u2606"), menuItems.length > 0 && /* @__PURE__ */ React301.createElement("div", { style: styles.menuContainer, ref: menuRef }, /* @__PURE__ */ React301.createElement("button", { style: styles.menuButton, onClick: () => setIsMenuOpen(!isMenuOpen), "aria-label": "Menu" }, /* @__PURE__ */ React301.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor" }, /* @__PURE__ */ React301.createElement("circle", { cx: "3", cy: "8", r: "1.5" }), /* @__PURE__ */ React301.createElement("circle", { cx: "8", cy: "8", r: "1.5" }), /* @__PURE__ */ React301.createElement("circle", { cx: "13", cy: "8", r: "1.5" }))), isMenuOpen && /* @__PURE__ */ React301.createElement("div", { style: styles.dropdown }, menuItems.map((item, index) => /* @__PURE__ */ React301.createElement(React301.Fragment, { key: index }, item.divider && index > 0 && /* @__PURE__ */ React301.createElement("div", { style: styles.divider }), /* @__PURE__ */ React301.createElement(
33513
+ "button",
33514
+ {
33515
+ style: {
33516
+ ...styles.menuItem,
33517
+ ...item.disabled ? styles.menuItemDisabled : {}
33518
+ },
33519
+ onClick: () => handleMenuItemClick(item),
33520
+ disabled: item.disabled
33521
+ },
33522
+ item.icon && /* @__PURE__ */ React301.createElement("span", { style: styles.menuItemIcon }, item.icon),
33523
+ /* @__PURE__ */ React301.createElement("span", null, item.label)
33524
+ )))))));
33525
+ }
33526
+ var styles = {
33527
+ container: {
33528
+ display: "flex",
33529
+ alignItems: "center",
33530
+ justifyContent: "space-between",
33531
+ padding: "8px 12px",
33532
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
33533
+ backgroundColor: "transparent",
33534
+ fontSize: "14px",
33535
+ minHeight: "44px",
33536
+ color: "rgba(255, 255, 255, 0.9)"
33537
+ },
33538
+ leftSection: {
33539
+ display: "flex",
33540
+ alignItems: "center",
33541
+ gap: "8px"
33542
+ },
33543
+ icon: {
33544
+ fontSize: "16px"
33545
+ },
33546
+ title: {
33547
+ fontWeight: 500,
33548
+ color: "rgba(255, 255, 255, 0.9)"
33549
+ },
33550
+ privacyContainer: {
33551
+ position: "relative"
33552
+ },
33553
+ privacyBadge: {
33554
+ display: "flex",
33555
+ alignItems: "center",
33556
+ gap: "4px",
33557
+ padding: "2px 6px",
33558
+ border: "none",
33559
+ backgroundColor: "transparent",
33560
+ color: "rgba(255, 255, 255, 0.5)",
33561
+ fontSize: "12px",
33562
+ cursor: "pointer",
33563
+ borderRadius: "3px"
33564
+ },
33565
+ lockIcon: {
33566
+ fontSize: "12px"
33567
+ },
33568
+ chevron: {
33569
+ fontSize: "10px",
33570
+ marginLeft: "2px"
33571
+ },
33572
+ rightSection: {
33573
+ display: "flex",
33574
+ alignItems: "center",
33575
+ gap: "8px"
33576
+ },
33577
+ editedText: {
33578
+ color: "rgba(255, 255, 255, 0.4)",
33579
+ fontSize: "12px"
33580
+ },
33581
+ shareButton: {
33582
+ padding: "4px 10px",
33583
+ border: "none",
33584
+ backgroundColor: "transparent",
33585
+ color: "rgba(255, 255, 255, 0.9)",
33586
+ fontSize: "14px",
33587
+ cursor: "pointer",
33588
+ borderRadius: "3px",
33589
+ fontWeight: 500
33590
+ },
33591
+ iconButton: {
33592
+ padding: "4px 8px",
33593
+ border: "none",
33594
+ backgroundColor: "transparent",
33595
+ color: "rgba(255, 255, 255, 0.5)",
33596
+ fontSize: "16px",
33597
+ cursor: "pointer",
33598
+ borderRadius: "3px"
33599
+ },
33600
+ menuContainer: {
33601
+ position: "relative"
33602
+ },
33603
+ menuButton: {
33604
+ display: "flex",
33605
+ alignItems: "center",
33606
+ justifyContent: "center",
33607
+ padding: "4px 8px",
33608
+ border: "none",
33609
+ backgroundColor: "transparent",
33610
+ color: "rgba(255, 255, 255, 0.5)",
33611
+ cursor: "pointer",
33612
+ borderRadius: "3px"
33613
+ },
33614
+ dropdown: {
33615
+ position: "absolute",
33616
+ top: "100%",
33617
+ right: 0,
33618
+ marginTop: "4px",
33619
+ minWidth: "180px",
33620
+ backgroundColor: "rgb(37, 37, 37)",
33621
+ borderRadius: "6px",
33622
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.4)",
33623
+ border: "1px solid rgba(255, 255, 255, 0.1)",
33624
+ padding: "4px 0",
33625
+ zIndex: 1e3
33626
+ },
33627
+ menuItem: {
33628
+ display: "flex",
33629
+ alignItems: "center",
33630
+ gap: "8px",
33631
+ width: "100%",
33632
+ padding: "8px 12px",
33633
+ border: "none",
33634
+ backgroundColor: "transparent",
33635
+ color: "rgba(255, 255, 255, 0.9)",
33636
+ fontSize: "14px",
33637
+ cursor: "pointer",
33638
+ textAlign: "left"
33639
+ },
33640
+ menuItemDisabled: {
33641
+ color: "rgba(255, 255, 255, 0.3)",
33642
+ cursor: "not-allowed"
33643
+ },
33644
+ menuItemActive: {
33645
+ backgroundColor: "rgba(255, 255, 255, 0.08)"
33646
+ },
33647
+ menuItemIcon: {
33648
+ display: "flex",
33649
+ alignItems: "center",
33650
+ fontSize: "16px"
33651
+ },
33652
+ divider: {
33653
+ height: "1px",
33654
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
33655
+ margin: "4px 0"
33656
+ }
33657
+ };
33658
+
33496
33659
  // src/mantine/components/EntitySigningSetup.tsx
33497
- import React301, { useState as useState139 } from "react";
33498
- import { Modal as Modal3, Stack as Stack198, Text as Text172, TextInput as TextInput8, Button as Button57, Alert as Alert54, Group as Group109 } from "@mantine/core";
33660
+ import React302, { useState as useState140 } from "react";
33661
+ import { Modal as Modal3, Stack as Stack198, Text as Text173, TextInput as TextInput8, Button as Button56, Alert as Alert54, Group as Group110 } from "@mantine/core";
33499
33662
  import { IconAlertCircle as IconAlertCircle20, IconCheck as IconCheck23, IconKey as IconKey2 } from "@tabler/icons-react";
33500
33663
  var EntitySigningSetup = ({ opened, onClose, entityDid, entityName, onSetup }) => {
33501
- const [pin, setPin] = useState139("");
33502
- const [confirmPin, setConfirmPin] = useState139("");
33503
- const [loading, setLoading] = useState139(false);
33504
- const [error, setError] = useState139(null);
33505
- const [success, setSuccess] = useState139(false);
33664
+ const [pin, setPin] = useState140("");
33665
+ const [confirmPin, setConfirmPin] = useState140("");
33666
+ const [loading, setLoading] = useState140(false);
33667
+ const [error, setError] = useState140(null);
33668
+ const [success, setSuccess] = useState140(false);
33506
33669
  const handleSetup = async () => {
33507
33670
  if (pin.length < 4) {
33508
33671
  setError("PIN must be at least 4 characters");
@@ -33542,15 +33705,15 @@ var EntitySigningSetup = ({ opened, onClose, entityDid, entityName, onSetup }) =
33542
33705
  setSuccess(false);
33543
33706
  }
33544
33707
  };
33545
- return /* @__PURE__ */ React301.createElement(
33708
+ return /* @__PURE__ */ React302.createElement(
33546
33709
  Modal3,
33547
33710
  {
33548
33711
  opened,
33549
33712
  onClose: handleClose,
33550
- title: /* @__PURE__ */ React301.createElement(Group109, { gap: "xs" }, /* @__PURE__ */ React301.createElement(IconKey2, { size: 20 }), /* @__PURE__ */ React301.createElement(Text172, { fw: 600 }, "Entity Signing Setup")),
33713
+ title: /* @__PURE__ */ React302.createElement(Group110, { gap: "xs" }, /* @__PURE__ */ React302.createElement(IconKey2, { size: 20 }), /* @__PURE__ */ React302.createElement(Text173, { fw: 600 }, "Entity Signing Setup")),
33551
33714
  size: "md"
33552
33715
  },
33553
- /* @__PURE__ */ React301.createElement(Stack198, { gap: "md" }, success ? /* @__PURE__ */ React301.createElement(Alert54, { color: "green", icon: /* @__PURE__ */ React301.createElement(IconCheck23, { size: 16 }) }, "Entity signing key set up successfully!") : /* @__PURE__ */ React301.createElement(React301.Fragment, null, /* @__PURE__ */ React301.createElement(Text172, { size: "sm", c: "dimmed" }, "Flow authorization requires a signing key for", " ", /* @__PURE__ */ React301.createElement(Text172, { span: true, fw: 500 }, entityName || entityDid), "."), /* @__PURE__ */ React301.createElement(Alert54, { color: "blue", variant: "light" }, /* @__PURE__ */ React301.createElement(Text172, { size: "sm" }, "This is a ", /* @__PURE__ */ React301.createElement("strong", null, "one-time setup"), " that allows flows to grant permissions without requiring wallet signatures for each delegation.")), /* @__PURE__ */ React301.createElement(Stack198, { gap: "xs" }, /* @__PURE__ */ React301.createElement(Text172, { size: "sm", fw: 500 }, "What happens:"), /* @__PURE__ */ React301.createElement(Text172, { size: "sm", c: "dimmed" }, "1. A new signing key is generated"), /* @__PURE__ */ React301.createElement(Text172, { size: "sm", c: "dimmed" }, "2. Key is registered on the entity's DID document (requires wallet)"), /* @__PURE__ */ React301.createElement(Text172, { size: "sm", c: "dimmed" }, "3. Key is stored encrypted in the entity's Matrix room")), /* @__PURE__ */ React301.createElement(
33716
+ /* @__PURE__ */ React302.createElement(Stack198, { gap: "md" }, success ? /* @__PURE__ */ React302.createElement(Alert54, { color: "green", icon: /* @__PURE__ */ React302.createElement(IconCheck23, { size: 16 }) }, "Entity signing key set up successfully!") : /* @__PURE__ */ React302.createElement(React302.Fragment, null, /* @__PURE__ */ React302.createElement(Text173, { size: "sm", c: "dimmed" }, "Flow authorization requires a signing key for", " ", /* @__PURE__ */ React302.createElement(Text173, { span: true, fw: 500 }, entityName || entityDid), "."), /* @__PURE__ */ React302.createElement(Alert54, { color: "blue", variant: "light" }, /* @__PURE__ */ React302.createElement(Text173, { size: "sm" }, "This is a ", /* @__PURE__ */ React302.createElement("strong", null, "one-time setup"), " that allows flows to grant permissions without requiring wallet signatures for each delegation.")), /* @__PURE__ */ React302.createElement(Stack198, { gap: "xs" }, /* @__PURE__ */ React302.createElement(Text173, { size: "sm", fw: 500 }, "What happens:"), /* @__PURE__ */ React302.createElement(Text173, { size: "sm", c: "dimmed" }, "1. A new signing key is generated"), /* @__PURE__ */ React302.createElement(Text173, { size: "sm", c: "dimmed" }, "2. Key is registered on the entity's DID document (requires wallet)"), /* @__PURE__ */ React302.createElement(Text173, { size: "sm", c: "dimmed" }, "3. Key is stored encrypted in the entity's Matrix room")), /* @__PURE__ */ React302.createElement(
33554
33717
  TextInput8,
33555
33718
  {
33556
33719
  label: "Enter PIN to encrypt signing key",
@@ -33561,18 +33724,18 @@ var EntitySigningSetup = ({ opened, onClose, entityDid, entityName, onSetup }) =
33561
33724
  onChange: (e) => setPin(e.currentTarget.value),
33562
33725
  disabled: loading
33563
33726
  }
33564
- ), /* @__PURE__ */ React301.createElement(TextInput8, { label: "Confirm PIN", type: "password", placeholder: "Confirm PIN", value: confirmPin, onChange: (e) => setConfirmPin(e.currentTarget.value), disabled: loading }), error && /* @__PURE__ */ React301.createElement(Alert54, { color: "red", icon: /* @__PURE__ */ React301.createElement(IconAlertCircle20, { size: 16 }) }, error), /* @__PURE__ */ React301.createElement(Group109, { justify: "flex-end", mt: "md" }, /* @__PURE__ */ React301.createElement(Button57, { variant: "subtle", onClick: handleClose, disabled: loading }, "Cancel"), /* @__PURE__ */ React301.createElement(Button57, { onClick: handleSetup, loading, leftSection: /* @__PURE__ */ React301.createElement(IconKey2, { size: 16 }) }, "Setup Entity Signing"))))
33727
+ ), /* @__PURE__ */ React302.createElement(TextInput8, { label: "Confirm PIN", type: "password", placeholder: "Confirm PIN", value: confirmPin, onChange: (e) => setConfirmPin(e.currentTarget.value), disabled: loading }), error && /* @__PURE__ */ React302.createElement(Alert54, { color: "red", icon: /* @__PURE__ */ React302.createElement(IconAlertCircle20, { size: 16 }) }, error), /* @__PURE__ */ React302.createElement(Group110, { justify: "flex-end", mt: "md" }, /* @__PURE__ */ React302.createElement(Button56, { variant: "subtle", onClick: handleClose, disabled: loading }, "Cancel"), /* @__PURE__ */ React302.createElement(Button56, { onClick: handleSetup, loading, leftSection: /* @__PURE__ */ React302.createElement(IconKey2, { size: 16 }) }, "Setup Entity Signing"))))
33565
33728
  );
33566
33729
  };
33567
33730
 
33568
33731
  // src/mantine/components/FlowPermissionsPanel.tsx
33569
- import React302, { useState as useState140, useEffect as useEffect114, useMemo as useMemo122 } from "react";
33570
- import { Stack as Stack199, Text as Text173, Paper as Paper18, Group as Group110, Badge as Badge45, Button as Button58, ActionIcon as ActionIcon38, Loader as Loader54, Alert as Alert55, Divider as Divider29 } from "@mantine/core";
33571
- import { IconPlus as IconPlus11, IconTrash as IconTrash11, IconShieldCheck as IconShieldCheck16, IconUser as IconUser14, IconRobot as IconRobot4, IconBuilding as IconBuilding2 } from "@tabler/icons-react";
33732
+ import React303, { useState as useState141, useEffect as useEffect114, useMemo as useMemo122 } from "react";
33733
+ import { Stack as Stack199, Text as Text174, Paper as Paper18, Group as Group111, Badge as Badge45, Button as Button57, ActionIcon as ActionIcon38, Loader as Loader54, Alert as Alert55, Divider as Divider29 } from "@mantine/core";
33734
+ import { IconPlus as IconPlus11, IconTrash as IconTrash12, IconShieldCheck as IconShieldCheck16, IconUser as IconUser14, IconRobot as IconRobot4, IconBuilding as IconBuilding2 } from "@tabler/icons-react";
33572
33735
  var FlowPermissionsPanel = ({ editor, entityDid, entityName, onGrantPermission, onRevokePermission, getUserDisplayName }) => {
33573
- const [delegations, setDelegations] = useState140([]);
33574
- const [loading, setLoading] = useState140(true);
33575
- const [revoking, setRevoking] = useState140(null);
33736
+ const [delegations, setDelegations] = useState141([]);
33737
+ const [loading, setLoading] = useState141(true);
33738
+ const [revoking, setRevoking] = useState141(null);
33576
33739
  const rootDelegation = useMemo122(() => {
33577
33740
  if (editor.getUcanService) {
33578
33741
  return editor.getUcanService()?.getRootDelegation() || null;
@@ -33621,11 +33784,11 @@ var FlowPermissionsPanel = ({ editor, entityDid, entityName, onGrantPermission,
33621
33784
  const getIcon2 = (type) => {
33622
33785
  switch (type) {
33623
33786
  case "oracle":
33624
- return /* @__PURE__ */ React302.createElement(IconRobot4, { size: 16 });
33787
+ return /* @__PURE__ */ React303.createElement(IconRobot4, { size: 16 });
33625
33788
  case "entity":
33626
- return /* @__PURE__ */ React302.createElement(IconBuilding2, { size: 16 });
33789
+ return /* @__PURE__ */ React303.createElement(IconBuilding2, { size: 16 });
33627
33790
  default:
33628
- return /* @__PURE__ */ React302.createElement(IconUser14, { size: 16 });
33791
+ return /* @__PURE__ */ React303.createElement(IconUser14, { size: 16 });
33629
33792
  }
33630
33793
  };
33631
33794
  const formatCapabilities = (caps) => {
@@ -33644,31 +33807,31 @@ var FlowPermissionsPanel = ({ editor, entityDid, entityName, onGrantPermission,
33644
33807
  if (date < /* @__PURE__ */ new Date()) return "Expired";
33645
33808
  return date.toLocaleDateString();
33646
33809
  };
33647
- return /* @__PURE__ */ React302.createElement(Stack199, { gap: "md" }, /* @__PURE__ */ React302.createElement(Stack199, { gap: "xs" }, /* @__PURE__ */ React302.createElement(Text173, { fw: 600, size: "sm" }, "Root Authority"), /* @__PURE__ */ React302.createElement(Paper18, { p: "sm", withBorder: true }, /* @__PURE__ */ React302.createElement(Group110, { gap: "xs" }, /* @__PURE__ */ React302.createElement(IconShieldCheck16, { size: 20, color: "var(--mantine-color-green-6)" }), /* @__PURE__ */ React302.createElement(Stack199, { gap: 2, style: { flex: 1 } }, /* @__PURE__ */ React302.createElement(Text173, { size: "sm", fw: 500 }, entityName || entityDid), /* @__PURE__ */ React302.createElement(Text173, { size: "xs", c: "dimmed" }, rootDelegation ? `Granted: ${new Date(rootDelegation.createdAt).toLocaleDateString()}` : "Root capability not set up")), /* @__PURE__ */ React302.createElement(Badge45, { color: "green", variant: "light" }, "Entity")))), /* @__PURE__ */ React302.createElement(Divider29, { label: "Delegated Permissions", labelPosition: "center" }), loading ? /* @__PURE__ */ React302.createElement(Group110, { justify: "center", py: "xl" }, /* @__PURE__ */ React302.createElement(Loader54, { size: "sm" })) : delegations.length === 0 ? /* @__PURE__ */ React302.createElement(Alert55, { color: "gray", variant: "light" }, /* @__PURE__ */ React302.createElement(Text173, { size: "sm" }, "No permissions have been granted yet.")) : /* @__PURE__ */ React302.createElement(Stack199, { gap: "xs" }, delegations.map(({ delegation, displayName, type }) => /* @__PURE__ */ React302.createElement(Paper18, { key: delegation.cid, p: "sm", withBorder: true }, /* @__PURE__ */ React302.createElement(Group110, { justify: "space-between" }, /* @__PURE__ */ React302.createElement(Group110, { gap: "xs" }, getIcon2(type), /* @__PURE__ */ React302.createElement(Stack199, { gap: 2 }, /* @__PURE__ */ React302.createElement(Text173, { size: "sm", fw: 500 }, displayName), /* @__PURE__ */ React302.createElement(Text173, { size: "xs", c: "dimmed" }, formatCapabilities(delegation.capabilities)), /* @__PURE__ */ React302.createElement(Group110, { gap: "xs" }, /* @__PURE__ */ React302.createElement(Text173, { size: "xs", c: "dimmed" }, "Expires: ", formatExpiration(delegation.expiration)), /* @__PURE__ */ React302.createElement(Text173, { size: "xs", c: "dimmed" }, "\u2022"), /* @__PURE__ */ React302.createElement(Text173, { size: "xs", c: "dimmed" }, "Granted by: ", delegation.issuerDid === entityDid ? "Entity" : delegation.issuerDid.slice(-8))))), /* @__PURE__ */ React302.createElement(ActionIcon38, { color: "red", variant: "subtle", onClick: () => handleRevoke(delegation.cid), loading: revoking === delegation.cid, disabled: !!revoking }, /* @__PURE__ */ React302.createElement(IconTrash11, { size: 16 })))))), /* @__PURE__ */ React302.createElement(Button58, { leftSection: /* @__PURE__ */ React302.createElement(IconPlus11, { size: 16 }), variant: "light", onClick: onGrantPermission }, "Grant Permission"));
33810
+ return /* @__PURE__ */ React303.createElement(Stack199, { gap: "md" }, /* @__PURE__ */ React303.createElement(Stack199, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Text174, { fw: 600, size: "sm" }, "Root Authority"), /* @__PURE__ */ React303.createElement(Paper18, { p: "sm", withBorder: true }, /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, /* @__PURE__ */ React303.createElement(IconShieldCheck16, { size: 20, color: "var(--mantine-color-green-6)" }), /* @__PURE__ */ React303.createElement(Stack199, { gap: 2, style: { flex: 1 } }, /* @__PURE__ */ React303.createElement(Text174, { size: "sm", fw: 500 }, entityName || entityDid), /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed" }, rootDelegation ? `Granted: ${new Date(rootDelegation.createdAt).toLocaleDateString()}` : "Root capability not set up")), /* @__PURE__ */ React303.createElement(Badge45, { color: "green", variant: "light" }, "Entity")))), /* @__PURE__ */ React303.createElement(Divider29, { label: "Delegated Permissions", labelPosition: "center" }), loading ? /* @__PURE__ */ React303.createElement(Group111, { justify: "center", py: "xl" }, /* @__PURE__ */ React303.createElement(Loader54, { size: "sm" })) : delegations.length === 0 ? /* @__PURE__ */ React303.createElement(Alert55, { color: "gray", variant: "light" }, /* @__PURE__ */ React303.createElement(Text174, { size: "sm" }, "No permissions have been granted yet.")) : /* @__PURE__ */ React303.createElement(Stack199, { gap: "xs" }, delegations.map(({ delegation, displayName, type }) => /* @__PURE__ */ React303.createElement(Paper18, { key: delegation.cid, p: "sm", withBorder: true }, /* @__PURE__ */ React303.createElement(Group111, { justify: "space-between" }, /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, getIcon2(type), /* @__PURE__ */ React303.createElement(Stack199, { gap: 2 }, /* @__PURE__ */ React303.createElement(Text174, { size: "sm", fw: 500 }, displayName), /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed" }, formatCapabilities(delegation.capabilities)), /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed" }, "Expires: ", formatExpiration(delegation.expiration)), /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed" }, "\u2022"), /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed" }, "Granted by: ", delegation.issuerDid === entityDid ? "Entity" : delegation.issuerDid.slice(-8))))), /* @__PURE__ */ React303.createElement(ActionIcon38, { color: "red", variant: "subtle", onClick: () => handleRevoke(delegation.cid), loading: revoking === delegation.cid, disabled: !!revoking }, /* @__PURE__ */ React303.createElement(IconTrash12, { size: 16 })))))), /* @__PURE__ */ React303.createElement(Button57, { leftSection: /* @__PURE__ */ React303.createElement(IconPlus11, { size: 16 }), variant: "light", onClick: onGrantPermission }, "Grant Permission"));
33648
33811
  };
33649
33812
 
33650
33813
  // src/mantine/components/GrantPermissionModal.tsx
33651
- import React303, { useState as useState141, useCallback as useCallback112 } from "react";
33652
- import { Modal as Modal4, Stack as Stack200, Text as Text174, TextInput as TextInput9, Button as Button59, Group as Group111, Radio as Radio5, Checkbox as Checkbox13, Alert as Alert56, Paper as Paper19, Loader as Loader55, Badge as Badge46, ActionIcon as ActionIcon39, Divider as Divider30, NumberInput as NumberInput3 } from "@mantine/core";
33814
+ import React304, { useState as useState142, useCallback as useCallback112 } from "react";
33815
+ import { Modal as Modal4, Stack as Stack200, Text as Text175, TextInput as TextInput9, Button as Button58, Group as Group112, Radio as Radio5, Checkbox as Checkbox13, Alert as Alert56, Paper as Paper19, Loader as Loader55, Badge as Badge46, ActionIcon as ActionIcon39, Divider as Divider30, NumberInput as NumberInput3 } from "@mantine/core";
33653
33816
  import { IconSearch as IconSearch8, IconUser as IconUser15, IconRobot as IconRobot5, IconX as IconX14, IconShieldPlus as IconShieldPlus4 } from "@tabler/icons-react";
33654
33817
  var GrantPermissionModal = ({ opened, onClose, flowUri, blocks, targetBlockId, searchUsers, getOracles, onGrant }) => {
33655
33818
  const singleBlockMode = !!targetBlockId || blocks.length === 1;
33656
33819
  const fixedBlockId = targetBlockId || (blocks.length === 1 ? blocks[0].id : null);
33657
33820
  const fixedBlock = fixedBlockId ? blocks.find((b) => b.id === fixedBlockId) || blocks[0] : null;
33658
- const [recipientType, setRecipientType] = useState141("user");
33659
- const [searchQuery, setSearchQuery] = useState141("");
33660
- const [searchResults, setSearchResults] = useState141([]);
33661
- const [searching, setSearching] = useState141(false);
33662
- const [selectedRecipient, setSelectedRecipient] = useState141(null);
33663
- const [manualDid, setManualDid] = useState141("");
33664
- const [scopeType, setScopeType] = useState141("full");
33665
- const [selectedBlocks, setSelectedBlocks] = useState141([]);
33666
- const [expirationEnabled, setExpirationEnabled] = useState141(false);
33667
- const [expirationDays, setExpirationDays] = useState141(30);
33668
- const [canDelegate, setCanDelegate] = useState141(false);
33669
- const [pin, setPin] = useState141("");
33670
- const [loading, setLoading] = useState141(false);
33671
- const [error, setError] = useState141(null);
33821
+ const [recipientType, setRecipientType] = useState142("user");
33822
+ const [searchQuery, setSearchQuery] = useState142("");
33823
+ const [searchResults, setSearchResults] = useState142([]);
33824
+ const [searching, setSearching] = useState142(false);
33825
+ const [selectedRecipient, setSelectedRecipient] = useState142(null);
33826
+ const [manualDid, setManualDid] = useState142("");
33827
+ const [scopeType, setScopeType] = useState142("full");
33828
+ const [selectedBlocks, setSelectedBlocks] = useState142([]);
33829
+ const [expirationEnabled, setExpirationEnabled] = useState142(false);
33830
+ const [expirationDays, setExpirationDays] = useState142(30);
33831
+ const [canDelegate, setCanDelegate] = useState142(false);
33832
+ const [pin, setPin] = useState142("");
33833
+ const [loading, setLoading] = useState142(false);
33834
+ const [error, setError] = useState142(null);
33672
33835
  const handleSearch = useCallback112(async () => {
33673
33836
  if (searchQuery.length < 2) return;
33674
33837
  setSearching(true);
@@ -33756,15 +33919,15 @@ var GrantPermissionModal = ({ opened, onClose, flowUri, blocks, targetBlockId, s
33756
33919
  resetForm();
33757
33920
  }
33758
33921
  };
33759
- return /* @__PURE__ */ React303.createElement(
33922
+ return /* @__PURE__ */ React304.createElement(
33760
33923
  Modal4,
33761
33924
  {
33762
33925
  opened,
33763
33926
  onClose: handleClose,
33764
- title: /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, /* @__PURE__ */ React303.createElement(IconShieldPlus4, { size: 20 }), /* @__PURE__ */ React303.createElement(Text174, { fw: 600 }, "Grant Permission")),
33927
+ title: /* @__PURE__ */ React304.createElement(Group112, { gap: "xs" }, /* @__PURE__ */ React304.createElement(IconShieldPlus4, { size: 20 }), /* @__PURE__ */ React304.createElement(Text175, { fw: 600 }, "Grant Permission")),
33765
33928
  size: "lg"
33766
33929
  },
33767
- /* @__PURE__ */ React303.createElement(Stack200, { gap: "md" }, /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Text174, { size: "sm", fw: 500 }, "Recipient Type"), /* @__PURE__ */ React303.createElement(
33930
+ /* @__PURE__ */ React304.createElement(Stack200, { gap: "md" }, /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React304.createElement(Text175, { size: "sm", fw: 500 }, "Recipient Type"), /* @__PURE__ */ React304.createElement(
33768
33931
  Radio5.Group,
33769
33932
  {
33770
33933
  value: recipientType,
@@ -33774,23 +33937,23 @@ var GrantPermissionModal = ({ opened, onClose, flowUri, blocks, targetBlockId, s
33774
33937
  setSearchResults([]);
33775
33938
  }
33776
33939
  },
33777
- /* @__PURE__ */ React303.createElement(Group111, null, /* @__PURE__ */ React303.createElement(Radio5, { value: "user", label: "User" }), /* @__PURE__ */ React303.createElement(Radio5, { value: "oracle", label: "Oracle" }), /* @__PURE__ */ React303.createElement(Radio5, { value: "manual", label: "Enter DID" }))
33778
- )), recipientType !== "manual" ? /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React303.createElement(
33940
+ /* @__PURE__ */ React304.createElement(Group112, null, /* @__PURE__ */ React304.createElement(Radio5, { value: "user", label: "User" }), /* @__PURE__ */ React304.createElement(Radio5, { value: "oracle", label: "Oracle" }), /* @__PURE__ */ React304.createElement(Radio5, { value: "manual", label: "Enter DID" }))
33941
+ )), recipientType !== "manual" ? /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React304.createElement(
33779
33942
  TextInput9,
33780
33943
  {
33781
33944
  placeholder: recipientType === "oracle" ? "Search oracles..." : "Search users...",
33782
- leftSection: /* @__PURE__ */ React303.createElement(IconSearch8, { size: 16 }),
33783
- rightSection: searching ? /* @__PURE__ */ React303.createElement(Loader55, { size: 14 }) : null,
33945
+ leftSection: /* @__PURE__ */ React304.createElement(IconSearch8, { size: 16 }),
33946
+ rightSection: searching ? /* @__PURE__ */ React304.createElement(Loader55, { size: 14 }) : null,
33784
33947
  value: searchQuery,
33785
33948
  onChange: (e) => setSearchQuery(e.currentTarget.value),
33786
33949
  onKeyDown: (e) => e.key === "Enter" && handleSearch()
33787
33950
  }
33788
- ), selectedRecipient ? /* @__PURE__ */ React303.createElement(Paper19, { p: "sm", withBorder: true }, /* @__PURE__ */ React303.createElement(Group111, { justify: "space-between" }, /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, recipientType === "oracle" ? /* @__PURE__ */ React303.createElement(IconRobot5, { size: 16 }) : /* @__PURE__ */ React303.createElement(IconUser15, { size: 16 }), /* @__PURE__ */ React303.createElement(Text174, { size: "sm" }, selectedRecipient.displayName), /* @__PURE__ */ React303.createElement(Badge46, { size: "xs", variant: "light" }, selectedRecipient.did.slice(-12))), /* @__PURE__ */ React303.createElement(ActionIcon39, { size: "sm", variant: "subtle", onClick: () => setSelectedRecipient(null) }, /* @__PURE__ */ React303.createElement(IconX14, { size: 14 })))) : searchResults.length > 0 ? /* @__PURE__ */ React303.createElement(Paper19, { p: "xs", withBorder: true, style: { maxHeight: 150, overflow: "auto" } }, /* @__PURE__ */ React303.createElement(Stack200, { gap: 4 }, searchResults.map((result) => /* @__PURE__ */ React303.createElement(Button59, { key: result.did, variant: "subtle", size: "sm", justify: "flex-start", onClick: () => setSelectedRecipient(result) }, result.displayName)))) : null) : /* @__PURE__ */ React303.createElement(TextInput9, { label: "Recipient DID", placeholder: "did:ixo:...", value: manualDid, onChange: (e) => setManualDid(e.currentTarget.value) }), /* @__PURE__ */ React303.createElement(Divider30, null), /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Text174, { size: "sm", fw: 500 }, "Permission Scope"), singleBlockMode && fixedBlock ? (
33951
+ ), selectedRecipient ? /* @__PURE__ */ React304.createElement(Paper19, { p: "sm", withBorder: true }, /* @__PURE__ */ React304.createElement(Group112, { justify: "space-between" }, /* @__PURE__ */ React304.createElement(Group112, { gap: "xs" }, recipientType === "oracle" ? /* @__PURE__ */ React304.createElement(IconRobot5, { size: 16 }) : /* @__PURE__ */ React304.createElement(IconUser15, { size: 16 }), /* @__PURE__ */ React304.createElement(Text175, { size: "sm" }, selectedRecipient.displayName), /* @__PURE__ */ React304.createElement(Badge46, { size: "xs", variant: "light" }, selectedRecipient.did.slice(-12))), /* @__PURE__ */ React304.createElement(ActionIcon39, { size: "sm", variant: "subtle", onClick: () => setSelectedRecipient(null) }, /* @__PURE__ */ React304.createElement(IconX14, { size: 14 })))) : searchResults.length > 0 ? /* @__PURE__ */ React304.createElement(Paper19, { p: "xs", withBorder: true, style: { maxHeight: 150, overflow: "auto" } }, /* @__PURE__ */ React304.createElement(Stack200, { gap: 4 }, searchResults.map((result) => /* @__PURE__ */ React304.createElement(Button58, { key: result.did, variant: "subtle", size: "sm", justify: "flex-start", onClick: () => setSelectedRecipient(result) }, result.displayName)))) : null) : /* @__PURE__ */ React304.createElement(TextInput9, { label: "Recipient DID", placeholder: "did:ixo:...", value: manualDid, onChange: (e) => setManualDid(e.currentTarget.value) }), /* @__PURE__ */ React304.createElement(Divider30, null), /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React304.createElement(Text175, { size: "sm", fw: 500 }, "Permission Scope"), singleBlockMode && fixedBlock ? (
33789
33952
  // Single block mode: show fixed block info
33790
- /* @__PURE__ */ React303.createElement(Paper19, { p: "sm", withBorder: true }, /* @__PURE__ */ React303.createElement(Group111, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Badge46, { variant: "light", color: "blue" }, fixedBlock.type), /* @__PURE__ */ React303.createElement(Text174, { size: "sm" }, fixedBlock.name || `Block ${fixedBlock.id.slice(-8)}`)), /* @__PURE__ */ React303.createElement(Text174, { size: "xs", c: "dimmed", mt: "xs" }, "Permission will be granted to execute this specific block."))
33953
+ /* @__PURE__ */ React304.createElement(Paper19, { p: "sm", withBorder: true }, /* @__PURE__ */ React304.createElement(Group112, { gap: "xs" }, /* @__PURE__ */ React304.createElement(Badge46, { variant: "light", color: "blue" }, fixedBlock.type), /* @__PURE__ */ React304.createElement(Text175, { size: "sm" }, fixedBlock.name || `Block ${fixedBlock.id.slice(-8)}`)), /* @__PURE__ */ React304.createElement(Text175, { size: "xs", c: "dimmed", mt: "xs" }, "Permission will be granted to execute this specific block."))
33791
33954
  ) : (
33792
33955
  // Multi-block mode: show scope selection
33793
- /* @__PURE__ */ React303.createElement(React303.Fragment, null, /* @__PURE__ */ React303.createElement(Radio5.Group, { value: scopeType, onChange: (v) => setScopeType(v) }, /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Radio5, { value: "full", label: "Full flow access (can execute any block)" }), /* @__PURE__ */ React303.createElement(Radio5, { value: "blocks", label: "Specific blocks only" }))), scopeType === "blocks" && /* @__PURE__ */ React303.createElement(Paper19, { p: "sm", withBorder: true, style: { maxHeight: 150, overflow: "auto" } }, /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, blocks.map((block) => /* @__PURE__ */ React303.createElement(
33956
+ /* @__PURE__ */ React304.createElement(React304.Fragment, null, /* @__PURE__ */ React304.createElement(Radio5.Group, { value: scopeType, onChange: (v) => setScopeType(v) }, /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React304.createElement(Radio5, { value: "full", label: "Full flow access (can execute any block)" }), /* @__PURE__ */ React304.createElement(Radio5, { value: "blocks", label: "Specific blocks only" }))), scopeType === "blocks" && /* @__PURE__ */ React304.createElement(Paper19, { p: "sm", withBorder: true, style: { maxHeight: 150, overflow: "auto" } }, /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, blocks.map((block) => /* @__PURE__ */ React304.createElement(
33794
33957
  Checkbox13,
33795
33958
  {
33796
33959
  key: block.id,
@@ -33805,7 +33968,7 @@ var GrantPermissionModal = ({ opened, onClose, flowUri, blocks, targetBlockId, s
33805
33968
  }
33806
33969
  }
33807
33970
  )))))
33808
- )), /* @__PURE__ */ React303.createElement(Divider30, null), /* @__PURE__ */ React303.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React303.createElement(Checkbox13, { label: "Set expiration", checked: expirationEnabled, onChange: (e) => setExpirationEnabled(e.currentTarget.checked) }), expirationEnabled && /* @__PURE__ */ React303.createElement(NumberInput3, { label: "Expires in (days)", placeholder: "30", value: expirationDays, onChange: setExpirationDays, min: 1, max: 365 })), /* @__PURE__ */ React303.createElement(
33971
+ )), /* @__PURE__ */ React304.createElement(Divider30, null), /* @__PURE__ */ React304.createElement(Stack200, { gap: "xs" }, /* @__PURE__ */ React304.createElement(Checkbox13, { label: "Set expiration", checked: expirationEnabled, onChange: (e) => setExpirationEnabled(e.currentTarget.checked) }), expirationEnabled && /* @__PURE__ */ React304.createElement(NumberInput3, { label: "Expires in (days)", placeholder: "30", value: expirationDays, onChange: setExpirationDays, min: 1, max: 365 })), /* @__PURE__ */ React304.createElement(
33809
33972
  Checkbox13,
33810
33973
  {
33811
33974
  label: "Recipient can grant permissions to others",
@@ -33813,7 +33976,7 @@ var GrantPermissionModal = ({ opened, onClose, flowUri, blocks, targetBlockId, s
33813
33976
  checked: canDelegate,
33814
33977
  onChange: (e) => setCanDelegate(e.currentTarget.checked)
33815
33978
  }
33816
- ), /* @__PURE__ */ React303.createElement(Divider30, null), /* @__PURE__ */ React303.createElement(TextInput9, { label: "Enter your PIN to sign this delegation", type: "password", placeholder: "PIN", value: pin, onChange: (e) => setPin(e.currentTarget.value) }), error && /* @__PURE__ */ React303.createElement(Alert56, { color: "red" }, error), /* @__PURE__ */ React303.createElement(Group111, { justify: "flex-end" }, /* @__PURE__ */ React303.createElement(Button59, { variant: "subtle", onClick: handleClose, disabled: loading }, "Cancel"), /* @__PURE__ */ React303.createElement(Button59, { onClick: handleGrant, loading }, "Grant Permission")))
33979
+ ), /* @__PURE__ */ React304.createElement(Divider30, null), /* @__PURE__ */ React304.createElement(TextInput9, { label: "Enter your PIN to sign this delegation", type: "password", placeholder: "PIN", value: pin, onChange: (e) => setPin(e.currentTarget.value) }), error && /* @__PURE__ */ React304.createElement(Alert56, { color: "red" }, error), /* @__PURE__ */ React304.createElement(Group112, { justify: "flex-end" }, /* @__PURE__ */ React304.createElement(Button58, { variant: "subtle", onClick: handleClose, disabled: loading }, "Cancel"), /* @__PURE__ */ React304.createElement(Button58, { onClick: handleGrant, loading }, "Grant Permission")))
33817
33980
  );
33818
33981
  };
33819
33982
 
@@ -33905,10 +34068,11 @@ export {
33905
34068
  useCreateCollaborativeIxoEditor,
33906
34069
  BaseIconPicker,
33907
34070
  CoverImage,
33908
- PageHeader,
34071
+ PageTitle,
33909
34072
  ExternalDropZone,
33910
34073
  IxoEditor,
33911
34074
  DebugButton,
34075
+ PageHeader,
33912
34076
  EvaluationTab,
33913
34077
  EntitySigningSetup,
33914
34078
  FlowPermissionsPanel,
@@ -33926,4 +34090,4 @@ export {
33926
34090
  getExtraSlashMenuItems,
33927
34091
  useCreateIxoEditor
33928
34092
  };
33929
- //# sourceMappingURL=chunk-UWTEHXWI.mjs.map
34093
+ //# sourceMappingURL=chunk-3MI2QQYH.mjs.map