@calimero-network/mero-react 4.2.0 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.cjs +22 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -10
- package/dist/index.d.ts +24 -10
- package/dist/index.js +22 -130
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -292,7 +292,7 @@ Helpers: `defaultMeroTheme` (the full default palette), `resolveMeroTheme(partia
|
|
|
292
292
|
|
|
293
293
|
| Prop | Type | Default | Notes |
|
|
294
294
|
|------|------|---------|-------|
|
|
295
|
-
| `connectionType` | `ConnectionType \| CustomConnectionConfig` | `
|
|
295
|
+
| `connectionType` | `ConnectionType \| CustomConnectionConfig` | `Remote` | `Custom` connects straight to the given URL, skipping the modal. Every other value opens the LoginModal (node discovery + manual URL entry). |
|
|
296
296
|
| `theme` | `MeroTheme` | — | Partial token override. |
|
|
297
297
|
| `logoOnly` | `boolean` | `false` | Render only the Calimero logo (square button). The label is still announced via `aria-label`. |
|
|
298
298
|
| `label` | `string \| { connect?, connected?, reconnecting? }` | — | Override default labels. Bare string targets the disconnected state. |
|
|
@@ -305,10 +305,10 @@ AppMode.SingleContext // 'single-context'
|
|
|
305
305
|
AppMode.MultiContext // 'multi-context'
|
|
306
306
|
AppMode.Admin // 'admin'
|
|
307
307
|
|
|
308
|
-
ConnectionType.
|
|
309
|
-
ConnectionType.
|
|
310
|
-
ConnectionType.
|
|
311
|
-
ConnectionType.
|
|
308
|
+
ConnectionType.Remote // 'remote' — opens the LoginModal (discovery + manual URL)
|
|
309
|
+
ConnectionType.Custom // 'custom' — skip the modal, connect to a fixed URL
|
|
310
|
+
ConnectionType.RemoteAndLocal // deprecated, same as Remote
|
|
311
|
+
ConnectionType.Local // deprecated, same as Remote
|
|
312
312
|
```
|
|
313
313
|
|
|
314
314
|
## Types
|
package/dist/index.cjs
CHANGED
|
@@ -200,9 +200,18 @@ var isBrowser = typeof window !== "undefined";
|
|
|
200
200
|
function getPermissionsForMode(mode) {
|
|
201
201
|
switch (mode) {
|
|
202
202
|
case "single-context" /* SingleContext */:
|
|
203
|
-
return ["context:execute"];
|
|
203
|
+
return ["context:execute", "context:list", "application:list", "blob", "context:alias"];
|
|
204
204
|
case "multi-context" /* MultiContext */:
|
|
205
|
-
return [
|
|
205
|
+
return [
|
|
206
|
+
"context:create",
|
|
207
|
+
"context:list",
|
|
208
|
+
"context:execute",
|
|
209
|
+
"application:list",
|
|
210
|
+
"namespace",
|
|
211
|
+
"group",
|
|
212
|
+
"blob",
|
|
213
|
+
"context:alias"
|
|
214
|
+
];
|
|
206
215
|
case "admin" /* Admin */:
|
|
207
216
|
return ["admin"];
|
|
208
217
|
default:
|
|
@@ -579,7 +588,6 @@ function themeToCssVars(theme) {
|
|
|
579
588
|
function cssVar(theme, key) {
|
|
580
589
|
return `var(${MERO_CSS_VARS[key]}, ${theme[key]})`;
|
|
581
590
|
}
|
|
582
|
-
var DEFAULT_LOCAL_NODE_URL = "http://node1.127.0.0.1.nip.io";
|
|
583
591
|
var CUSTOM_SELECTION = "__custom__";
|
|
584
592
|
function isValidUrl(urlString) {
|
|
585
593
|
if (!urlString || urlString.trim() === "") {
|
|
@@ -697,29 +705,6 @@ function buildStyles(t) {
|
|
|
697
705
|
fontSize: "0.875rem",
|
|
698
706
|
textAlign: "center"
|
|
699
707
|
},
|
|
700
|
-
radioGroup: {
|
|
701
|
-
display: "flex",
|
|
702
|
-
gap: "0.75rem",
|
|
703
|
-
marginBottom: "1rem",
|
|
704
|
-
justifyContent: "center"
|
|
705
|
-
},
|
|
706
|
-
radioLabel: {
|
|
707
|
-
display: "flex",
|
|
708
|
-
alignItems: "center",
|
|
709
|
-
gap: "0.5rem",
|
|
710
|
-
color: text,
|
|
711
|
-
cursor: "pointer",
|
|
712
|
-
padding: "0.5rem 1rem",
|
|
713
|
-
borderRadius: radius,
|
|
714
|
-
border: `1px solid ${border}`,
|
|
715
|
-
backgroundColor: bgSecondary,
|
|
716
|
-
transition: "all 0.15s ease"
|
|
717
|
-
},
|
|
718
|
-
radioLabelActive: {
|
|
719
|
-
border: `1px solid ${accent}`,
|
|
720
|
-
backgroundColor: accentGlow,
|
|
721
|
-
color: text
|
|
722
|
-
},
|
|
723
708
|
radioList: {
|
|
724
709
|
display: "flex",
|
|
725
710
|
flexDirection: "column",
|
|
@@ -782,29 +767,6 @@ function buildStyles(t) {
|
|
|
782
767
|
marginBottom: "1rem",
|
|
783
768
|
boxSizing: "border-box"
|
|
784
769
|
},
|
|
785
|
-
localInfo: {
|
|
786
|
-
color: textSecondary,
|
|
787
|
-
fontSize: "0.875rem",
|
|
788
|
-
textAlign: "center",
|
|
789
|
-
padding: "0.75rem",
|
|
790
|
-
backgroundColor: bgSecondary,
|
|
791
|
-
borderRadius: radius,
|
|
792
|
-
marginBottom: "1rem",
|
|
793
|
-
border: `1px solid ${border}`
|
|
794
|
-
},
|
|
795
|
-
localInfoCode: {
|
|
796
|
-
color: accent
|
|
797
|
-
},
|
|
798
|
-
noNodeInfo: {
|
|
799
|
-
color: textSecondary,
|
|
800
|
-
fontSize: "0.875rem",
|
|
801
|
-
textAlign: "center",
|
|
802
|
-
padding: "0.75rem",
|
|
803
|
-
backgroundColor: bgSecondary,
|
|
804
|
-
borderRadius: radius,
|
|
805
|
-
marginBottom: "1rem",
|
|
806
|
-
border: `1px solid ${border}`
|
|
807
|
-
},
|
|
808
770
|
toolbar: {
|
|
809
771
|
display: "flex",
|
|
810
772
|
justifyContent: "center",
|
|
@@ -875,12 +837,10 @@ function buildStyles(t) {
|
|
|
875
837
|
function LoginModal({
|
|
876
838
|
onConnect,
|
|
877
839
|
onClose,
|
|
878
|
-
connectionType,
|
|
879
840
|
isOpen,
|
|
880
841
|
theme,
|
|
881
842
|
localNodePorts = DEFAULT_LOCAL_NODE_PORTS
|
|
882
843
|
}) {
|
|
883
|
-
const [nodeType, setNodeType] = react.useState("local");
|
|
884
844
|
const [selected, setSelected] = react.useState(CUSTOM_SELECTION);
|
|
885
845
|
const [discovered, setDiscovered] = react.useState([]);
|
|
886
846
|
const [discovering, setDiscovering] = react.useState(false);
|
|
@@ -893,27 +853,16 @@ function LoginModal({
|
|
|
893
853
|
() => theme ? themeToCssVars(resolved) : void 0,
|
|
894
854
|
[theme, resolved]
|
|
895
855
|
);
|
|
896
|
-
const shouldShowLocal = connectionType === "remote-and-local" /* RemoteAndLocal */ || connectionType === "local" /* Local */;
|
|
897
|
-
const shouldShowRemote = connectionType === "remote-and-local" /* RemoteAndLocal */ || connectionType === "remote" /* Remote */;
|
|
898
|
-
const shouldShowRadioGroup = shouldShowLocal && shouldShowRemote;
|
|
899
856
|
react.useEffect(() => {
|
|
900
857
|
const savedUrl = localStorage.getItem("mero:node_url");
|
|
901
858
|
if (savedUrl) {
|
|
902
859
|
setCustomUrl(savedUrl);
|
|
903
860
|
}
|
|
904
861
|
}, []);
|
|
905
|
-
react.useEffect(() => {
|
|
906
|
-
if (connectionType === "local" /* Local */) {
|
|
907
|
-
setNodeType("local");
|
|
908
|
-
} else if (connectionType === "remote" /* Remote */) {
|
|
909
|
-
setNodeType("remote");
|
|
910
|
-
}
|
|
911
|
-
}, [connectionType]);
|
|
912
862
|
const [scanNonce, setScanNonce] = react.useState(0);
|
|
913
863
|
const portsKey = react.useMemo(() => localNodePorts.join(","), [localNodePorts]);
|
|
914
|
-
const remoteActive = isOpen && shouldShowRemote && nodeType === "remote";
|
|
915
864
|
react.useEffect(() => {
|
|
916
|
-
if (!
|
|
865
|
+
if (!isOpen) {
|
|
917
866
|
return;
|
|
918
867
|
}
|
|
919
868
|
const controller = new AbortController();
|
|
@@ -934,16 +883,16 @@ function LoginModal({
|
|
|
934
883
|
active = false;
|
|
935
884
|
controller.abort();
|
|
936
885
|
};
|
|
937
|
-
}, [
|
|
886
|
+
}, [isOpen, portsKey, scanNonce]);
|
|
938
887
|
const isCustom = selected === CUSTOM_SELECTION;
|
|
939
888
|
const hasDiscovered = discovered.length > 0;
|
|
940
|
-
const canConnect = !loading &&
|
|
889
|
+
const canConnect = !loading && !discovering && (isCustom ? isValidUrl(customUrl) : true);
|
|
941
890
|
const canConnectRef = react.useRef(canConnect);
|
|
942
891
|
canConnectRef.current = canConnect;
|
|
943
892
|
const handleConnect = react.useCallback(async () => {
|
|
944
|
-
const
|
|
945
|
-
const
|
|
946
|
-
if (
|
|
893
|
+
const usingDiscovered = selected !== CUSTOM_SELECTION;
|
|
894
|
+
const targetUrl = usingDiscovered ? selected : customUrl;
|
|
895
|
+
if (!usingDiscovered && !isValidUrl(targetUrl)) {
|
|
947
896
|
return;
|
|
948
897
|
}
|
|
949
898
|
const normalizedUrl = targetUrl.replace(/\/+$/, "");
|
|
@@ -968,7 +917,7 @@ function LoginModal({
|
|
|
968
917
|
setError("Failed to connect. Please check the URL and try again.");
|
|
969
918
|
setLoading(false);
|
|
970
919
|
}
|
|
971
|
-
}, [
|
|
920
|
+
}, [selected, customUrl, onConnect]);
|
|
972
921
|
if (!isOpen) {
|
|
973
922
|
return null;
|
|
974
923
|
}
|
|
@@ -1018,7 +967,7 @@ function LoginModal({
|
|
|
1018
967
|
)
|
|
1019
968
|
);
|
|
1020
969
|
};
|
|
1021
|
-
const
|
|
970
|
+
const renderNodeSection = () => {
|
|
1022
971
|
if (discovering) {
|
|
1023
972
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.discovering, "data-testid": "node-discovering", children: [
|
|
1024
973
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.spinnerSmall }),
|
|
@@ -1026,7 +975,7 @@ function LoginModal({
|
|
|
1026
975
|
] });
|
|
1027
976
|
}
|
|
1028
977
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1029
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.info, children: hasDiscovered ? "Select
|
|
978
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.info, children: hasDiscovered ? "Select your Calimero node to continue." : "No local node found. Enter a node URL to continue." }),
|
|
1030
979
|
hasDiscovered && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1031
980
|
"div",
|
|
1032
981
|
{
|
|
@@ -1086,64 +1035,8 @@ function LoginModal({
|
|
|
1086
1035
|
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Connecting to node..." }),
|
|
1087
1036
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.spinner })
|
|
1088
1037
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1089
|
-
shouldShowRadioGroup && /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.info, children: "Select your Calimero node type to continue." }),
|
|
1090
1038
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: styles.error, children: error }),
|
|
1091
|
-
|
|
1092
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1093
|
-
"label",
|
|
1094
|
-
{
|
|
1095
|
-
"data-testid": "node-type-local",
|
|
1096
|
-
style: {
|
|
1097
|
-
...styles.radioLabel,
|
|
1098
|
-
...nodeType === "local" ? styles.radioLabelActive : {}
|
|
1099
|
-
},
|
|
1100
|
-
onClick: () => setNodeType("local"),
|
|
1101
|
-
children: [
|
|
1102
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1103
|
-
"input",
|
|
1104
|
-
{
|
|
1105
|
-
type: "radio",
|
|
1106
|
-
value: "local",
|
|
1107
|
-
checked: nodeType === "local",
|
|
1108
|
-
onChange: () => setNodeType("local"),
|
|
1109
|
-
style: { display: "none" }
|
|
1110
|
-
}
|
|
1111
|
-
),
|
|
1112
|
-
"Local"
|
|
1113
|
-
]
|
|
1114
|
-
}
|
|
1115
|
-
),
|
|
1116
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1117
|
-
"label",
|
|
1118
|
-
{
|
|
1119
|
-
"data-testid": "node-type-remote",
|
|
1120
|
-
style: {
|
|
1121
|
-
...styles.radioLabel,
|
|
1122
|
-
...nodeType === "remote" ? styles.radioLabelActive : {}
|
|
1123
|
-
},
|
|
1124
|
-
onClick: () => setNodeType("remote"),
|
|
1125
|
-
children: [
|
|
1126
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1127
|
-
"input",
|
|
1128
|
-
{
|
|
1129
|
-
type: "radio",
|
|
1130
|
-
value: "remote",
|
|
1131
|
-
checked: nodeType === "remote",
|
|
1132
|
-
onChange: () => setNodeType("remote"),
|
|
1133
|
-
style: { display: "none" }
|
|
1134
|
-
}
|
|
1135
|
-
),
|
|
1136
|
-
"Remote"
|
|
1137
|
-
]
|
|
1138
|
-
}
|
|
1139
|
-
)
|
|
1140
|
-
] }),
|
|
1141
|
-
nodeType === "local" && shouldShowLocal && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles.localInfo, children: [
|
|
1142
|
-
"Using default local node: ",
|
|
1143
|
-
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
1144
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { style: styles.localInfoCode, children: DEFAULT_LOCAL_NODE_URL })
|
|
1145
|
-
] }),
|
|
1146
|
-
nodeType === "remote" && shouldShowRemote && renderRemoteView(),
|
|
1039
|
+
renderNodeSection(),
|
|
1147
1040
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.buttonGroup, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1148
1041
|
"button",
|
|
1149
1042
|
{
|
|
@@ -1163,7 +1056,7 @@ function LoginModal({
|
|
|
1163
1056
|
return reactDom.createPortal(modalContent, document.body);
|
|
1164
1057
|
}
|
|
1165
1058
|
function ConnectButton({
|
|
1166
|
-
connectionType = "remote
|
|
1059
|
+
connectionType = "remote" /* Remote */,
|
|
1167
1060
|
className,
|
|
1168
1061
|
style,
|
|
1169
1062
|
theme,
|
|
@@ -1314,7 +1207,6 @@ function ConnectButton({
|
|
|
1314
1207
|
isOpen: isModalOpen,
|
|
1315
1208
|
onConnect: handleModalConnect,
|
|
1316
1209
|
onClose: () => setIsModalOpen(false),
|
|
1317
|
-
connectionType: typeof connectionType === "object" ? "remote-and-local" /* RemoteAndLocal */ : connectionType,
|
|
1318
1210
|
theme: resolvedTheme ?? theme
|
|
1319
1211
|
}
|
|
1320
1212
|
)
|