@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/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { isNotEmpty, isEmpty, InitializationError, isMetaClassModule, isMetaFactoryModule, isFunctionModule, isObjectLikeModule, isFunction, mergeBlueprints, stoneBlueprint, classDecoratorLegacyWrapper, setMetadata, methodDecoratorLegacyWrapper, addMetadata, LIFECYCLE_HOOK_KEY, hasMetadata, getMetadata, isMatchedAdapter, Logger, addBlueprint } from '@stone-js/core';
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, useContext } from 'react';
5
- import { createRoot, hydrateRoot } from 'react-dom/client';
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, RedirectResponse, MetaStaticFileMiddleware, MetaCompressionMiddleware } from '@stone-js/http-core';
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
- * A class decorator for defining a class as a React Page route action.
1151
- * Uses the `Match` decorator internally to register the route with the HTTP `GET` method.
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
- * import { Page } from '@stone-js/use-react';
1159
- *
1160
- * @Page('/user-profile')
1161
- * class UserPage {
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 Page = (path, options = {}) => {
1173
- return classDecoratorLegacyWrapper((target, context) => {
1174
- setMetadata(context, REACT_PAGE_KEY, {
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
- * Hook decorator to mark a method as a lifecycle hook
1210
- * And automatically add it to the global lifecycle hook registry.
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
- * class MyClass {
1215
- * // ...
1216
- * @Hook('onPreparingPage')
1217
- * onPreparingPage () {}
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 Hook = (name) => {
1225
- return methodDecoratorLegacyWrapper((_target, context) => {
1226
- addMetadata(context, LIFECYCLE_HOOK_KEY, { name, method: context.name });
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
- * Decorator to create a snapshot of the current data.
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 name - The name of the snapshot.
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 { Service } from '@stone-js/core';
1268
- * import { Snapshot } from '@stone-js/use-react';
1101
+ * import { Page } from '@stone-js/use-react';
1269
1102
  *
1270
- * @Service({ alias: 'userService' })
1271
- * class UserService {
1272
- * @Snapshot()
1273
- * showProfile() {
1274
- * return { name: 'John Doe' };
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 Snapshot = (name) => {
1280
- return methodDecoratorLegacyWrapper((target, context) => {
1281
- return async function (...args) {
1282
- name = name ?? `${String(Object.getPrototypeOf(this).constructor.name)}.${String(context.name)}`;
1283
- return await ReactRuntime.instance?.snapshot(name, () => target.apply(this, args));
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
- * Sets the error handler for the React adapter and registers error pages.
1294
+ * Default blueprint for a React-based Stone.js application.
1421
1295
  *
1422
- * @param errorHandler - The error handler to set for the React adapter.
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
- function setUseReactAdapterErrorHandler(errorHandler, context) {
1427
- context
1428
- .blueprint
1429
- .set('stone.adapter.errorHandlers.default', { module: errorHandler, isClass: true });
1430
- context
1431
- .modules
1432
- .filter(module => hasMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY))
1433
- .forEach(module => {
1434
- const { error, layout, adapterAlias, platform } = getMetadata(module, REACT_ADAPTER_ERROR_PAGE_KEY, { error: 'default' });
1435
- if (isMatchedAdapter(context.blueprint, platform, adapterAlias)) {
1436
- Array(error).flat().forEach(name => {
1437
- context
1438
- .blueprint
1439
- .set(`stone.useReact.adapterErrorPages.${name}`, { isClass: true, layout, module });
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
- // Process both eager and lazy loaded error pages
1444
- Object
1445
- .keys(context.blueprint.get('stone.useReact.adapterErrorPages', {}))
1446
- .forEach((name) => {
1447
- context
1448
- .blueprint
1449
- .set(`stone.adapter.errorHandlers.${name}`, { module: errorHandler, isClass: true });
1450
- });
1451
- return context;
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
  /**