keycloakify 10.0.0-rc.22 → 10.0.0-rc.24
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/PUBLIC_URL.d.ts +1 -1
- package/PUBLIC_URL.js +1 -1
- package/PUBLIC_URL.js.map +1 -1
- package/account/Fallback.js.map +1 -1
- package/account/Template.js +3 -3
- package/account/Template.js.map +1 -1
- package/account/i18n/baseMessages/index.js.map +1 -1
- package/account/i18n/i18n.js.map +1 -1
- package/account/index.d.ts +2 -2
- package/account/index.js +1 -2
- package/account/index.js.map +1 -1
- package/account/kcContext/KcContext.d.ts +12 -0
- package/account/kcContext/KcContext.js.map +1 -1
- package/account/kcContext/getKcContextMock.d.ts +24 -0
- package/account/kcContext/getKcContextMock.js +28 -0
- package/account/kcContext/getKcContextMock.js.map +1 -0
- package/account/kcContext/index.d.ts +2 -1
- package/account/kcContext/index.js +1 -1
- package/account/kcContext/index.js.map +1 -1
- package/account/kcContext/kcContextMocks.js +23 -91
- package/account/kcContext/kcContextMocks.js.map +1 -1
- package/account/pages/Account.js +1 -1
- package/account/pages/Account.js.map +1 -1
- package/account/pages/Applications.js +2 -2
- package/account/pages/Applications.js.map +1 -1
- package/account/pages/FederatedIdentity.js +1 -1
- package/account/pages/FederatedIdentity.js.map +1 -1
- package/account/pages/Log.js +1 -1
- package/account/pages/Log.js.map +1 -1
- package/account/pages/Password.js +6 -4
- package/account/pages/Password.js.map +1 -1
- package/account/pages/Sessions.js +1 -1
- package/account/pages/Sessions.js.map +1 -1
- package/account/pages/Totp.js +1 -1
- package/account/pages/Totp.js.map +1 -1
- package/bin/main.js +174 -162
- package/lib/BASE_URL.js.map +1 -1
- package/login/Fallback.js.map +1 -1
- package/login/Template.js +7 -7
- package/login/Template.js.map +1 -1
- package/login/UserProfileFormFields.js +24 -68
- package/login/UserProfileFormFields.js.map +1 -1
- package/login/i18n/baseMessages/index.js.map +1 -1
- package/login/i18n/i18n.d.ts +1 -1
- package/login/i18n/i18n.js +1 -1
- package/login/i18n/i18n.js.map +1 -1
- package/login/index.d.ts +2 -3
- package/login/index.js +1 -2
- package/login/index.js.map +1 -1
- package/login/kcContext/KcContext.d.ts +23 -13
- package/login/kcContext/KcContext.js.map +1 -1
- package/login/kcContext/getKcContextMock.d.ts +24 -0
- package/login/kcContext/getKcContextMock.js +28 -0
- package/login/kcContext/getKcContextMock.js.map +1 -0
- package/login/kcContext/index.d.ts +2 -1
- package/login/kcContext/index.js +1 -1
- package/login/kcContext/index.js.map +1 -1
- package/login/kcContext/kcContextMocks.js +29 -103
- package/login/kcContext/kcContextMocks.js.map +1 -1
- package/login/lib/useDownloadTerms.js +8 -14
- package/login/lib/useDownloadTerms.js.map +1 -1
- package/login/lib/useGetClassName.js +1 -1
- package/login/lib/useGetClassName.js.map +1 -1
- package/login/lib/useUserProfileForm.d.ts +9 -1
- package/login/lib/useUserProfileForm.js +94 -15
- package/login/lib/useUserProfileForm.js.map +1 -1
- package/login/pages/Code.js +1 -1
- package/login/pages/Code.js.map +1 -1
- package/login/pages/DeleteAccountConfirm.js +2 -2
- package/login/pages/DeleteAccountConfirm.js.map +1 -1
- package/login/pages/DeleteCredential.js +1 -1
- package/login/pages/DeleteCredential.js.map +1 -1
- package/login/pages/Error.js +1 -1
- package/login/pages/Error.js.map +1 -1
- package/login/pages/FrontchannelLogout.js +1 -1
- package/login/pages/FrontchannelLogout.js.map +1 -1
- package/login/pages/IdpReviewUserProfile.js +1 -1
- package/login/pages/IdpReviewUserProfile.js.map +1 -1
- package/login/pages/Info.js +5 -5
- package/login/pages/Info.js.map +1 -1
- package/login/pages/Login.js +4 -4
- package/login/pages/Login.js.map +1 -1
- package/login/pages/LoginConfigTotp.js +2 -2
- package/login/pages/LoginConfigTotp.js.map +1 -1
- package/login/pages/LoginIdpLinkConfirm.js +1 -1
- package/login/pages/LoginIdpLinkConfirm.js.map +1 -1
- package/login/pages/LoginIdpLinkEmail.js +1 -1
- package/login/pages/LoginIdpLinkEmail.js.map +1 -1
- package/login/pages/LoginOauth2DeviceVerifyUserCode.js +1 -1
- package/login/pages/LoginOauth2DeviceVerifyUserCode.js.map +1 -1
- package/login/pages/LoginOauthGrant.js +2 -2
- package/login/pages/LoginOauthGrant.js.map +1 -1
- package/login/pages/LoginOtp.js +1 -1
- package/login/pages/LoginOtp.js.map +1 -1
- package/login/pages/LoginPageExpired.js +1 -1
- package/login/pages/LoginPageExpired.js.map +1 -1
- package/login/pages/LoginPassword.js +3 -3
- package/login/pages/LoginPassword.js.map +1 -1
- package/login/pages/LoginRecoveryAuthnCodeConfig.js +10 -10
- package/login/pages/LoginRecoveryAuthnCodeConfig.js.map +1 -1
- package/login/pages/LoginRecoveryAuthnCodeInput.js +1 -1
- package/login/pages/LoginRecoveryAuthnCodeInput.js.map +1 -1
- package/login/pages/LoginResetOtp.js +1 -1
- package/login/pages/LoginResetOtp.js.map +1 -1
- package/login/pages/LoginResetPassword.js +2 -2
- package/login/pages/LoginResetPassword.js.map +1 -1
- package/login/pages/LoginUpdatePassword.js +3 -3
- package/login/pages/LoginUpdatePassword.js.map +1 -1
- package/login/pages/LoginUpdateProfile.js +4 -2
- package/login/pages/LoginUpdateProfile.js.map +1 -1
- package/login/pages/LoginUsername.js +3 -3
- package/login/pages/LoginUsername.js.map +1 -1
- package/login/pages/LoginVerifyEmail.js +1 -1
- package/login/pages/LoginVerifyEmail.js.map +1 -1
- package/login/pages/LoginX509Info.js +1 -1
- package/login/pages/LoginX509Info.js.map +1 -1
- package/login/pages/LogoutConfirm.js +1 -1
- package/login/pages/LogoutConfirm.js.map +1 -1
- package/login/pages/Register.js +8 -4
- package/login/pages/Register.js.map +1 -1
- package/login/pages/SamlPostForm.js +1 -1
- package/login/pages/SamlPostForm.js.map +1 -1
- package/login/pages/SelectAuthenticator.js +2 -2
- package/login/pages/SelectAuthenticator.js.map +1 -1
- package/login/pages/Terms.js +1 -1
- package/login/pages/Terms.js.map +1 -1
- package/login/pages/UpdateEmail.js +5 -3
- package/login/pages/UpdateEmail.js.map +1 -1
- package/login/pages/WebauthnAuthenticate.js +8 -8
- package/login/pages/WebauthnAuthenticate.js.map +1 -1
- package/login/pages/WebauthnError.js +2 -2
- package/login/pages/WebauthnError.js.map +1 -1
- package/login/pages/WebauthnRegister.js +5 -5
- package/login/pages/WebauthnRegister.js.map +1 -1
- package/package.json +26 -38
- package/src/PUBLIC_URL.ts +1 -1
- package/src/account/Template.tsx +2 -3
- package/src/account/index.ts +2 -2
- package/src/account/kcContext/KcContext.ts +19 -1
- package/src/account/kcContext/getKcContextMock.ts +80 -0
- package/src/account/kcContext/index.ts +2 -1
- package/src/account/kcContext/kcContextMocks.ts +26 -91
- package/src/bin/copy-keycloak-resources-to-public.ts +1 -4
- package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +19 -11
- package/src/bin/start-keycloak/start-keycloak.ts +18 -5
- package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +25 -25
- package/src/login/Template.tsx +4 -5
- package/src/login/UserProfileFormFields.tsx +28 -80
- package/src/login/i18n/i18n.tsx +3 -3
- package/src/login/index.ts +6 -3
- package/src/login/kcContext/KcContext.ts +43 -31
- package/src/login/kcContext/getKcContextMock.ts +80 -0
- package/src/login/kcContext/index.ts +7 -1
- package/src/login/kcContext/kcContextMocks.ts +92 -165
- package/src/login/lib/useDownloadTerms.ts +10 -24
- package/src/login/lib/useGetClassName.ts +1 -1
- package/src/login/lib/useUserProfileForm.tsx +117 -13
- package/src/login/pages/LoginConfigTotp.tsx +1 -1
- package/src/login/pages/LoginRecoveryAuthnCodeConfig.tsx +7 -8
- package/src/login/pages/WebauthnAuthenticate.tsx +2 -3
- package/src/login/pages/WebauthnRegister.tsx +2 -3
- package/src/tools/ExtractAfterStartingWith.ts +4 -0
- package/src/tools/StatefulObservable/hooks/useRerenderOnChange.ts +4 -4
- package/src/tools/ValueOf.ts +2 -0
- package/src/tools/deepAssign.ts +51 -20
- package/src/tools/structuredCloneButFunctions.ts +24 -0
- package/src/tools/useInsertLinkTags.ts +78 -87
- package/src/tools/useInsertScriptTags.ts +69 -78
- package/src/tools/useOnFirstMount.ts +18 -0
- package/tools/Array.prototype.every.js.map +1 -1
- package/tools/ExtractAfterStartingWith.d.ts +1 -0
- package/tools/ExtractAfterStartingWith.js +2 -0
- package/tools/ExtractAfterStartingWith.js.map +1 -0
- package/tools/HTMLElement.prototype.prepend.js.map +1 -1
- package/tools/StatefulObservable/StatefulObservable.js.map +1 -1
- package/tools/StatefulObservable/hooks/useRerenderOnChange.d.ts +1 -1
- package/tools/StatefulObservable/hooks/useRerenderOnChange.js +4 -4
- package/tools/StatefulObservable/hooks/useRerenderOnChange.js.map +1 -1
- package/tools/ValueOf.d.ts +2 -0
- package/tools/ValueOf.js +2 -0
- package/tools/ValueOf.js.map +1 -0
- package/tools/clsx.js.map +1 -1
- package/tools/deepAssign.d.ts +1 -0
- package/tools/deepAssign.js +39 -16
- package/tools/deepAssign.js.map +1 -1
- package/tools/formatNumber.js.map +1 -1
- package/tools/structuredCloneButFunctions.d.ts +7 -0
- package/tools/structuredCloneButFunctions.js +19 -0
- package/tools/structuredCloneButFunctions.js.map +1 -0
- package/tools/useInsertLinkTags.d.ts +11 -6
- package/tools/useInsertLinkTags.js +53 -53
- package/tools/useInsertLinkTags.js.map +1 -1
- package/tools/useInsertScriptTags.d.ts +15 -6
- package/tools/useInsertScriptTags.js +56 -64
- package/tools/useInsertScriptTags.js.map +1 -1
- package/tools/useOnFirstMount.d.ts +2 -0
- package/tools/useOnFirstMount.js +15 -0
- package/tools/useOnFirstMount.js.map +1 -0
- package/tools/useSetClassName.js.map +1 -1
- package/vite-plugin/index.js +66 -64
- package/account/kcContext/createGetKcContext.d.ts +0 -19
- package/account/kcContext/createGetKcContext.js +0 -78
- package/account/kcContext/createGetKcContext.js.map +0 -1
- package/account/kcContext/getKcContext.d.ts +0 -13
- package/account/kcContext/getKcContext.js +0 -13
- package/account/kcContext/getKcContext.js.map +0 -1
- package/account/kcContext/getKcContextFromWindow.d.ts +0 -10
- package/account/kcContext/getKcContextFromWindow.js +0 -5
- package/account/kcContext/getKcContextFromWindow.js.map +0 -1
- package/login/kcContext/createGetKcContext.d.ts +0 -19
- package/login/kcContext/createGetKcContext.js +0 -117
- package/login/kcContext/createGetKcContext.js.map +0 -1
- package/login/kcContext/getKcContext.d.ts +0 -13
- package/login/kcContext/getKcContext.js +0 -13
- package/login/kcContext/getKcContext.js.map +0 -1
- package/login/kcContext/getKcContextFromWindow.d.ts +0 -10
- package/login/kcContext/getKcContextFromWindow.js +0 -5
- package/login/kcContext/getKcContextFromWindow.js.map +0 -1
- package/src/account/kcContext/createGetKcContext.ts +0 -134
- package/src/account/kcContext/getKcContext.ts +0 -23
- package/src/account/kcContext/getKcContextFromWindow.ts +0 -15
- package/src/login/kcContext/createGetKcContext.ts +0 -206
- package/src/login/kcContext/getKcContext.ts +0 -23
- package/src/login/kcContext/getKcContextFromWindow.ts +0 -15
- package/src/tools/AndByDiscriminatingKey.ts +0 -31
- package/src/tools/deepClone.ts +0 -19
- package/src/tools/memoize.ts +0 -55
- package/tools/AndByDiscriminatingKey.d.ts +0 -5
- package/tools/AndByDiscriminatingKey.js +0 -2
- package/tools/AndByDiscriminatingKey.js.map +0 -1
- package/tools/deepClone.d.ts +0 -2
- package/tools/deepClone.js +0 -14
- package/tools/deepClone.js.map +0 -1
- package/tools/memoize.d.ts +0 -7
- package/tools/memoize.js +0 -38
- package/tools/memoize.js.map +0 -1
@@ -3,12 +3,10 @@ import { clsx } from "keycloakify/tools/clsx";
|
|
3
3
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
4
4
|
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
5
5
|
import { assert } from "tsafe/assert";
|
6
|
-
import {
|
6
|
+
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
7
7
|
import type { KcContext } from "../kcContext";
|
8
8
|
import type { I18n } from "../i18n";
|
9
9
|
|
10
|
-
const { useInsertScriptTags } = createUseInsertScriptTags();
|
11
|
-
|
12
10
|
export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext, { pageId: "webauthn-authenticate.ftl" }>, I18n>) {
|
13
11
|
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
|
14
12
|
|
@@ -31,6 +29,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|
31
29
|
const { msg, msgStr, advancedMsg } = i18n;
|
32
30
|
|
33
31
|
const { insertScriptTags } = useInsertScriptTags({
|
32
|
+
componentOrHookName: "WebauthnAuthenticate",
|
34
33
|
scriptTags: [
|
35
34
|
{
|
36
35
|
type: "text/javascript",
|
@@ -3,12 +3,10 @@ import { clsx } from "keycloakify/tools/clsx";
|
|
3
3
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
4
4
|
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
5
5
|
import { assert } from "tsafe/assert";
|
6
|
-
import {
|
6
|
+
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
7
7
|
import type { KcContext } from "../kcContext";
|
8
8
|
import type { I18n } from "../i18n";
|
9
9
|
|
10
|
-
const { useInsertScriptTags } = createUseInsertScriptTags();
|
11
|
-
|
12
10
|
export default function WebauthnRegister(props: PageProps<Extract<KcContext, { pageId: "webauthn-register.ftl" }>, I18n>) {
|
13
11
|
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
|
14
12
|
|
@@ -35,6 +33,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
|
35
33
|
const { msg, msgStr } = i18n;
|
36
34
|
|
37
35
|
const { insertScriptTags } = useInsertScriptTags({
|
36
|
+
componentOrHookName: "WebauthnRegister",
|
38
37
|
scriptTags: [
|
39
38
|
{
|
40
39
|
type: "text/javascript",
|
@@ -5,15 +5,15 @@ import type { StatefulObservable } from "../StatefulObservable";
|
|
5
5
|
/**
|
6
6
|
* Equivalent of https://docs.evt.land/api/react-hooks
|
7
7
|
* */
|
8
|
-
export function useRerenderOnChange(
|
8
|
+
export function useRerenderOnChange(obs: StatefulObservable<unknown>): void {
|
9
9
|
//NOTE: We use function in case the state is a function
|
10
|
-
const [, setCurrent] = useState(() =>
|
10
|
+
const [, setCurrent] = useState(() => obs.current);
|
11
11
|
|
12
12
|
useObservable(
|
13
13
|
({ registerSubscription }) => {
|
14
|
-
const subscription =
|
14
|
+
const subscription = obs.subscribe(current => setCurrent(() => current));
|
15
15
|
registerSubscription(subscription);
|
16
16
|
},
|
17
|
-
[
|
17
|
+
[obs]
|
18
18
|
);
|
19
19
|
}
|
package/src/tools/deepAssign.ts
CHANGED
@@ -1,45 +1,61 @@
|
|
1
1
|
import { assert } from "tsafe/assert";
|
2
2
|
import { is } from "tsafe/is";
|
3
|
-
import {
|
3
|
+
import { structuredCloneButFunctions } from "./structuredCloneButFunctions";
|
4
4
|
|
5
|
-
|
5
|
+
/** NOTE: Array a copied over, not merged. */
|
6
6
|
export function deepAssign(params: {
|
7
7
|
target: Record<string, unknown>;
|
8
8
|
source: Record<string, unknown>;
|
9
|
-
}) {
|
10
|
-
const { target } = params;
|
11
|
-
|
12
|
-
const source = deepClone(params.source);
|
9
|
+
}): void {
|
10
|
+
const { target, source } = params;
|
13
11
|
|
14
12
|
Object.keys(source).forEach(key => {
|
15
13
|
var dereferencedSource = source[key];
|
16
14
|
|
15
|
+
if (dereferencedSource === undefined) {
|
16
|
+
delete target[key];
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
if (dereferencedSource instanceof Date) {
|
21
|
+
assign({
|
22
|
+
target,
|
23
|
+
key,
|
24
|
+
value: new Date(dereferencedSource.getTime())
|
25
|
+
});
|
26
|
+
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
|
30
|
+
if (dereferencedSource instanceof Array) {
|
31
|
+
assign({
|
32
|
+
target,
|
33
|
+
key,
|
34
|
+
value: structuredCloneButFunctions(dereferencedSource)
|
35
|
+
});
|
36
|
+
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
|
17
40
|
if (
|
18
|
-
target[key] === undefined ||
|
19
41
|
dereferencedSource instanceof Function ||
|
20
42
|
!(dereferencedSource instanceof Object)
|
21
43
|
) {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
configurable: true,
|
44
|
+
assign({
|
45
|
+
target,
|
46
|
+
key,
|
26
47
|
value: dereferencedSource
|
27
48
|
});
|
28
49
|
|
29
50
|
return;
|
30
51
|
}
|
31
52
|
|
32
|
-
|
33
|
-
|
34
|
-
if (dereferencedSource instanceof Array) {
|
35
|
-
assert(is<unknown[]>(dereferencedTarget));
|
36
|
-
assert(is<unknown[]>(dereferencedSource));
|
37
|
-
|
38
|
-
dereferencedSource.forEach(entry => dereferencedTarget.push(entry));
|
39
|
-
|
40
|
-
return;
|
53
|
+
if (!(target[key] instanceof Object)) {
|
54
|
+
target[key] = {};
|
41
55
|
}
|
42
56
|
|
57
|
+
const dereferencedTarget = target[key];
|
58
|
+
|
43
59
|
assert(is<Record<string, unknown>>(dereferencedTarget));
|
44
60
|
assert(is<Record<string, unknown>>(dereferencedSource));
|
45
61
|
|
@@ -49,3 +65,18 @@ export function deepAssign(params: {
|
|
49
65
|
});
|
50
66
|
});
|
51
67
|
}
|
68
|
+
|
69
|
+
function assign(params: {
|
70
|
+
target: Record<string, unknown>;
|
71
|
+
key: string;
|
72
|
+
value: unknown;
|
73
|
+
}): void {
|
74
|
+
const { target, key, value } = params;
|
75
|
+
|
76
|
+
Object.defineProperty(target, key, {
|
77
|
+
enumerable: true,
|
78
|
+
writable: true,
|
79
|
+
configurable: true,
|
80
|
+
value
|
81
|
+
});
|
82
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import "minimal-polyfills/Object.fromEntries";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Functionally equivalent to structuredClone but
|
5
|
+
* functions are not cloned but kept as is.
|
6
|
+
* (as opposed to structuredClone that chokes if it encounters a function)
|
7
|
+
*/
|
8
|
+
export function structuredCloneButFunctions<T>(o: T): T {
|
9
|
+
if (!(o instanceof Object)) {
|
10
|
+
return o;
|
11
|
+
}
|
12
|
+
|
13
|
+
if (typeof o === "function") {
|
14
|
+
return o;
|
15
|
+
}
|
16
|
+
|
17
|
+
if (o instanceof Array) {
|
18
|
+
return o.map(structuredCloneButFunctions) as any;
|
19
|
+
}
|
20
|
+
|
21
|
+
return Object.fromEntries(
|
22
|
+
Object.entries(o).map(([key, value]) => [key, structuredCloneButFunctions(value)])
|
23
|
+
) as any;
|
24
|
+
}
|
@@ -1,95 +1,86 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
1
|
+
import { useEffect, useReducer } from "react";
|
2
|
+
import { useConst } from "keycloakify/tools/useConst";
|
3
|
+
import { id } from "tsafe/id";
|
4
|
+
import { useOnFistMount } from "keycloakify/tools/useOnFirstMount";
|
5
|
+
|
6
|
+
const alreadyMountedComponentOrHookNames = new Set<string>();
|
7
|
+
|
8
|
+
/**
|
9
|
+
* NOTE: The component that use this hook can only be mounded once!
|
10
|
+
* And can't rerender with different hrefs.
|
11
|
+
* If it's mounted again the page will be reloaded.
|
12
|
+
* This simulates the behavior of a server rendered page that imports css stylesheet in the head.
|
13
|
+
*/
|
14
|
+
export function useInsertLinkTags(params: {
|
15
|
+
componentOrHookName: string;
|
16
|
+
hrefs: string[];
|
17
|
+
}) {
|
18
|
+
const { hrefs, componentOrHookName } = params;
|
19
|
+
|
20
|
+
useOnFistMount(() => {
|
21
|
+
const isAlreadyMounted =
|
22
|
+
alreadyMountedComponentOrHookNames.has(componentOrHookName);
|
23
|
+
|
24
|
+
if (isAlreadyMounted) {
|
25
|
+
window.location.reload();
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
|
29
|
+
alreadyMountedComponentOrHookNames.add(componentOrHookName);
|
30
|
+
});
|
31
|
+
|
32
|
+
const [areAllStyleSheetsLoaded, setAllStyleSheetsLoaded] = useReducer(
|
33
|
+
() => true,
|
34
|
+
false
|
35
|
+
);
|
36
|
+
|
37
|
+
const refPrAllStyleSheetLoaded = useConst(() => ({
|
38
|
+
current: id<Promise<void> | undefined>(undefined)
|
39
|
+
}));
|
40
|
+
|
41
|
+
useEffect(() => {
|
42
|
+
let isActive = true;
|
43
|
+
|
44
|
+
(refPrAllStyleSheetLoaded.current ??= (async () => {
|
45
|
+
let lastMountedHtmlElement: HTMLLinkElement | undefined = undefined;
|
46
|
+
|
47
|
+
const prs: Promise<void>[] = [];
|
48
|
+
|
49
|
+
for (const href of hrefs) {
|
50
|
+
const htmlElement = document.createElement("link");
|
51
|
+
|
52
|
+
prs.push(
|
53
|
+
new Promise<void>(resolve =>
|
54
|
+
htmlElement.addEventListener("load", () => resolve())
|
55
|
+
)
|
56
|
+
);
|
57
|
+
|
58
|
+
htmlElement.rel = "stylesheet";
|
59
|
+
|
60
|
+
htmlElement.href = href;
|
61
|
+
|
62
|
+
if (lastMountedHtmlElement !== undefined) {
|
63
|
+
lastMountedHtmlElement.insertAdjacentElement("afterend", htmlElement);
|
64
|
+
} else {
|
65
|
+
document.head.prepend(htmlElement);
|
36
66
|
}
|
37
67
|
|
38
|
-
|
39
|
-
|
40
|
-
const prs: Promise<void>[] = [];
|
41
|
-
const removeFns: (() => void)[] = [];
|
42
|
-
|
43
|
-
for (const href of hrefs) {
|
44
|
-
const htmlElement = document.createElement("link");
|
45
|
-
|
46
|
-
prs.push(
|
47
|
-
new Promise<void>(resolve =>
|
48
|
-
htmlElement.addEventListener("load", () => resolve())
|
49
|
-
)
|
50
|
-
);
|
51
|
-
|
52
|
-
htmlElement.rel = "stylesheet";
|
53
|
-
|
54
|
-
htmlElement.href = href;
|
55
|
-
|
56
|
-
if (lastMountedHtmlElement !== undefined) {
|
57
|
-
lastMountedHtmlElement.insertAdjacentElement(
|
58
|
-
"afterend",
|
59
|
-
htmlElement
|
60
|
-
);
|
61
|
-
} else {
|
62
|
-
document.head.prepend(htmlElement);
|
63
|
-
}
|
64
|
-
|
65
|
-
removeFns.push(() => {
|
66
|
-
htmlElement.remove();
|
67
|
-
});
|
68
|
-
|
69
|
-
lastMountedHtmlElement = htmlElement;
|
70
|
-
}
|
71
|
-
|
72
|
-
linkTagsContext = {
|
73
|
-
styleSheetHrefs: hrefs,
|
74
|
-
prAreAllStyleSheetsLoaded: Promise.all(prs).then(() => undefined),
|
75
|
-
remove: () => removeFns.forEach(fn => fn())
|
76
|
-
};
|
68
|
+
lastMountedHtmlElement = htmlElement;
|
77
69
|
}
|
78
70
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
});
|
71
|
+
await Promise.all(prs);
|
72
|
+
})()).then(() => {
|
73
|
+
if (!isActive) {
|
74
|
+
return;
|
75
|
+
}
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
};
|
89
|
-
}, []);
|
77
|
+
setAllStyleSheetsLoaded();
|
78
|
+
});
|
90
79
|
|
91
|
-
return
|
92
|
-
|
80
|
+
return () => {
|
81
|
+
isActive = false;
|
82
|
+
};
|
83
|
+
}, []);
|
93
84
|
|
94
|
-
return {
|
85
|
+
return { areAllStyleSheetsLoaded };
|
95
86
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { useCallback } from "react";
|
2
|
-
import { useConst } from "keycloakify/tools/useConst";
|
3
2
|
import { assert } from "tsafe/assert";
|
3
|
+
import { useOnFistMount } from "keycloakify/tools/useOnFirstMount";
|
4
4
|
|
5
5
|
export type ScriptTag = ScriptTag.TextContent | ScriptTag.Src;
|
6
6
|
|
@@ -17,95 +17,86 @@ export namespace ScriptTag {
|
|
17
17
|
};
|
18
18
|
}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
const alreadyMountedComponentOrHookNames = new Set<string>();
|
21
|
+
|
22
|
+
/**
|
23
|
+
* NOTE: The component that use this hook can only be mounded once!
|
24
|
+
* And can't rerender with different scriptTags.
|
25
|
+
* If it's mounted again the page will be reloaded.
|
26
|
+
* This simulates the behavior of a server rendered page that imports javascript in the head.
|
27
|
+
*
|
28
|
+
* The returned function is supposed to be called in a useEffect and
|
29
|
+
* will not download the scripts multiple times event if called more than once (react strict mode).
|
30
|
+
*
|
31
|
+
*/
|
32
|
+
export function useInsertScriptTags(params: {
|
33
|
+
componentOrHookName: string;
|
34
|
+
scriptTags: ScriptTag[];
|
35
|
+
}) {
|
36
|
+
const { scriptTags, componentOrHookName } = params;
|
37
|
+
|
38
|
+
useOnFistMount(() => {
|
39
|
+
const isAlreadyMounted =
|
40
|
+
alreadyMountedComponentOrHookNames.has(componentOrHookName);
|
41
|
+
|
42
|
+
if (isAlreadyMounted) {
|
43
|
+
window.location.reload();
|
44
|
+
return;
|
45
|
+
}
|
46
|
+
|
47
|
+
alreadyMountedComponentOrHookNames.add(componentOrHookName);
|
48
|
+
});
|
25
49
|
|
26
|
-
|
27
|
-
current: scriptTags
|
28
|
-
}));
|
50
|
+
let areScriptsInserted = false;
|
29
51
|
|
30
|
-
|
52
|
+
const insertScriptTags = useCallback(() => {
|
53
|
+
if (areScriptsInserted) {
|
54
|
+
return;
|
55
|
+
}
|
31
56
|
|
32
|
-
|
57
|
+
scriptTags.forEach(scriptTag => {
|
58
|
+
// NOTE: Avoid loading same script twice. (Like jQuery for example)
|
33
59
|
{
|
34
|
-
const
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
if ("src" in scriptTag) {
|
41
|
-
return scriptTag.src;
|
42
|
-
}
|
43
|
-
assert(false);
|
44
|
-
})
|
45
|
-
.join("---");
|
46
|
-
|
47
|
-
if (
|
48
|
-
getFingerprint(scriptTags) !==
|
49
|
-
getFingerprint(currentScriptTagsRef.current)
|
50
|
-
) {
|
51
|
-
// NOTE: This is for when the scripts imported in the Template have changed switching
|
52
|
-
// from one page to another in storybook.
|
53
|
-
window.location.reload();
|
54
|
-
|
55
|
-
return;
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
if (areScriptsInserted) {
|
60
|
-
return;
|
61
|
-
}
|
62
|
-
|
63
|
-
scriptTags.forEach(scriptTag => {
|
64
|
-
// NOTE: Avoid loading same script twice. (Like jQuery for example)
|
65
|
-
{
|
66
|
-
const scripts = document.getElementsByTagName("script");
|
67
|
-
for (let i = 0; i < scripts.length; i++) {
|
68
|
-
const script = scripts[i];
|
69
|
-
if ("textContent" in scriptTag) {
|
70
|
-
if (script.textContent === scriptTag.textContent) {
|
71
|
-
return;
|
72
|
-
}
|
73
|
-
continue;
|
60
|
+
const scripts = document.getElementsByTagName("script");
|
61
|
+
for (let i = 0; i < scripts.length; i++) {
|
62
|
+
const script = scripts[i];
|
63
|
+
if ("textContent" in scriptTag) {
|
64
|
+
if (script.textContent === scriptTag.textContent) {
|
65
|
+
return;
|
74
66
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
67
|
+
continue;
|
68
|
+
}
|
69
|
+
if ("src" in scriptTag) {
|
70
|
+
if (script.getAttribute("src") === scriptTag.src) {
|
71
|
+
return;
|
80
72
|
}
|
81
|
-
|
73
|
+
continue;
|
82
74
|
}
|
75
|
+
assert(false);
|
83
76
|
}
|
77
|
+
}
|
84
78
|
|
85
|
-
|
86
|
-
|
87
|
-
htmlElement.type = scriptTag.type;
|
79
|
+
const htmlElement = document.createElement("script");
|
88
80
|
|
89
|
-
|
90
|
-
if ("textContent" in scriptTag) {
|
91
|
-
htmlElement.textContent = scriptTag.textContent;
|
92
|
-
return;
|
93
|
-
}
|
94
|
-
if ("src" in scriptTag) {
|
95
|
-
htmlElement.src = scriptTag.src;
|
96
|
-
return;
|
97
|
-
}
|
98
|
-
assert(false);
|
99
|
-
})();
|
81
|
+
htmlElement.type = scriptTag.type;
|
100
82
|
|
101
|
-
|
102
|
-
|
83
|
+
(() => {
|
84
|
+
if ("textContent" in scriptTag) {
|
85
|
+
htmlElement.textContent = scriptTag.textContent;
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
if ("src" in scriptTag) {
|
89
|
+
htmlElement.src = scriptTag.src;
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
assert(false);
|
93
|
+
})();
|
103
94
|
|
104
|
-
|
105
|
-
}
|
95
|
+
document.head.appendChild(htmlElement);
|
96
|
+
});
|
106
97
|
|
107
|
-
|
108
|
-
}
|
98
|
+
areScriptsInserted = true;
|
99
|
+
}, []);
|
109
100
|
|
110
|
-
return {
|
101
|
+
return { insertScriptTags };
|
111
102
|
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { useEffect } from "react";
|
2
|
+
import { useConst } from "powerhooks/useConst";
|
3
|
+
import { id } from "tsafe/id";
|
4
|
+
|
5
|
+
/** Callback is guaranteed to be call only once per component mount event in strict mode */
|
6
|
+
export function useOnFistMount(callback: () => void) {
|
7
|
+
const refHasCallbackBeenCalled = useConst(() => ({ current: id<boolean>(false) }));
|
8
|
+
|
9
|
+
useEffect(() => {
|
10
|
+
if (refHasCallbackBeenCalled.current) {
|
11
|
+
return;
|
12
|
+
}
|
13
|
+
|
14
|
+
callback();
|
15
|
+
|
16
|
+
refHasCallbackBeenCalled.current = true;
|
17
|
+
}, []);
|
18
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Array.prototype.every.js","sourceRoot":"","sources":["../src/tools/Array.prototype.every.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE
|
1
|
+
{"version":3,"file":"Array.prototype.every.js","sourceRoot":"","sources":["../src/tools/Array.prototype.every.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE;IACxB,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,UAAU,UAAe,EAAE,OAAY;QAC3D,YAAY,CAAC;QACb,IAAI,CAAC,EAAE,CAAC,CAAC;QAET,IAAI,IAAI,IAAI,IAAI,EAAE;YACd,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;SACtD;QAED,8DAA8D;QAC9D,4BAA4B;QAC5B,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAErB,mEAAmE;QACnE,sCAAsC;QACtC,oCAAoC;QACpC,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QAEzB,sEAAsE;QACtE,IACI,OAAO,UAAU,KAAK,UAAU;YAChC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,mBAAmB,EACpE;YACE,MAAM,IAAI,SAAS,EAAE,CAAC;SACzB;QAED,yEAAyE;QACzE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;YACtB,CAAC,GAAG,OAAO,CAAC;SACf;QAED,iBAAiB;QACjB,CAAC,GAAG,CAAC,CAAC;QAEN,2BAA2B;QAC3B,OAAO,CAAC,GAAG,GAAG,EAAE;YACZ,IAAI,MAAM,CAAC;YAEX,4BAA4B;YAC5B,yDAAyD;YACzD,oEAAoE;YACpE,mCAAmC;YACnC,qCAAqC;YACrC,+BAA+B;YAC/B,IAAI,CAAC,IAAI,CAAC,EAAE;gBACR,IAAI,UAAU,CAAC;gBACf,iEAAiE;gBACjE,4BAA4B;gBAC5B,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAEd,uEAAuE;gBACvE,+DAA+D;gBAC/D,2CAA2C;gBAC3C,iDAAiD;gBACjD,IAAI,CAAC;oBAAE,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;;oBAChD,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAE3C,wDAAwD;gBACxD,IAAI,CAAC,UAAU,EAAE;oBACb,OAAO,KAAK,CAAC;iBAChB;aACJ;YACD,CAAC,EAAE,CAAC;SACP;QACD,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;CACL"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export type ExtractAfterStartingWith<Prefix extends string, StrEnum> = StrEnum extends `${Prefix}${infer U}` ? U : never;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ExtractAfterStartingWith.js","sourceRoot":"","sources":["../src/tools/ExtractAfterStartingWith.ts"],"names":[],"mappings":""}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"HTMLElement.prototype.prepend.js","sourceRoot":"","sources":["../src/tools/HTMLElement.prototype.prepend.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE
|
1
|
+
{"version":3,"file":"HTMLElement.prototype.prepend.js","sourceRoot":"","sources":["../src/tools/HTMLElement.prototype.prepend.ts"],"names":[],"mappings":";AAAA,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE;IAChC,WAAW,CAAC,SAAS,CAAC,OAAO,GAAG,UAAU,SAAS;QAC/C,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE;YAC/B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;SAC5E;QAED,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC,CAAC;CACL"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"StatefulObservable.js","sourceRoot":"","sources":["../../src/tools/StatefulObservable/StatefulObservable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAW9B,MAAM,UAAU,wBAAwB,CACpC,eAAwB;IAExB,MAAM,aAAa,GAA0B,EAAE,CAAC;IAEhD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QACvB,IAAI,YAAY,GAAoB,SAAS,CAAC;QAE9C,SAAS,GAAG,CAAC,IAAO;YAChB,YAAY,GAAG,CAAC,IAAI,CAAC,CAAC;YAEtB,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO;YACH,GAAG,EAAE,GAAG,EAAE;gBACN,IAAI,YAAY,KAAK,SAAS,EAAE
|
1
|
+
{"version":3,"file":"StatefulObservable.js","sourceRoot":"","sources":["../../src/tools/StatefulObservable/StatefulObservable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAW9B,MAAM,UAAU,wBAAwB,CACpC,eAAwB;IAExB,MAAM,aAAa,GAA0B,EAAE,CAAC;IAEhD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;QACvB,IAAI,YAAY,GAAoB,SAAS,CAAC;QAE9C,SAAS,GAAG,CAAC,IAAO;YAChB,YAAY,GAAG,CAAC,IAAI,CAAC,CAAC;YAEtB,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO;YACH,GAAG,EAAE,GAAG,EAAE;gBACN,IAAI,YAAY,KAAK,SAAS,EAAE;oBAC5B,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;oBACvB,MAAM,CAAC,CAAC,EAAE,CAAY,YAAY,CAAC,CAAC,CAAC;iBACxC;gBACD,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YACD,GAAG;SACN,CAAC;IACN,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,MAAM,CAAC,cAAc,CACxB;QACI,OAAO,EAAE,IAAgB;QACzB,SAAS,EAAE,CAAC,IAAuB,EAAE,EAAE;YACnC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEzB,OAAO;gBACH,WAAW,EAAE,GAAG,EAAE,CACd,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;aAC3D,CAAC;QACN,CAAC;KACJ,EACD,SAAS,EACT;QACI,UAAU,EAAE,IAAI;QAChB,GAAG;QACH,GAAG;KACN,CACJ,CAAC;AACN,CAAC"}
|
@@ -2,4 +2,4 @@ import type { StatefulObservable } from "../StatefulObservable";
|
|
2
2
|
/**
|
3
3
|
* Equivalent of https://docs.evt.land/api/react-hooks
|
4
4
|
* */
|
5
|
-
export declare function useRerenderOnChange(
|
5
|
+
export declare function useRerenderOnChange(obs: StatefulObservable<unknown>): void;
|
@@ -3,12 +3,12 @@ import { useState } from "react";
|
|
3
3
|
/**
|
4
4
|
* Equivalent of https://docs.evt.land/api/react-hooks
|
5
5
|
* */
|
6
|
-
export function useRerenderOnChange(
|
6
|
+
export function useRerenderOnChange(obs) {
|
7
7
|
//NOTE: We use function in case the state is a function
|
8
|
-
const [, setCurrent] = useState(() =>
|
8
|
+
const [, setCurrent] = useState(() => obs.current);
|
9
9
|
useObservable(({ registerSubscription }) => {
|
10
|
-
const subscription =
|
10
|
+
const subscription = obs.subscribe(current => setCurrent(() => current));
|
11
11
|
registerSubscription(subscription);
|
12
|
-
}, [
|
12
|
+
}, [obs]);
|
13
13
|
}
|
14
14
|
//# sourceMappingURL=useRerenderOnChange.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useRerenderOnChange.js","sourceRoot":"","sources":["../../../src/tools/StatefulObservable/hooks/useRerenderOnChange.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC;;KAEK;AACL,MAAM,UAAU,mBAAmB,CAAC,
|
1
|
+
{"version":3,"file":"useRerenderOnChange.js","sourceRoot":"","sources":["../../../src/tools/StatefulObservable/hooks/useRerenderOnChange.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC;;KAEK;AACL,MAAM,UAAU,mBAAmB,CAAC,GAAgC;IAChE,uDAAuD;IACvD,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,aAAa,CACT,CAAC,EAAE,oBAAoB,EAAE,EAAE,EAAE;QACzB,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC,EACD,CAAC,GAAG,CAAC,CACR,CAAC;AACN,CAAC"}
|
package/tools/ValueOf.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ValueOf.js","sourceRoot":"","sources":["../src/tools/ValueOf.ts"],"names":[],"mappings":""}
|