@stone-js/use-react 0.2.0 → 0.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/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/browser.js +172 -168
- package/dist/index.d.ts +273 -278
- package/dist/index.js +291 -287
- package/package.json +15 -15
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { isNotEmpty, isEmpty, InitializationError, isMetaClassModule, isMetaFactoryModule,
|
|
1
|
+
import { isNotEmpty, isEmpty, InitializationError, isMetaClassModule, isMetaFactoryModule, isObjectLikeModule, isFunction, isFunctionModule, classDecoratorLegacyWrapper, setMetadata, methodDecoratorLegacyWrapper, addMetadata, LIFECYCLE_HOOK_KEY, hasMetadata, getMetadata, isMatchedAdapter, mergeBlueprints, stoneBlueprint, Logger, addBlueprint } from '@stone-js/core';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { renderToString } from 'react-dom/server';
|
|
4
|
-
import { createContext, StrictMode, useState, useEffect
|
|
5
|
-
import {
|
|
4
|
+
import { createContext, StrictMode, useContext, useMemo, useState, useEffect } from 'react';
|
|
5
|
+
import { hydrateRoot, createRoot } from 'react-dom/client';
|
|
6
6
|
import { Config } from '@stone-js/config';
|
|
7
7
|
import { GET, NODE_CONSOLE_PLATFORM, Router, RouteEvent } from '@stone-js/router';
|
|
8
|
-
import { OutgoingHttpResponse,
|
|
8
|
+
import { RedirectResponse, OutgoingHttpResponse, MetaCompressionMiddleware, MetaStaticFileMiddleware } from '@stone-js/http-core';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Stone DOM Attribute.
|
|
@@ -912,167 +912,6 @@ class UseReactServiceProvider {
|
|
|
912
912
|
*/
|
|
913
913
|
const MetaUseReactServiceProvider = { module: UseReactServiceProvider, isClass: true };
|
|
914
914
|
|
|
915
|
-
/**
|
|
916
|
-
* Utility function to define an adapter error page.
|
|
917
|
-
*
|
|
918
|
-
* @param module - The adapter error page module.
|
|
919
|
-
* @param options - Optional adapter error page options.
|
|
920
|
-
* @returns The UseReactBlueprint.
|
|
921
|
-
*/
|
|
922
|
-
function defineAdapterErrorPage(module, options) {
|
|
923
|
-
const error = options?.error ?? 'default';
|
|
924
|
-
const adapterErrorPages = Object.fromEntries([error].flat().map((err) => [
|
|
925
|
-
err,
|
|
926
|
-
{
|
|
927
|
-
...options,
|
|
928
|
-
module,
|
|
929
|
-
error: err,
|
|
930
|
-
isFactory: options?.isClass !== true
|
|
931
|
-
}
|
|
932
|
-
]));
|
|
933
|
-
return {
|
|
934
|
-
stone: {
|
|
935
|
-
useReact: {
|
|
936
|
-
adapterErrorPages
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
};
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
* Default blueprint for a React-based Stone.js application.
|
|
944
|
-
*
|
|
945
|
-
* - Defines middleware, lifecycle hooks, and the default HTML template path.
|
|
946
|
-
*/
|
|
947
|
-
const internalUseReactBlueprint = {
|
|
948
|
-
stone: {
|
|
949
|
-
useReact: {},
|
|
950
|
-
services: [MetaReactRuntime],
|
|
951
|
-
providers: [MetaUseReactServiceProvider]
|
|
952
|
-
}
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
/**
|
|
956
|
-
* Defines a Stone React app using a factory-based or class-based main handler.
|
|
957
|
-
*
|
|
958
|
-
* @param moduleOrOptions - A factory function or class constructor for the main page.
|
|
959
|
-
* @param optionsOrBlueprints - Optional application-level configuration.
|
|
960
|
-
* @param maybeBlueprints - Additional blueprints to merge.
|
|
961
|
-
* @returns A fully merged Stone blueprint.
|
|
962
|
-
*/
|
|
963
|
-
function defineStoneReactApp(moduleOrOptions = {}, optionsOrBlueprints, maybeBlueprints) {
|
|
964
|
-
let module;
|
|
965
|
-
let options = {};
|
|
966
|
-
let blueprints = [];
|
|
967
|
-
// Pattern: defineStoneReactApp(handler, options?, blueprints?)
|
|
968
|
-
if (isFunctionModule(moduleOrOptions)) {
|
|
969
|
-
module = moduleOrOptions;
|
|
970
|
-
if (isObjectLikeModule(optionsOrBlueprints)) {
|
|
971
|
-
options = optionsOrBlueprints;
|
|
972
|
-
blueprints = Array.isArray(maybeBlueprints) ? maybeBlueprints : [];
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
else if (isObjectLikeModule(moduleOrOptions)) { // Pattern: defineStoneReactApp(options, blueprints?)
|
|
976
|
-
options = moduleOrOptions;
|
|
977
|
-
blueprints = Array.isArray(optionsOrBlueprints) ? optionsOrBlueprints : [];
|
|
978
|
-
}
|
|
979
|
-
const stonePart = {
|
|
980
|
-
...options,
|
|
981
|
-
useReact: {
|
|
982
|
-
...options.useReact
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
if (isNotEmpty(module)) {
|
|
986
|
-
stonePart.useReact.componentEventHandler = {
|
|
987
|
-
module,
|
|
988
|
-
isComponent: true,
|
|
989
|
-
isClass: options.isClass,
|
|
990
|
-
isFactory: options.isClass !== true
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
return mergeBlueprints(stoneBlueprint, internalUseReactBlueprint, ...blueprints, { stone: stonePart });
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
/**
|
|
997
|
-
* Utility function to define a page.
|
|
998
|
-
*
|
|
999
|
-
* @param module - The EventHandler module.
|
|
1000
|
-
* @param options - Page definition options.
|
|
1001
|
-
* @returns The UseReactBlueprint.
|
|
1002
|
-
*/
|
|
1003
|
-
function definePage(module, options) {
|
|
1004
|
-
return {
|
|
1005
|
-
stone: {
|
|
1006
|
-
router: {
|
|
1007
|
-
definitions: [
|
|
1008
|
-
{
|
|
1009
|
-
...options,
|
|
1010
|
-
method: GET,
|
|
1011
|
-
methods: [],
|
|
1012
|
-
children: undefined,
|
|
1013
|
-
handler: {
|
|
1014
|
-
module,
|
|
1015
|
-
isComponent: true,
|
|
1016
|
-
layout: options?.layout,
|
|
1017
|
-
isClass: options?.isClass,
|
|
1018
|
-
isFactory: options?.isClass !== true
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
]
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
};
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Utility function to define a page layout.
|
|
1028
|
-
*
|
|
1029
|
-
* @param module - The layout module.
|
|
1030
|
-
* @param options - Optional page layout definition options.
|
|
1031
|
-
* @returns The UseReactBlueprint.
|
|
1032
|
-
*/
|
|
1033
|
-
function definePageLayout(module, options) {
|
|
1034
|
-
const name = options?.name ?? 'default';
|
|
1035
|
-
return {
|
|
1036
|
-
stone: {
|
|
1037
|
-
useReact: {
|
|
1038
|
-
layout: {
|
|
1039
|
-
[name]: {
|
|
1040
|
-
module,
|
|
1041
|
-
isClass: options?.isClass,
|
|
1042
|
-
isFactory: options?.isClass !== true
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
/**
|
|
1050
|
-
* Utility function to define an error page.
|
|
1051
|
-
*
|
|
1052
|
-
* @param module - The layout module.
|
|
1053
|
-
* @param options - Optional page layout definition options.
|
|
1054
|
-
* @returns The UseReactBlueprint.
|
|
1055
|
-
*/
|
|
1056
|
-
function defineErrorPage(module, options) {
|
|
1057
|
-
const error = options?.error ?? 'default';
|
|
1058
|
-
const errorPages = Object.fromEntries([error].flat().map((err) => [
|
|
1059
|
-
err,
|
|
1060
|
-
{
|
|
1061
|
-
...options,
|
|
1062
|
-
module,
|
|
1063
|
-
error: err,
|
|
1064
|
-
isFactory: options?.isClass !== true
|
|
1065
|
-
}
|
|
1066
|
-
]));
|
|
1067
|
-
return {
|
|
1068
|
-
stone: {
|
|
1069
|
-
useReact: {
|
|
1070
|
-
errorPages
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
};
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
915
|
/**
|
|
1077
916
|
* Constants are defined here to prevent Circular dependency between modules
|
|
1078
917
|
* This pattern must be applied to all Stone libraries or third party libraries.
|
|
@@ -1147,37 +986,24 @@ const ErrorPage = (options) => {
|
|
|
1147
986
|
};
|
|
1148
987
|
|
|
1149
988
|
/**
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
* @param options - Configuration options for the route definition, excluding the `methods` property.
|
|
1154
|
-
* @returns A method decorator to be applied to a class method.
|
|
989
|
+
* Hook decorator to mark a method as a lifecycle hook
|
|
990
|
+
* And automatically add it to the global lifecycle hook registry.
|
|
1155
991
|
*
|
|
1156
992
|
* @example
|
|
1157
993
|
* ```typescript
|
|
1158
|
-
*
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
* handle({ event }): Record<string, string> {
|
|
1163
|
-
* return { name: 'Jane Doe' };
|
|
1164
|
-
* }
|
|
1165
|
-
*
|
|
1166
|
-
* render({ data }) {
|
|
1167
|
-
* return <h1>User name: {data.name}</h1>;
|
|
1168
|
-
* }
|
|
994
|
+
* class MyClass {
|
|
995
|
+
* // ...
|
|
996
|
+
* @Hook('onPreparingPage')
|
|
997
|
+
* onPreparingPage () {}
|
|
1169
998
|
* }
|
|
1170
999
|
* ```
|
|
1000
|
+
*
|
|
1001
|
+
* @param name - The name of the lifecycle hook.
|
|
1002
|
+
* @returns A class decorator function that sets the metadata using the provided options.
|
|
1171
1003
|
*/
|
|
1172
|
-
const
|
|
1173
|
-
return
|
|
1174
|
-
|
|
1175
|
-
...options,
|
|
1176
|
-
path,
|
|
1177
|
-
method: GET,
|
|
1178
|
-
methods: [],
|
|
1179
|
-
handler: { isClass: true, isComponent: true, layout: options.layout, module: target }
|
|
1180
|
-
});
|
|
1004
|
+
const Hook = (name) => {
|
|
1005
|
+
return methodDecoratorLegacyWrapper((_target, context) => {
|
|
1006
|
+
addMetadata(context, LIFECYCLE_HOOK_KEY, { name, method: context.name });
|
|
1181
1007
|
});
|
|
1182
1008
|
};
|
|
1183
1009
|
|
|
@@ -1206,24 +1032,31 @@ const PageLayout = (options) => {
|
|
|
1206
1032
|
};
|
|
1207
1033
|
|
|
1208
1034
|
/**
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1035
|
+
* Decorator to create a snapshot of the current data.
|
|
1036
|
+
*
|
|
1037
|
+
* @param name - The name of the snapshot.
|
|
1038
|
+
* @returns A method decorator.
|
|
1211
1039
|
*
|
|
1212
1040
|
* @example
|
|
1213
1041
|
* ```typescript
|
|
1214
|
-
*
|
|
1215
|
-
*
|
|
1216
|
-
*
|
|
1217
|
-
*
|
|
1042
|
+
* import { Service } from '@stone-js/core';
|
|
1043
|
+
* import { Snapshot } from '@stone-js/use-react';
|
|
1044
|
+
*
|
|
1045
|
+
* @Service({ alias: 'userService' })
|
|
1046
|
+
* class UserService {
|
|
1047
|
+
* @Snapshot()
|
|
1048
|
+
* showProfile() {
|
|
1049
|
+
* return { name: 'John Doe' };
|
|
1050
|
+
* }
|
|
1218
1051
|
* }
|
|
1219
1052
|
* ```
|
|
1220
|
-
*
|
|
1221
|
-
* @param name - The name of the lifecycle hook.
|
|
1222
|
-
* @returns A class decorator function that sets the metadata using the provided options.
|
|
1223
1053
|
*/
|
|
1224
|
-
const
|
|
1225
|
-
return methodDecoratorLegacyWrapper((
|
|
1226
|
-
|
|
1054
|
+
const Snapshot = (name) => {
|
|
1055
|
+
return methodDecoratorLegacyWrapper((target, context) => {
|
|
1056
|
+
return async function (...args) {
|
|
1057
|
+
name = name ?? `${String(Object.getPrototypeOf(this).constructor.name)}.${String(context.name)}`;
|
|
1058
|
+
return await ReactRuntime.instance?.snapshot(name, () => target.apply(this, args));
|
|
1059
|
+
};
|
|
1227
1060
|
});
|
|
1228
1061
|
};
|
|
1229
1062
|
|
|
@@ -1257,33 +1090,74 @@ const PageStatus = (statusCode = 200, headers = {}) => {
|
|
|
1257
1090
|
};
|
|
1258
1091
|
|
|
1259
1092
|
/**
|
|
1260
|
-
*
|
|
1093
|
+
* A class decorator for defining a class as a React Page route action.
|
|
1094
|
+
* Uses the `Match` decorator internally to register the route with the HTTP `GET` method.
|
|
1261
1095
|
*
|
|
1262
|
-
* @param
|
|
1263
|
-
* @returns A method decorator.
|
|
1096
|
+
* @param options - Configuration options for the route definition, excluding the `methods` property.
|
|
1097
|
+
* @returns A method decorator to be applied to a class method.
|
|
1264
1098
|
*
|
|
1265
1099
|
* @example
|
|
1266
1100
|
* ```typescript
|
|
1267
|
-
* import {
|
|
1268
|
-
* import { Snapshot } from '@stone-js/use-react';
|
|
1101
|
+
* import { Page } from '@stone-js/use-react';
|
|
1269
1102
|
*
|
|
1270
|
-
* @
|
|
1271
|
-
* class
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1103
|
+
* @Page('/user-profile')
|
|
1104
|
+
* class UserPage {
|
|
1105
|
+
* handle({ event }): Record<string, string> {
|
|
1106
|
+
* return { name: 'Jane Doe' };
|
|
1107
|
+
* }
|
|
1108
|
+
*
|
|
1109
|
+
* render({ data }) {
|
|
1110
|
+
* return <h1>User name: {data.name}</h1>;
|
|
1275
1111
|
* }
|
|
1276
1112
|
* }
|
|
1277
1113
|
* ```
|
|
1278
1114
|
*/
|
|
1279
|
-
const
|
|
1280
|
-
return
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1115
|
+
const Page = (path, options = {}) => {
|
|
1116
|
+
return classDecoratorLegacyWrapper((target, context) => {
|
|
1117
|
+
setMetadata(context, REACT_PAGE_KEY, {
|
|
1118
|
+
...options,
|
|
1119
|
+
path,
|
|
1120
|
+
method: GET,
|
|
1121
|
+
methods: [],
|
|
1122
|
+
handler: { isClass: true, isComponent: true, layout: options.layout, module: target }
|
|
1123
|
+
});
|
|
1124
|
+
});
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Sets the error handler for the React adapter and registers error pages.
|
|
1129
|
+
*
|
|
1130
|
+
* @param errorHandler - The error handler to set for the React adapter.
|
|
1131
|
+
* @param context - The blueprint context containing modules and blueprint.
|
|
1132
|
+
* @returns The updated blueprint context with the error handler and error pages set.
|
|
1133
|
+
*/
|
|
1134
|
+
function setUseReactAdapterErrorHandler(errorHandler, context) {
|
|
1135
|
+
context
|
|
1136
|
+
.blueprint
|
|
1137
|
+
.set('stone.adapter.errorHandlers.default', { module: errorHandler, isClass: true });
|
|
1138
|
+
context
|
|
1139
|
+
.modules
|
|
1140
|
+
.filter(module => hasMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY))
|
|
1141
|
+
.forEach(module => {
|
|
1142
|
+
const { error, layout, adapterAlias, platform } = getMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY, { error: 'default' });
|
|
1143
|
+
if (isMatchedAdapter(context.blueprint, platform, adapterAlias)) {
|
|
1144
|
+
Array(error).flat().forEach(name => {
|
|
1145
|
+
context
|
|
1146
|
+
.blueprint
|
|
1147
|
+
.set(`stone.useReact.adapterErrorPages.${name}`, { isClass: true, layout, module });
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1285
1150
|
});
|
|
1286
|
-
|
|
1151
|
+
// Process both eager and lazy loaded error pages
|
|
1152
|
+
Object
|
|
1153
|
+
.keys(context.blueprint.get('stone.useReact.adapterErrorPages', {}))
|
|
1154
|
+
.forEach((name) => {
|
|
1155
|
+
context
|
|
1156
|
+
.blueprint
|
|
1157
|
+
.set(`stone.adapter.errorHandlers.${name}`, { module: errorHandler, isClass: true });
|
|
1158
|
+
});
|
|
1159
|
+
return context;
|
|
1160
|
+
}
|
|
1287
1161
|
|
|
1288
1162
|
/**
|
|
1289
1163
|
* Blueprint middleware to dynamically set lifecycle hooks for react.
|
|
@@ -1417,38 +1291,164 @@ async function SetUseReactEventHandlerMiddleware(context, next) {
|
|
|
1417
1291
|
}
|
|
1418
1292
|
|
|
1419
1293
|
/**
|
|
1420
|
-
*
|
|
1294
|
+
* Default blueprint for a React-based Stone.js application.
|
|
1421
1295
|
*
|
|
1422
|
-
*
|
|
1423
|
-
* @param context - The blueprint context containing modules and blueprint.
|
|
1424
|
-
* @returns The updated blueprint context with the error handler and error pages set.
|
|
1296
|
+
* - Defines middleware, lifecycle hooks, and the default HTML template path.
|
|
1425
1297
|
*/
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1298
|
+
const internalUseReactBlueprint = {
|
|
1299
|
+
stone: {
|
|
1300
|
+
useReact: {},
|
|
1301
|
+
services: [MetaReactRuntime],
|
|
1302
|
+
providers: [MetaUseReactServiceProvider]
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Utility function to define an adapter error page.
|
|
1308
|
+
*
|
|
1309
|
+
* @param module - The adapter error page module.
|
|
1310
|
+
* @param options - Optional adapter error page options.
|
|
1311
|
+
* @returns The UseReactBlueprint.
|
|
1312
|
+
*/
|
|
1313
|
+
function defineAdapterErrorPage(module, options) {
|
|
1314
|
+
const error = options?.error ?? 'default';
|
|
1315
|
+
const adapterErrorPages = Object.fromEntries([error].flat().map((err) => [
|
|
1316
|
+
err,
|
|
1317
|
+
{
|
|
1318
|
+
...options,
|
|
1319
|
+
module,
|
|
1320
|
+
error: err,
|
|
1321
|
+
isFactory: options?.isClass !== true
|
|
1441
1322
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1323
|
+
]));
|
|
1324
|
+
return {
|
|
1325
|
+
stone: {
|
|
1326
|
+
useReact: {
|
|
1327
|
+
adapterErrorPages
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* Defines a Stone React app using a factory-based or class-based main handler.
|
|
1335
|
+
*
|
|
1336
|
+
* @param moduleOrOptions - A factory function or class constructor for the main page.
|
|
1337
|
+
* @param optionsOrBlueprints - Optional application-level configuration.
|
|
1338
|
+
* @param maybeBlueprints - Additional blueprints to merge.
|
|
1339
|
+
* @returns A fully merged Stone blueprint.
|
|
1340
|
+
*/
|
|
1341
|
+
function defineStoneReactApp(moduleOrOptions = {}, optionsOrBlueprints, maybeBlueprints) {
|
|
1342
|
+
let module;
|
|
1343
|
+
let options = {};
|
|
1344
|
+
let blueprints = [];
|
|
1345
|
+
// Pattern: defineStoneReactApp(handler, options?, blueprints?)
|
|
1346
|
+
if (isFunctionModule(moduleOrOptions)) {
|
|
1347
|
+
module = moduleOrOptions;
|
|
1348
|
+
if (isObjectLikeModule(optionsOrBlueprints)) {
|
|
1349
|
+
options = optionsOrBlueprints;
|
|
1350
|
+
blueprints = Array.isArray(maybeBlueprints) ? maybeBlueprints : [];
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
else if (isObjectLikeModule(moduleOrOptions)) { // Pattern: defineStoneReactApp(options, blueprints?)
|
|
1354
|
+
options = moduleOrOptions;
|
|
1355
|
+
blueprints = Array.isArray(optionsOrBlueprints) ? optionsOrBlueprints : [];
|
|
1356
|
+
}
|
|
1357
|
+
const stonePart = {
|
|
1358
|
+
...options,
|
|
1359
|
+
useReact: {
|
|
1360
|
+
...options.useReact
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
if (isNotEmpty(module)) {
|
|
1364
|
+
stonePart.useReact.componentEventHandler = {
|
|
1365
|
+
module,
|
|
1366
|
+
isComponent: true,
|
|
1367
|
+
isClass: options.isClass,
|
|
1368
|
+
isFactory: options.isClass !== true
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
return mergeBlueprints(stoneBlueprint, internalUseReactBlueprint, ...blueprints, { stone: stonePart });
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* Utility function to define a page.
|
|
1376
|
+
*
|
|
1377
|
+
* @param module - The EventHandler module.
|
|
1378
|
+
* @param options - Page definition options.
|
|
1379
|
+
* @returns The UseReactBlueprint.
|
|
1380
|
+
*/
|
|
1381
|
+
function definePage(module, options) {
|
|
1382
|
+
return {
|
|
1383
|
+
stone: {
|
|
1384
|
+
router: {
|
|
1385
|
+
definitions: [
|
|
1386
|
+
{
|
|
1387
|
+
...options,
|
|
1388
|
+
method: GET,
|
|
1389
|
+
methods: [],
|
|
1390
|
+
children: undefined,
|
|
1391
|
+
handler: {
|
|
1392
|
+
module,
|
|
1393
|
+
isComponent: true,
|
|
1394
|
+
layout: options?.layout,
|
|
1395
|
+
isClass: options?.isClass,
|
|
1396
|
+
isFactory: options?.isClass !== true
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
]
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Utility function to define a page layout.
|
|
1406
|
+
*
|
|
1407
|
+
* @param module - The layout module.
|
|
1408
|
+
* @param options - Optional page layout definition options.
|
|
1409
|
+
* @returns The UseReactBlueprint.
|
|
1410
|
+
*/
|
|
1411
|
+
function definePageLayout(module, options) {
|
|
1412
|
+
const name = options?.name ?? 'default';
|
|
1413
|
+
return {
|
|
1414
|
+
stone: {
|
|
1415
|
+
useReact: {
|
|
1416
|
+
layout: {
|
|
1417
|
+
[name]: {
|
|
1418
|
+
module,
|
|
1419
|
+
isClass: options?.isClass,
|
|
1420
|
+
isFactory: options?.isClass !== true
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Utility function to define an error page.
|
|
1429
|
+
*
|
|
1430
|
+
* @param module - The layout module.
|
|
1431
|
+
* @param options - Optional page layout definition options.
|
|
1432
|
+
* @returns The UseReactBlueprint.
|
|
1433
|
+
*/
|
|
1434
|
+
function defineErrorPage(module, options) {
|
|
1435
|
+
const error = options?.error ?? 'default';
|
|
1436
|
+
const errorPages = Object.fromEntries([error].flat().map((err) => [
|
|
1437
|
+
err,
|
|
1438
|
+
{
|
|
1439
|
+
...options,
|
|
1440
|
+
module,
|
|
1441
|
+
error: err,
|
|
1442
|
+
isFactory: options?.isClass !== true
|
|
1443
|
+
}
|
|
1444
|
+
]));
|
|
1445
|
+
return {
|
|
1446
|
+
stone: {
|
|
1447
|
+
useReact: {
|
|
1448
|
+
errorPages
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
1452
|
}
|
|
1453
1453
|
|
|
1454
1454
|
/**
|
|
@@ -1624,6 +1624,47 @@ const StoneClient = ({ children }) => {
|
|
|
1624
1624
|
return isClient() ? jsx(Fragment, { children: children }) : jsx(Fragment, {});
|
|
1625
1625
|
};
|
|
1626
1626
|
|
|
1627
|
+
/**
|
|
1628
|
+
* Internal link component using Stone.js router.
|
|
1629
|
+
*/
|
|
1630
|
+
const StoneLink = ({ to, href, noRel, external, children, ariaCurrentValue = 'page', selectedClass = 'selected', ...rest }) => {
|
|
1631
|
+
const isExternal = external === true;
|
|
1632
|
+
const shouldHandleNav = !isExternal && isNotEmpty(to);
|
|
1633
|
+
const router = useContext(StoneContext).container.resolve(Router);
|
|
1634
|
+
const path = useMemo(() => {
|
|
1635
|
+
return isObjectLikeModule(to) ? router.generate(to) : to ?? href ?? '#';
|
|
1636
|
+
}, [to, href, router]);
|
|
1637
|
+
const [currentRoute, setCurrentRoute] = useState(router.getCurrentRoute());
|
|
1638
|
+
const selectedClassName = currentRoute?.path === path ? selectedClass : undefined;
|
|
1639
|
+
const elemClassName = [rest.className, selectedClassName].filter(Boolean).join(' ').trim();
|
|
1640
|
+
const handleClick = (event) => {
|
|
1641
|
+
rest.onClick?.(event);
|
|
1642
|
+
if (event.defaultPrevented || isExternal)
|
|
1643
|
+
return;
|
|
1644
|
+
event.preventDefault();
|
|
1645
|
+
isNotEmpty(to) && router.navigate(to);
|
|
1646
|
+
};
|
|
1647
|
+
if (isEmpty(to) && isEmpty(href)) {
|
|
1648
|
+
Logger.warn('StoneLink: missing "to" or "href"');
|
|
1649
|
+
}
|
|
1650
|
+
useEffect(() => {
|
|
1651
|
+
const routerEventHandler = (event) => {
|
|
1652
|
+
setCurrentRoute(event.get('route'));
|
|
1653
|
+
};
|
|
1654
|
+
router.on(RouteEvent.ROUTED, routerEventHandler);
|
|
1655
|
+
return () => {
|
|
1656
|
+
router.off(RouteEvent.ROUTED, routerEventHandler);
|
|
1657
|
+
};
|
|
1658
|
+
}, [router]);
|
|
1659
|
+
return (
|
|
1660
|
+
// eslint-disable-next-line react/jsx-no-target-blank
|
|
1661
|
+
jsx("a", { ...rest, href: path, className: elemClassName, target: isExternal ? '_blank' : rest.target, "aria-current": isNotEmpty(selectedClassName) ? ariaCurrentValue : undefined, rel: noRel === true
|
|
1662
|
+
? undefined
|
|
1663
|
+
: isExternal
|
|
1664
|
+
? 'noopener noreferrer'
|
|
1665
|
+
: rest.rel, onClick: shouldHandleNav ? handleClick : rest.onClick, children: children }));
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1627
1668
|
/**
|
|
1628
1669
|
* A dynamic rendering component that updates its content based on a global event.
|
|
1629
1670
|
*
|
|
@@ -1636,7 +1677,7 @@ const StoneClient = ({ children }) => {
|
|
|
1636
1677
|
* @param options - The options to create the Stone Outlet.
|
|
1637
1678
|
* @returns The Stone Outlet component.
|
|
1638
1679
|
*/
|
|
1639
|
-
const StoneOutlet = ({ children }) => {
|
|
1680
|
+
const StoneOutlet = ({ children, ...rest }) => {
|
|
1640
1681
|
const [currentView, setCurrentView] = useState(children);
|
|
1641
1682
|
useEffect(() => {
|
|
1642
1683
|
const eventName = STONE_PAGE_EVENT_OUTLET;
|
|
@@ -1648,44 +1689,7 @@ const StoneOutlet = ({ children }) => {
|
|
|
1648
1689
|
window.addEventListener(eventName, handleEvent);
|
|
1649
1690
|
return () => window.removeEventListener(eventName, handleEvent);
|
|
1650
1691
|
}, []);
|
|
1651
|
-
return jsx("div", { "data-stone-outlet": 'true', children: currentView });
|
|
1652
|
-
};
|
|
1653
|
-
|
|
1654
|
-
/**
|
|
1655
|
-
* Internal link component using Stone.js router.
|
|
1656
|
-
*/
|
|
1657
|
-
const InternalLink = ({ to, href, noRel, children, className, defaultNav, selectedClass = 'selected', ariaCurrentValue = 'page', rel = 'noopener noreferrer' }) => {
|
|
1658
|
-
const router = useContext(StoneContext).container.resolve(Router);
|
|
1659
|
-
const path = isObjectLikeModule(to) ? router.generate(to) : to ?? href;
|
|
1660
|
-
const [currentRoute, setCurrentRoute] = useState(router.getCurrentRoute());
|
|
1661
|
-
const selectedClassName = currentRoute?.path === path ? selectedClass : undefined;
|
|
1662
|
-
const elemClassName = [className, selectedClassName].filter(Boolean).join(' ').trim();
|
|
1663
|
-
const handleClick = (event) => {
|
|
1664
|
-
event.preventDefault();
|
|
1665
|
-
router.navigate(to ?? '');
|
|
1666
|
-
};
|
|
1667
|
-
useEffect(() => {
|
|
1668
|
-
const routerEventHandler = (event) => {
|
|
1669
|
-
setCurrentRoute(event.get('route'));
|
|
1670
|
-
};
|
|
1671
|
-
router.on(RouteEvent.ROUTED, routerEventHandler);
|
|
1672
|
-
return () => {
|
|
1673
|
-
router.off(RouteEvent.ROUTED, routerEventHandler);
|
|
1674
|
-
};
|
|
1675
|
-
}, [router]);
|
|
1676
|
-
return defaultNav === true
|
|
1677
|
-
? (jsx("a", { href: path, className: elemClassName, "aria-current": ariaCurrentValue, rel: noRel !== undefined ? undefined : rel, children: children }))
|
|
1678
|
-
: (jsx("button", { onClick: handleClick, className: elemClassName, "aria-current": ariaCurrentValue, rel: noRel !== undefined ? undefined : rel, children: children }));
|
|
1679
|
-
};
|
|
1680
|
-
/**
|
|
1681
|
-
* External link component rendering a regular <a> tag.
|
|
1682
|
-
*/
|
|
1683
|
-
const ExternalLink = ({ to, href, noRel, target, children, className, ariaCurrentValue = 'page', rel = 'noopener noreferrer' }) => (jsx("a", { target: target, className: className, "aria-current": ariaCurrentValue, rel: noRel !== undefined ? undefined : rel, href: typeof to === 'string' ? to : href, children: children }));
|
|
1684
|
-
/**
|
|
1685
|
-
* Main StoneLink component delegating to internal or external versions.
|
|
1686
|
-
*/
|
|
1687
|
-
const StoneLink = (props) => {
|
|
1688
|
-
return props.external === true ? jsx(ExternalLink, { ...props }) : jsx(InternalLink, { ...props });
|
|
1692
|
+
return jsx("div", { ...rest, "data-stone-outlet": 'true', children: currentView });
|
|
1689
1693
|
};
|
|
1690
1694
|
|
|
1691
1695
|
/**
|