@alepha/react 0.9.2 → 0.9.3
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.browser.js +136 -78
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +159 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -158
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +230 -156
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +160 -87
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
- package/src/components/ErrorViewer.tsx +1 -1
- package/src/components/Link.tsx +4 -24
- package/src/components/NestedView.tsx +11 -2
- package/src/components/NotFound.tsx +4 -1
- package/src/descriptors/$page.ts +71 -9
- package/src/errors/{RedirectionError.ts → Redirection.ts} +1 -1
- package/src/hooks/RouterHookApi.ts +35 -11
- package/src/hooks/useActive.ts +22 -15
- package/src/hooks/useClient.ts +2 -0
- package/src/hooks/useRouter.ts +2 -1
- package/src/hooks/useRouterEvents.ts +5 -2
- package/src/hooks/useStore.ts +9 -1
- package/src/index.shared.ts +2 -2
- package/src/providers/BrowserRouterProvider.ts +9 -0
- package/src/providers/PageDescriptorProvider.ts +111 -31
- package/src/providers/ReactBrowserProvider.ts +17 -11
- package/src/providers/ReactServerProvider.ts +47 -10
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,12 @@ const $page = (options) => {
|
|
|
41
41
|
return (0, __alepha_core.createDescriptor)(PageDescriptor, options);
|
|
42
42
|
};
|
|
43
43
|
var PageDescriptor = class extends __alepha_core.Descriptor {
|
|
44
|
+
onInit() {
|
|
45
|
+
if (this.options.static) this.options.cache ??= {
|
|
46
|
+
provider: "memory",
|
|
47
|
+
ttl: [1, "week"]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
44
50
|
get name() {
|
|
45
51
|
return this.options.name ?? this.config.propertyKey;
|
|
46
52
|
}
|
|
@@ -49,7 +55,7 @@ var PageDescriptor = class extends __alepha_core.Descriptor {
|
|
|
49
55
|
* Only valid for server-side rendering, it will throw an error if called on the client-side.
|
|
50
56
|
*/
|
|
51
57
|
async render(options) {
|
|
52
|
-
throw new
|
|
58
|
+
throw new Error("render method is not implemented in this environment");
|
|
53
59
|
}
|
|
54
60
|
};
|
|
55
61
|
$page[__alepha_core.KIND] = PageDescriptor;
|
|
@@ -103,7 +109,7 @@ const ErrorViewer = ({ error, alepha }) => {
|
|
|
103
109
|
heading: {
|
|
104
110
|
fontSize: "20px",
|
|
105
111
|
fontWeight: "bold",
|
|
106
|
-
marginBottom: "
|
|
112
|
+
marginBottom: "10px"
|
|
107
113
|
},
|
|
108
114
|
name: {
|
|
109
115
|
fontSize: "16px",
|
|
@@ -320,13 +326,16 @@ const NestedView = (props) => {
|
|
|
320
326
|
const layer = (0, react.useContext)(RouterLayerContext);
|
|
321
327
|
const index = layer?.index ?? 0;
|
|
322
328
|
const [view, setView] = (0, react.useState)(app?.state.layers[index]?.element);
|
|
323
|
-
useRouterEvents({ onEnd: ({ state }) => {
|
|
329
|
+
useRouterEvents({ onEnd: ({ state, context }) => {
|
|
330
|
+
if (app) app.context = context;
|
|
324
331
|
if (!state.layers[index]?.cache) setView(state.layers[index]?.element);
|
|
325
332
|
} }, [app]);
|
|
326
333
|
if (!app) throw new Error("NestedView must be used within a RouterContext.");
|
|
327
334
|
const element = view ?? props.children ?? null;
|
|
328
335
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBoundary_default, {
|
|
329
|
-
fallback:
|
|
336
|
+
fallback: (error) => {
|
|
337
|
+
return app.context.onError?.(error, app.context);
|
|
338
|
+
},
|
|
330
339
|
children: element
|
|
331
340
|
});
|
|
332
341
|
};
|
|
@@ -334,7 +343,7 @@ var NestedView_default = NestedView;
|
|
|
334
343
|
|
|
335
344
|
//#endregion
|
|
336
345
|
//#region src/components/NotFound.tsx
|
|
337
|
-
function NotFoundPage() {
|
|
346
|
+
function NotFoundPage(props) {
|
|
338
347
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
339
348
|
style: {
|
|
340
349
|
height: "100vh",
|
|
@@ -344,7 +353,8 @@ function NotFoundPage() {
|
|
|
344
353
|
alignItems: "center",
|
|
345
354
|
textAlign: "center",
|
|
346
355
|
fontFamily: "sans-serif",
|
|
347
|
-
padding: "1rem"
|
|
356
|
+
padding: "1rem",
|
|
357
|
+
...props.style
|
|
348
358
|
},
|
|
349
359
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
350
360
|
style: {
|
|
@@ -357,8 +367,8 @@ function NotFoundPage() {
|
|
|
357
367
|
}
|
|
358
368
|
|
|
359
369
|
//#endregion
|
|
360
|
-
//#region src/errors/
|
|
361
|
-
var
|
|
370
|
+
//#region src/errors/Redirection.ts
|
|
371
|
+
var Redirection = class extends Error {
|
|
362
372
|
page;
|
|
363
373
|
constructor(page) {
|
|
364
374
|
super("Redirection");
|
|
@@ -381,7 +391,7 @@ var PageDescriptorProvider = class {
|
|
|
381
391
|
for (const page of this.pages) if (page.name === name) return page;
|
|
382
392
|
throw new Error(`Page ${name} not found`);
|
|
383
393
|
}
|
|
384
|
-
|
|
394
|
+
pathname(name, options = {}) {
|
|
385
395
|
const page = this.page(name);
|
|
386
396
|
if (!page) throw new Error(`Page ${name} not found`);
|
|
387
397
|
let url = page.path ?? "";
|
|
@@ -391,7 +401,14 @@ var PageDescriptorProvider = class {
|
|
|
391
401
|
parent = parent.parent;
|
|
392
402
|
}
|
|
393
403
|
url = this.compile(url, options.params ?? {});
|
|
394
|
-
|
|
404
|
+
if (options.query) {
|
|
405
|
+
const query = new URLSearchParams(options.query);
|
|
406
|
+
if (query.toString()) url += `?${query.toString()}`;
|
|
407
|
+
}
|
|
408
|
+
return url.replace(/\/\/+/g, "/") || "/";
|
|
409
|
+
}
|
|
410
|
+
url(name, options = {}) {
|
|
411
|
+
return new URL(this.pathname(name, options), options.base ?? `http://localhost`);
|
|
395
412
|
}
|
|
396
413
|
root(state, context) {
|
|
397
414
|
const root = (0, react.createElement)(AlephaContext.Provider, { value: this.alepha }, (0, react.createElement)(RouterContext.Provider, { value: {
|
|
@@ -466,12 +483,10 @@ var PageDescriptorProvider = class {
|
|
|
466
483
|
...props
|
|
467
484
|
};
|
|
468
485
|
} catch (e) {
|
|
469
|
-
if (e instanceof
|
|
470
|
-
layers: [],
|
|
471
|
-
redirect: typeof e.page === "string" ? e.page : this.href(e.page),
|
|
486
|
+
if (e instanceof Redirection) return this.createRedirectionLayer(e.page, {
|
|
472
487
|
pathname,
|
|
473
488
|
search
|
|
474
|
-
};
|
|
489
|
+
});
|
|
475
490
|
this.log.error(e);
|
|
476
491
|
it.error = e;
|
|
477
492
|
break;
|
|
@@ -487,9 +502,21 @@ var PageDescriptorProvider = class {
|
|
|
487
502
|
acc += it.route.path ? this.compile(it.route.path, params) : "";
|
|
488
503
|
const path = acc.replace(/\/+/, "/");
|
|
489
504
|
const localErrorHandler = this.getErrorHandler(it.route);
|
|
490
|
-
if (localErrorHandler)
|
|
491
|
-
|
|
492
|
-
|
|
505
|
+
if (localErrorHandler) {
|
|
506
|
+
const onErrorParent = request.onError;
|
|
507
|
+
request.onError = (error, context$1) => {
|
|
508
|
+
const result = localErrorHandler(error, context$1);
|
|
509
|
+
if (result === void 0) return onErrorParent(error, context$1);
|
|
510
|
+
return result;
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (it.error) try {
|
|
514
|
+
let element$1 = await request.onError(it.error, request);
|
|
515
|
+
if (element$1 === void 0) throw it.error;
|
|
516
|
+
if (element$1 instanceof Redirection) return this.createRedirectionLayer(element$1.page, {
|
|
517
|
+
pathname,
|
|
518
|
+
search
|
|
519
|
+
});
|
|
493
520
|
if (element$1 === null) element$1 = this.renderError(it.error);
|
|
494
521
|
layers.push({
|
|
495
522
|
props,
|
|
@@ -503,6 +530,12 @@ var PageDescriptorProvider = class {
|
|
|
503
530
|
route: it.route
|
|
504
531
|
});
|
|
505
532
|
break;
|
|
533
|
+
} catch (e) {
|
|
534
|
+
if (e instanceof Redirection) return this.createRedirectionLayer(e.page, {
|
|
535
|
+
pathname,
|
|
536
|
+
search
|
|
537
|
+
});
|
|
538
|
+
throw e;
|
|
506
539
|
}
|
|
507
540
|
const element = await this.createElement(it.route, {
|
|
508
541
|
...props,
|
|
@@ -526,6 +559,14 @@ var PageDescriptorProvider = class {
|
|
|
526
559
|
search
|
|
527
560
|
};
|
|
528
561
|
}
|
|
562
|
+
createRedirectionLayer(href, context) {
|
|
563
|
+
return {
|
|
564
|
+
layers: [],
|
|
565
|
+
redirect: typeof href === "string" ? href : this.href(href),
|
|
566
|
+
pathname: context.pathname,
|
|
567
|
+
search: context.search
|
|
568
|
+
};
|
|
569
|
+
}
|
|
529
570
|
getErrorHandler(route) {
|
|
530
571
|
if (route.errorHandler) return route.errorHandler;
|
|
531
572
|
let parent = route.parent;
|
|
@@ -581,6 +622,7 @@ var PageDescriptorProvider = class {
|
|
|
581
622
|
let hasNotFoundHandler = false;
|
|
582
623
|
const pages = this.alepha.descriptors($page);
|
|
583
624
|
const hasParent = (it) => {
|
|
625
|
+
if (it.options.parent) return true;
|
|
584
626
|
for (const page of pages) {
|
|
585
627
|
const children = page.options.children ? Array.isArray(page.options.children) ? page.options.children : page.options.children() : [];
|
|
586
628
|
if (children.includes(it)) return true;
|
|
@@ -596,7 +638,7 @@ var PageDescriptorProvider = class {
|
|
|
596
638
|
name: "notFound",
|
|
597
639
|
cache: true,
|
|
598
640
|
component: NotFoundPage,
|
|
599
|
-
|
|
641
|
+
onServerResponse: ({ reply }) => {
|
|
600
642
|
reply.status = 404;
|
|
601
643
|
}
|
|
602
644
|
});
|
|
@@ -604,6 +646,12 @@ var PageDescriptorProvider = class {
|
|
|
604
646
|
});
|
|
605
647
|
map(pages, target) {
|
|
606
648
|
const children = target.options.children ? Array.isArray(target.options.children) ? target.options.children : target.options.children() : [];
|
|
649
|
+
const getChildrenFromParent = (it) => {
|
|
650
|
+
const children$1 = [];
|
|
651
|
+
for (const page of pages) if (page.options.parent === it) children$1.push(page);
|
|
652
|
+
return children$1;
|
|
653
|
+
};
|
|
654
|
+
children.push(...getChildrenFromParent(target));
|
|
607
655
|
return {
|
|
608
656
|
...target.options,
|
|
609
657
|
name: target.name,
|
|
@@ -725,6 +773,10 @@ var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
|
|
|
725
773
|
options.state.pathname = state.pathname;
|
|
726
774
|
options.state.search = state.search;
|
|
727
775
|
}
|
|
776
|
+
if (options.previous) for (let i = 0; i < options.previous.length; i++) {
|
|
777
|
+
const layer = options.previous[i];
|
|
778
|
+
if (state.layers[i]?.name !== layer.name) this.pageDescriptorProvider.page(layer.name)?.onLeave?.();
|
|
779
|
+
}
|
|
728
780
|
await this.alepha.emit("react:transition:end", {
|
|
729
781
|
state: options.state,
|
|
730
782
|
context
|
|
@@ -794,15 +846,11 @@ var ReactBrowserProvider = class {
|
|
|
794
846
|
}
|
|
795
847
|
async go(url, options = {}) {
|
|
796
848
|
const result = await this.render({ url });
|
|
797
|
-
if (result.context.url.pathname !== url) {
|
|
798
|
-
this.pushState(result.context.url.pathname);
|
|
849
|
+
if (result.context.url.pathname + result.context.url.search !== url) {
|
|
850
|
+
this.pushState(result.context.url.pathname + result.context.url.search);
|
|
799
851
|
return;
|
|
800
852
|
}
|
|
801
|
-
|
|
802
|
-
this.pushState(url);
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
this.pushState(url);
|
|
853
|
+
this.pushState(url, options.replace);
|
|
806
854
|
}
|
|
807
855
|
async render(options = {}) {
|
|
808
856
|
const previous = options.previous ?? this.state.layers;
|
|
@@ -831,7 +879,13 @@ var ReactBrowserProvider = class {
|
|
|
831
879
|
handler: async () => {
|
|
832
880
|
const hydration = this.getHydrationState();
|
|
833
881
|
const previous = hydration?.layers ?? [];
|
|
834
|
-
if (hydration
|
|
882
|
+
if (hydration) {
|
|
883
|
+
for (const [key, value] of Object.entries(hydration)) if (key !== "layers" && key !== "links") this.alepha.state(key, value);
|
|
884
|
+
}
|
|
885
|
+
if (hydration?.links) for (const link of hydration.links.links) this.client.pushLink({
|
|
886
|
+
...link,
|
|
887
|
+
prefix: hydration.links.prefix
|
|
888
|
+
});
|
|
835
889
|
const { context } = await this.render({ previous });
|
|
836
890
|
await this.alepha.emit("react:browser:render", {
|
|
837
891
|
state: this.state,
|
|
@@ -959,6 +1013,7 @@ var ReactServerProvider = class {
|
|
|
959
1013
|
html: (0, react_dom_server.renderToString)(this.pageDescriptorProvider.root(state, context))
|
|
960
1014
|
};
|
|
961
1015
|
const html = this.renderToHtml(this.template ?? "", state, context, options.hydration);
|
|
1016
|
+
if (html instanceof Redirection) throw new Error("Redirection is not supported in this context");
|
|
962
1017
|
const result = {
|
|
963
1018
|
context,
|
|
964
1019
|
state,
|
|
@@ -973,6 +1028,7 @@ var ReactServerProvider = class {
|
|
|
973
1028
|
const { url, reply, query, params } = serverRequest;
|
|
974
1029
|
const template = await templateLoader();
|
|
975
1030
|
if (!template) throw new Error("Template not found");
|
|
1031
|
+
this.log.trace("Rendering page", { name: page.name });
|
|
976
1032
|
const context = {
|
|
977
1033
|
url,
|
|
978
1034
|
params,
|
|
@@ -998,6 +1054,10 @@ var ReactServerProvider = class {
|
|
|
998
1054
|
}
|
|
999
1055
|
target = target.parent;
|
|
1000
1056
|
}
|
|
1057
|
+
await this.alepha.emit("react:transition:begin", {
|
|
1058
|
+
request: serverRequest,
|
|
1059
|
+
context
|
|
1060
|
+
});
|
|
1001
1061
|
await this.alepha.emit("react:server:render:begin", {
|
|
1002
1062
|
request: serverRequest,
|
|
1003
1063
|
context
|
|
@@ -1012,14 +1072,20 @@ var ReactServerProvider = class {
|
|
|
1012
1072
|
reply.headers.expires = "0";
|
|
1013
1073
|
if (page.cache && serverRequest.user) delete context.links;
|
|
1014
1074
|
const html = this.renderToHtml(template, state, context);
|
|
1015
|
-
|
|
1075
|
+
if (html instanceof Redirection) {
|
|
1076
|
+
reply.redirect(typeof html.page === "string" ? html.page : this.pageDescriptorProvider.href(html.page));
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const event = {
|
|
1016
1080
|
request: serverRequest,
|
|
1017
1081
|
context,
|
|
1018
1082
|
state,
|
|
1019
1083
|
html
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1084
|
+
};
|
|
1085
|
+
await this.alepha.emit("react:server:render:end", event);
|
|
1086
|
+
page.onServerResponse?.(serverRequest);
|
|
1087
|
+
this.log.trace("Page rendered", { name: page.name });
|
|
1088
|
+
return event.html;
|
|
1023
1089
|
};
|
|
1024
1090
|
}
|
|
1025
1091
|
renderToHtml(template, state, context, hydration = true) {
|
|
@@ -1030,20 +1096,23 @@ var ReactServerProvider = class {
|
|
|
1030
1096
|
app = (0, react_dom_server.renderToString)(element);
|
|
1031
1097
|
} catch (error) {
|
|
1032
1098
|
this.log.error("Error during SSR", error);
|
|
1033
|
-
|
|
1099
|
+
const element$1 = context.onError(error, context);
|
|
1100
|
+
if (element$1 instanceof Redirection) return element$1;
|
|
1101
|
+
app = (0, react_dom_server.renderToString)(element$1);
|
|
1034
1102
|
}
|
|
1035
1103
|
this.serverTimingProvider.endTiming("renderToString");
|
|
1036
1104
|
const response = { html: template };
|
|
1037
1105
|
if (hydration) {
|
|
1106
|
+
const { request, context: context$1,...rest } = this.alepha.context.als?.getStore() ?? {};
|
|
1038
1107
|
const hydrationData = {
|
|
1039
|
-
|
|
1108
|
+
...rest,
|
|
1040
1109
|
layers: state.layers.map((it) => ({
|
|
1041
1110
|
...it,
|
|
1042
1111
|
error: it.error ? {
|
|
1043
1112
|
...it.error,
|
|
1044
1113
|
name: it.error.name,
|
|
1045
1114
|
message: it.error.message,
|
|
1046
|
-
stack: it.error.stack
|
|
1115
|
+
stack: !this.alepha.isProduction() ? it.error.stack : void 0
|
|
1047
1116
|
} : void 0,
|
|
1048
1117
|
index: void 0,
|
|
1049
1118
|
path: void 0,
|
|
@@ -1063,24 +1132,34 @@ var ReactServerProvider = class {
|
|
|
1063
1132
|
else {
|
|
1064
1133
|
const bodyOpenTag = /<body([^>]*)>/i;
|
|
1065
1134
|
if (bodyOpenTag.test(response.html)) response.html = response.html.replace(bodyOpenTag, (match) => {
|
|
1066
|
-
return `${match}
|
|
1135
|
+
return `${match}<div id="${this.env.REACT_ROOT_ID}">${app}</div>`;
|
|
1067
1136
|
});
|
|
1068
1137
|
}
|
|
1069
1138
|
const bodyCloseTagRegex = /<\/body>/i;
|
|
1070
|
-
if (bodyCloseTagRegex.test(response.html)) response.html = response.html.replace(bodyCloseTagRegex, `${script}
|
|
1139
|
+
if (bodyCloseTagRegex.test(response.html)) response.html = response.html.replace(bodyCloseTagRegex, `${script}</body>`);
|
|
1071
1140
|
}
|
|
1072
1141
|
};
|
|
1073
1142
|
|
|
1074
1143
|
//#endregion
|
|
1075
1144
|
//#region src/hooks/RouterHookApi.ts
|
|
1076
1145
|
var RouterHookApi = class {
|
|
1077
|
-
constructor(pages, context, state, layer, browser) {
|
|
1146
|
+
constructor(pages, context, state, layer, pageApi, browser) {
|
|
1078
1147
|
this.pages = pages;
|
|
1079
1148
|
this.context = context;
|
|
1080
1149
|
this.state = state;
|
|
1081
1150
|
this.layer = layer;
|
|
1151
|
+
this.pageApi = pageApi;
|
|
1082
1152
|
this.browser = browser;
|
|
1083
1153
|
}
|
|
1154
|
+
path(name, config = {}) {
|
|
1155
|
+
return this.pageApi.pathname(name, {
|
|
1156
|
+
params: {
|
|
1157
|
+
...this.context.params,
|
|
1158
|
+
...config.params
|
|
1159
|
+
},
|
|
1160
|
+
query: config.query
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1084
1163
|
getURL() {
|
|
1085
1164
|
if (!this.browser) return this.context.url;
|
|
1086
1165
|
return new URL(this.location.href);
|
|
@@ -1122,23 +1201,23 @@ var RouterHookApi = class {
|
|
|
1122
1201
|
}
|
|
1123
1202
|
async go(path, options) {
|
|
1124
1203
|
for (const page of this.pages) if (page.name === path) {
|
|
1125
|
-
|
|
1126
|
-
|
|
1204
|
+
await this.browser?.go(this.path(path, options), options);
|
|
1205
|
+
return;
|
|
1127
1206
|
}
|
|
1128
|
-
await this.browser?.go(
|
|
1207
|
+
await this.browser?.go(path, options);
|
|
1129
1208
|
}
|
|
1130
1209
|
anchor(path, options = {}) {
|
|
1210
|
+
let href = path;
|
|
1131
1211
|
for (const page of this.pages) if (page.name === path) {
|
|
1132
|
-
|
|
1212
|
+
href = this.path(path, options);
|
|
1133
1213
|
break;
|
|
1134
1214
|
}
|
|
1135
|
-
const href = this.createHref(path, this.layer, options);
|
|
1136
1215
|
return {
|
|
1137
1216
|
href,
|
|
1138
1217
|
onClick: (ev) => {
|
|
1139
1218
|
ev.stopPropagation();
|
|
1140
1219
|
ev.preventDefault();
|
|
1141
|
-
this.go(
|
|
1220
|
+
this.go(href, options).catch(console.error);
|
|
1142
1221
|
}
|
|
1143
1222
|
};
|
|
1144
1223
|
}
|
|
@@ -1167,27 +1246,18 @@ const useRouter = () => {
|
|
|
1167
1246
|
const pages = (0, react.useMemo)(() => {
|
|
1168
1247
|
return alepha.inject(PageDescriptorProvider).getPages();
|
|
1169
1248
|
}, []);
|
|
1170
|
-
return (0, react.useMemo)(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, alepha.isBrowser() ? alepha.inject(ReactBrowserProvider) : void 0), [layer]);
|
|
1249
|
+
return (0, react.useMemo)(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, alepha.inject(PageDescriptorProvider), alepha.isBrowser() ? alepha.inject(ReactBrowserProvider) : void 0), [layer]);
|
|
1171
1250
|
};
|
|
1172
1251
|
|
|
1173
1252
|
//#endregion
|
|
1174
1253
|
//#region src/components/Link.tsx
|
|
1175
1254
|
const Link = (props) => {
|
|
1176
|
-
react.default.useContext(RouterContext);
|
|
1177
1255
|
const router = useRouter();
|
|
1178
|
-
const
|
|
1179
|
-
if (!to) return null;
|
|
1180
|
-
const can = typeof props.to === "string" ? void 0 : props.to.options.can;
|
|
1181
|
-
if (can && !can()) return null;
|
|
1182
|
-
const name = typeof props.to === "string" ? void 0 : props.to.options.name;
|
|
1183
|
-
const anchorProps = {
|
|
1184
|
-
...props,
|
|
1185
|
-
to: void 0
|
|
1186
|
-
};
|
|
1256
|
+
const { to,...anchorProps } = props;
|
|
1187
1257
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1188
1258
|
...router.anchor(to),
|
|
1189
1259
|
...anchorProps,
|
|
1190
|
-
children: props.children
|
|
1260
|
+
children: props.children
|
|
1191
1261
|
});
|
|
1192
1262
|
};
|
|
1193
1263
|
var Link_default = Link;
|
|
@@ -1199,22 +1269,21 @@ const useActive = (path) => {
|
|
|
1199
1269
|
const ctx = (0, react.useContext)(RouterContext);
|
|
1200
1270
|
const layer = (0, react.useContext)(RouterLayerContext);
|
|
1201
1271
|
if (!ctx || !layer) throw new Error("useRouter must be used within a RouterProvider");
|
|
1202
|
-
let name;
|
|
1203
|
-
if (typeof path === "object" && path.options.name) name = path.options.name;
|
|
1204
1272
|
const [current, setCurrent] = (0, react.useState)(ctx.state.pathname);
|
|
1205
|
-
const href = (0, react.useMemo)(() => router.createHref(path, layer), [path, layer]);
|
|
1273
|
+
const href = (0, react.useMemo)(() => router.createHref(path ?? "", layer), [path, layer]);
|
|
1206
1274
|
const [isPending, setPending] = (0, react.useState)(false);
|
|
1207
|
-
const isActive = current === href;
|
|
1208
|
-
useRouterEvents({ onEnd: ({ state }) =>
|
|
1275
|
+
const isActive = current === href || current === `${href}/` || `${current}/` === href;
|
|
1276
|
+
useRouterEvents({ onEnd: ({ state }) => {
|
|
1277
|
+
path && setCurrent(state.pathname);
|
|
1278
|
+
} }, [path]);
|
|
1209
1279
|
return {
|
|
1210
|
-
name,
|
|
1211
1280
|
isPending,
|
|
1212
1281
|
isActive,
|
|
1213
1282
|
anchorProps: {
|
|
1214
1283
|
href,
|
|
1215
1284
|
onClick: (ev) => {
|
|
1216
|
-
ev
|
|
1217
|
-
ev
|
|
1285
|
+
ev?.stopPropagation();
|
|
1286
|
+
ev?.preventDefault();
|
|
1218
1287
|
if (isActive) return;
|
|
1219
1288
|
if (isPending) return;
|
|
1220
1289
|
setPending(true);
|
|
@@ -1233,9 +1302,36 @@ const useInject = (service) => {
|
|
|
1233
1302
|
return (0, react.useMemo)(() => alepha.inject(service), []);
|
|
1234
1303
|
};
|
|
1235
1304
|
|
|
1305
|
+
//#endregion
|
|
1306
|
+
//#region src/hooks/useStore.ts
|
|
1307
|
+
/**
|
|
1308
|
+
* Hook to access and mutate the Alepha state.
|
|
1309
|
+
*/
|
|
1310
|
+
const useStore = (key, defaultValue) => {
|
|
1311
|
+
const alepha = useAlepha();
|
|
1312
|
+
(0, react.useMemo)(() => {
|
|
1313
|
+
if (defaultValue != null && alepha.state(key) == null) alepha.state(key, defaultValue);
|
|
1314
|
+
}, [defaultValue]);
|
|
1315
|
+
const [state, setState] = (0, react.useState)(alepha.state(key));
|
|
1316
|
+
(0, react.useEffect)(() => {
|
|
1317
|
+
if (!alepha.isBrowser()) return;
|
|
1318
|
+
return alepha.on("state:mutate", (ev) => {
|
|
1319
|
+
if (ev.key === key) setState(ev.value);
|
|
1320
|
+
});
|
|
1321
|
+
}, []);
|
|
1322
|
+
if (!alepha.isBrowser()) {
|
|
1323
|
+
const value = alepha.context.get(key);
|
|
1324
|
+
if (value !== null) return [value, (_) => {}];
|
|
1325
|
+
}
|
|
1326
|
+
return [state, (value) => {
|
|
1327
|
+
alepha.state(key, value);
|
|
1328
|
+
}];
|
|
1329
|
+
};
|
|
1330
|
+
|
|
1236
1331
|
//#endregion
|
|
1237
1332
|
//#region src/hooks/useClient.ts
|
|
1238
1333
|
const useClient = (_scope) => {
|
|
1334
|
+
useStore("user");
|
|
1239
1335
|
return useInject(__alepha_server_links.LinkProvider).client();
|
|
1240
1336
|
};
|
|
1241
1337
|
|
|
@@ -1318,29 +1414,6 @@ const ssrSchemaLoading = (alepha, name) => {
|
|
|
1318
1414
|
return { loading: true };
|
|
1319
1415
|
};
|
|
1320
1416
|
|
|
1321
|
-
//#endregion
|
|
1322
|
-
//#region src/hooks/useStore.ts
|
|
1323
|
-
/**
|
|
1324
|
-
* Hook to access and mutate the Alepha state.
|
|
1325
|
-
*/
|
|
1326
|
-
const useStore = (key) => {
|
|
1327
|
-
const alepha = useAlepha();
|
|
1328
|
-
const [state, setState] = (0, react.useState)(alepha.state(key));
|
|
1329
|
-
(0, react.useEffect)(() => {
|
|
1330
|
-
if (!alepha.isBrowser()) return;
|
|
1331
|
-
return alepha.on("state:mutate", (ev) => {
|
|
1332
|
-
if (ev.key === key) setState(ev.value);
|
|
1333
|
-
});
|
|
1334
|
-
}, []);
|
|
1335
|
-
if (!alepha.isBrowser()) {
|
|
1336
|
-
const value = alepha.context.get(key);
|
|
1337
|
-
if (value !== null) return [value, (_) => {}];
|
|
1338
|
-
}
|
|
1339
|
-
return [state, (value) => {
|
|
1340
|
-
alepha.state(key, value);
|
|
1341
|
-
}];
|
|
1342
|
-
};
|
|
1343
|
-
|
|
1344
1417
|
//#endregion
|
|
1345
1418
|
//#region src/index.ts
|
|
1346
1419
|
/**
|
|
@@ -1377,7 +1450,7 @@ exports.PageDescriptor = PageDescriptor;
|
|
|
1377
1450
|
exports.PageDescriptorProvider = PageDescriptorProvider;
|
|
1378
1451
|
exports.ReactBrowserProvider = ReactBrowserProvider;
|
|
1379
1452
|
exports.ReactServerProvider = ReactServerProvider;
|
|
1380
|
-
exports.
|
|
1453
|
+
exports.Redirection = Redirection;
|
|
1381
1454
|
exports.RouterContext = RouterContext;
|
|
1382
1455
|
exports.RouterHookApi = RouterHookApi;
|
|
1383
1456
|
exports.RouterLayerContext = RouterLayerContext;
|