mogh_ui 1.2.10 → 1.3.0
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/auth/index.cjs.map +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/login/index.cjs.map +1 -1
- package/dist/auth/login/index.js.map +1 -1
- package/dist/formatting.cjs +12 -0
- package/dist/formatting.cjs.map +1 -1
- package/dist/formatting.d.ts +3 -0
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +11 -0
- package/dist/formatting.js.map +1 -1
- package/package.json +3 -3
package/dist/auth/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import { notifications } from \"@mantine/notifications\";\nimport {\n useMutation,\n UseMutationOptions,\n useQuery,\n} from \"@tanstack/react-query\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { sanitizeQueryInner } from \"./utils\";\n\nexport * from \"./login\";\nexport * from \"./profile\";\nexport * from \"./utils\";\n\nexport let AUTH_URL: string;\n\n/**\n * Set the global auth url.\n * Make sure to call this before first render.\n * @param url The global url\n */\nexport function setAuthUrl(url: string) {\n AUTH_URL = url;\n}\n\nexport function authClient() {\n return MoghAuth.MoghAuthClient(AUTH_URL, MoghAuth.LOGIN_TOKENS
|
|
1
|
+
{"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import { notifications } from \"@mantine/notifications\";\nimport {\n useMutation,\n UseMutationOptions,\n useQuery,\n} from \"@tanstack/react-query\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { sanitizeQueryInner } from \"./utils\";\n\nexport * from \"./login\";\nexport * from \"./profile\";\nexport * from \"./utils\";\n\nexport let AUTH_URL: string;\n\n/**\n * Set the global auth url.\n * Make sure to call this before first render.\n * @param url The global url\n */\nexport function setAuthUrl(url: string) {\n AUTH_URL = url;\n}\n\nexport function authClient() {\n return MoghAuth.MoghAuthClient(AUTH_URL, MoghAuth.LOGIN_TOKENS!.jwt());\n}\n\nexport function useLoginOptions() {\n return useQuery({\n queryKey: [\"GetLoginOptions\"],\n queryFn: () => authClient().login(\"GetLoginOptions\", {}),\n });\n}\n\nexport function useLogin<\n T extends MoghAuth.Types.LoginRequest[\"type\"],\n R extends Extract<MoghAuth.Types.LoginRequest, { type: T }>,\n P extends R[\"params\"],\n C extends Omit<\n UseMutationOptions<MoghAuth.LoginResponses[T], unknown, P, unknown>,\n \"mutationKey\" | \"mutationFn\"\n >,\n>(type: T, config?: C) {\n return useMutation({\n mutationKey: [type],\n mutationFn: (params: P) => authClient().login<T, R>(type, params),\n onError: (e: { result: { error?: string; trace?: string[] } }, ...args) => {\n console.log(\"Login error:\", e);\n const msg = e.result.error ?? \"Unknown error. See console.\";\n const detail = e.result?.trace\n ?.map((msg) => msg[0].toUpperCase() + msg.slice(1))\n .join(\" | \");\n let msg_log = msg ? msg[0].toUpperCase() + msg.slice(1) + \" | \" : \"\";\n if (detail) {\n msg_log += detail + \" | \";\n }\n notifications.show({\n title: `Login request ${type} failed`,\n message: `${msg_log}See console for details`,\n color: \"red\",\n });\n config?.onError && config.onError(e, ...args);\n },\n ...config,\n });\n}\n\nexport function useUserId() {\n return useQuery({\n queryKey: [\"\"],\n queryFn: () => authClient().manage(\"GetUserId\", {}),\n enabled: !!MoghAuth.LOGIN_TOKENS!.jwt(),\n });\n}\n\nexport function useManageAuth<\n T extends MoghAuth.Types.ManageRequest[\"type\"],\n R extends Extract<MoghAuth.Types.ManageRequest, { type: T }>,\n P extends R[\"params\"],\n C extends Omit<\n UseMutationOptions<MoghAuth.ManageResponses[T], unknown, P, unknown>,\n \"mutationKey\" | \"mutationFn\"\n >,\n>(type: T, config?: C) {\n return useMutation({\n mutationKey: [type],\n mutationFn: (params: P) => authClient().manage<T, R>(type, params),\n onError: (e: { result: { error?: string; trace?: string[] } }, ...args) => {\n console.log(\"Manage auth error:\", e);\n const msg = e.result.error ?? \"Unknown error. See console.\";\n const detail = e.result?.trace\n ?.map((msg) => msg[0].toUpperCase() + msg.slice(1))\n .join(\" | \");\n let msg_log = msg ? msg[0].toUpperCase() + msg.slice(1) + \" | \" : \"\";\n if (detail) {\n msg_log += detail + \" | \";\n }\n notifications.show({\n title: `Manage auth request ${type} failed`,\n message: `${msg_log}See console for details`,\n color: \"red\",\n });\n config?.onError && config.onError(e, ...args);\n },\n ...config,\n });\n}\n\nlet jwt_redeem_sent = false;\nlet passkey_sent = false;\n\n/// returns whether to show login / loading screen depending on state of exchange token loop\nexport function useAuthState() {\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS!.add_and_change(jwt);\n sanitizeQueryInner(search);\n };\n const { mutate: redeemJwt } = useLogin(\"ExchangeForJwt\", {\n onSuccess,\n });\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess,\n });\n const search = new URLSearchParams(location.search);\n\n const _passkey = search.get(\"passkey\");\n const passkey = _passkey\n ? JSON.parse(MoghAuth.Passkey.base64UrlDecode(_passkey))\n : null;\n\n // guard against multiple reqs sent\n // maybe isPending would do this but not sure about with render loop, this for sure will.\n if (passkey && !passkey_sent) {\n navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(passkey))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n passkey_sent = true;\n }\n\n const jwt_redeem_ready = search.get(\"redeem_ready\") === \"true\";\n\n // guard against multiple reqs sent\n // maybe isPending would do this but not sure about with render loop, this for sure will.\n if (jwt_redeem_ready && !jwt_redeem_sent) {\n redeemJwt({});\n jwt_redeem_sent = true;\n }\n\n return {\n jwt_redeem_ready,\n passkey_pending: !!passkey,\n totp: search.get(\"totp\") === \"true\",\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA8B;AAC9B,yBAIO;AACP,eAA0B;AAC1B,mBAAmC;AAEnC,yBAAc,oBATd;AAUA,yBAAc,sBAVd;AAWA,yBAAc,oBAXd;AAaO,IAAI;AAOJ,SAAS,WAAW,KAAa;AACtC,aAAW;AACb;AAEO,SAAS,aAAa;AAC3B,SAAO,SAAS,eAAe,UAAU,SAAS,aAAc,IAAI,CAAC;AACvE;AAEO,SAAS,kBAAkB;AAChC,aAAO,6BAAS;AAAA,IACd,UAAU,CAAC,iBAAiB;AAAA,IAC5B,SAAS,MAAM,WAAW,EAAE,MAAM,mBAAmB,CAAC,CAAC;AAAA,EACzD,CAAC;AACH;AAEO,SAAS,SAQd,MAAS,QAAY;AACrB,aAAO,gCAAY;AAAA,IACjB,aAAa,CAAC,IAAI;AAAA,IAClB,YAAY,CAAC,WAAc,WAAW,EAAE,MAAY,MAAM,MAAM;AAAA,IAChE,SAAS,CAAC,MAAwD,SAAS;AACzE,cAAQ,IAAI,gBAAgB,CAAC;AAC7B,YAAM,MAAM,EAAE,OAAO,SAAS;AAC9B,YAAM,SAAS,EAAE,QAAQ,OACrB,IAAI,CAACA,SAAQA,KAAI,CAAC,EAAE,YAAY,IAAIA,KAAI,MAAM,CAAC,CAAC,EACjD,KAAK,KAAK;AACb,UAAI,UAAU,MAAM,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,IAAI,QAAQ;AAClE,UAAI,QAAQ;AACV,mBAAW,SAAS;AAAA,MACtB;AACA,yCAAc,KAAK;AAAA,QACjB,OAAO,iBAAiB,IAAI;AAAA,QAC5B,SAAS,GAAG,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AACD,cAAQ,WAAW,OAAO,QAAQ,GAAG,GAAG,IAAI;AAAA,IAC9C;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,YAAY;AAC1B,aAAO,6BAAS;AAAA,IACd,UAAU,CAAC,EAAE;AAAA,IACb,SAAS,MAAM,WAAW,EAAE,OAAO,aAAa,CAAC,CAAC;AAAA,IAClD,SAAS,CAAC,CAAC,SAAS,aAAc,IAAI;AAAA,EACxC,CAAC;AACH;AAEO,SAAS,cAQd,MAAS,QAAY;AACrB,aAAO,gCAAY;AAAA,IACjB,aAAa,CAAC,IAAI;AAAA,IAClB,YAAY,CAAC,WAAc,WAAW,EAAE,OAAa,MAAM,MAAM;AAAA,IACjE,SAAS,CAAC,MAAwD,SAAS;AACzE,cAAQ,IAAI,sBAAsB,CAAC;AACnC,YAAM,MAAM,EAAE,OAAO,SAAS;AAC9B,YAAM,SAAS,EAAE,QAAQ,OACrB,IAAI,CAACA,SAAQA,KAAI,CAAC,EAAE,YAAY,IAAIA,KAAI,MAAM,CAAC,CAAC,EACjD,KAAK,KAAK;AACb,UAAI,UAAU,MAAM,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,IAAI,QAAQ;AAClE,UAAI,QAAQ;AACV,mBAAW,SAAS;AAAA,MACtB;AACA,yCAAc,KAAK;AAAA,QACjB,OAAO,uBAAuB,IAAI;AAAA,QAClC,SAAS,GAAG,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AACD,cAAQ,WAAW,OAAO,QAAQ,GAAG,GAAG,IAAI;AAAA,IAC9C;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAEA,IAAI,kBAAkB;AACtB,IAAI,eAAe;AAGZ,SAAS,eAAe;AAC7B,QAAM,YAAY,CAAC,EAAE,IAAI,MAAkC;AACzD,aAAS,aAAc,eAAe,GAAG;AACzC,yCAAmB,MAAM;AAAA,EAC3B;AACA,QAAM,EAAE,QAAQ,UAAU,IAAI,SAAS,kBAAkB;AAAA,IACvD;AAAA,EACF,CAAC;AACD,QAAM,EAAE,QAAQ,qBAAqB,IAAI,SAAS,wBAAwB;AAAA,IACxE;AAAA,EACF,CAAC;AACD,QAAM,SAAS,IAAI,gBAAgB,SAAS,MAAM;AAElD,QAAM,WAAW,OAAO,IAAI,SAAS;AACrC,QAAM,UAAU,WACZ,KAAK,MAAM,SAAS,QAAQ,gBAAgB,QAAQ,CAAC,IACrD;AAIJ,MAAI,WAAW,CAAC,cAAc;AAC5B,cAAU,YACP,IAAI,SAAS,QAAQ,gCAAgC,OAAO,CAAC,EAC7D,KAAK,CAAC,eAAe,qBAAqB,EAAE,WAAW,CAAC,CAAC,EACzD,MAAM,CAAC,MAAM;AACZ,cAAQ,MAAM,CAAC;AACf,yCAAc,KAAK;AAAA,QACjB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AACH,mBAAe;AAAA,EACjB;AAEA,QAAM,mBAAmB,OAAO,IAAI,cAAc,MAAM;AAIxD,MAAI,oBAAoB,CAAC,iBAAiB;AACxC,cAAU,CAAC,CAAC;AACZ,sBAAkB;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,CAAC,CAAC;AAAA,IACnB,MAAM,OAAO,IAAI,MAAM,MAAM;AAAA,EAC/B;AACF;","names":["msg"]}
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import { notifications } from \"@mantine/notifications\";\nimport {\n useMutation,\n UseMutationOptions,\n useQuery,\n} from \"@tanstack/react-query\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { sanitizeQueryInner } from \"./utils\";\n\nexport * from \"./login\";\nexport * from \"./profile\";\nexport * from \"./utils\";\n\nexport let AUTH_URL: string;\n\n/**\n * Set the global auth url.\n * Make sure to call this before first render.\n * @param url The global url\n */\nexport function setAuthUrl(url: string) {\n AUTH_URL = url;\n}\n\nexport function authClient() {\n return MoghAuth.MoghAuthClient(AUTH_URL, MoghAuth.LOGIN_TOKENS
|
|
1
|
+
{"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import { notifications } from \"@mantine/notifications\";\nimport {\n useMutation,\n UseMutationOptions,\n useQuery,\n} from \"@tanstack/react-query\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { sanitizeQueryInner } from \"./utils\";\n\nexport * from \"./login\";\nexport * from \"./profile\";\nexport * from \"./utils\";\n\nexport let AUTH_URL: string;\n\n/**\n * Set the global auth url.\n * Make sure to call this before first render.\n * @param url The global url\n */\nexport function setAuthUrl(url: string) {\n AUTH_URL = url;\n}\n\nexport function authClient() {\n return MoghAuth.MoghAuthClient(AUTH_URL, MoghAuth.LOGIN_TOKENS!.jwt());\n}\n\nexport function useLoginOptions() {\n return useQuery({\n queryKey: [\"GetLoginOptions\"],\n queryFn: () => authClient().login(\"GetLoginOptions\", {}),\n });\n}\n\nexport function useLogin<\n T extends MoghAuth.Types.LoginRequest[\"type\"],\n R extends Extract<MoghAuth.Types.LoginRequest, { type: T }>,\n P extends R[\"params\"],\n C extends Omit<\n UseMutationOptions<MoghAuth.LoginResponses[T], unknown, P, unknown>,\n \"mutationKey\" | \"mutationFn\"\n >,\n>(type: T, config?: C) {\n return useMutation({\n mutationKey: [type],\n mutationFn: (params: P) => authClient().login<T, R>(type, params),\n onError: (e: { result: { error?: string; trace?: string[] } }, ...args) => {\n console.log(\"Login error:\", e);\n const msg = e.result.error ?? \"Unknown error. See console.\";\n const detail = e.result?.trace\n ?.map((msg) => msg[0].toUpperCase() + msg.slice(1))\n .join(\" | \");\n let msg_log = msg ? msg[0].toUpperCase() + msg.slice(1) + \" | \" : \"\";\n if (detail) {\n msg_log += detail + \" | \";\n }\n notifications.show({\n title: `Login request ${type} failed`,\n message: `${msg_log}See console for details`,\n color: \"red\",\n });\n config?.onError && config.onError(e, ...args);\n },\n ...config,\n });\n}\n\nexport function useUserId() {\n return useQuery({\n queryKey: [\"\"],\n queryFn: () => authClient().manage(\"GetUserId\", {}),\n enabled: !!MoghAuth.LOGIN_TOKENS!.jwt(),\n });\n}\n\nexport function useManageAuth<\n T extends MoghAuth.Types.ManageRequest[\"type\"],\n R extends Extract<MoghAuth.Types.ManageRequest, { type: T }>,\n P extends R[\"params\"],\n C extends Omit<\n UseMutationOptions<MoghAuth.ManageResponses[T], unknown, P, unknown>,\n \"mutationKey\" | \"mutationFn\"\n >,\n>(type: T, config?: C) {\n return useMutation({\n mutationKey: [type],\n mutationFn: (params: P) => authClient().manage<T, R>(type, params),\n onError: (e: { result: { error?: string; trace?: string[] } }, ...args) => {\n console.log(\"Manage auth error:\", e);\n const msg = e.result.error ?? \"Unknown error. See console.\";\n const detail = e.result?.trace\n ?.map((msg) => msg[0].toUpperCase() + msg.slice(1))\n .join(\" | \");\n let msg_log = msg ? msg[0].toUpperCase() + msg.slice(1) + \" | \" : \"\";\n if (detail) {\n msg_log += detail + \" | \";\n }\n notifications.show({\n title: `Manage auth request ${type} failed`,\n message: `${msg_log}See console for details`,\n color: \"red\",\n });\n config?.onError && config.onError(e, ...args);\n },\n ...config,\n });\n}\n\nlet jwt_redeem_sent = false;\nlet passkey_sent = false;\n\n/// returns whether to show login / loading screen depending on state of exchange token loop\nexport function useAuthState() {\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS!.add_and_change(jwt);\n sanitizeQueryInner(search);\n };\n const { mutate: redeemJwt } = useLogin(\"ExchangeForJwt\", {\n onSuccess,\n });\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess,\n });\n const search = new URLSearchParams(location.search);\n\n const _passkey = search.get(\"passkey\");\n const passkey = _passkey\n ? JSON.parse(MoghAuth.Passkey.base64UrlDecode(_passkey))\n : null;\n\n // guard against multiple reqs sent\n // maybe isPending would do this but not sure about with render loop, this for sure will.\n if (passkey && !passkey_sent) {\n navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(passkey))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n passkey_sent = true;\n }\n\n const jwt_redeem_ready = search.get(\"redeem_ready\") === \"true\";\n\n // guard against multiple reqs sent\n // maybe isPending would do this but not sure about with render loop, this for sure will.\n if (jwt_redeem_ready && !jwt_redeem_sent) {\n redeemJwt({});\n jwt_redeem_sent = true;\n }\n\n return {\n jwt_redeem_ready,\n passkey_pending: !!passkey,\n totp: search.get(\"totp\") === \"true\",\n };\n}\n"],"mappings":"AAAA,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AACP,YAAY,cAAc;AAC1B,SAAS,0BAA0B;AAEnC,cAAc;AACd,cAAc;AACd,cAAc;AAEP,IAAI;AAOJ,SAAS,WAAW,KAAa;AACtC,aAAW;AACb;AAEO,SAAS,aAAa;AAC3B,SAAO,SAAS,eAAe,UAAU,SAAS,aAAc,IAAI,CAAC;AACvE;AAEO,SAAS,kBAAkB;AAChC,SAAO,SAAS;AAAA,IACd,UAAU,CAAC,iBAAiB;AAAA,IAC5B,SAAS,MAAM,WAAW,EAAE,MAAM,mBAAmB,CAAC,CAAC;AAAA,EACzD,CAAC;AACH;AAEO,SAAS,SAQd,MAAS,QAAY;AACrB,SAAO,YAAY;AAAA,IACjB,aAAa,CAAC,IAAI;AAAA,IAClB,YAAY,CAAC,WAAc,WAAW,EAAE,MAAY,MAAM,MAAM;AAAA,IAChE,SAAS,CAAC,MAAwD,SAAS;AACzE,cAAQ,IAAI,gBAAgB,CAAC;AAC7B,YAAM,MAAM,EAAE,OAAO,SAAS;AAC9B,YAAM,SAAS,EAAE,QAAQ,OACrB,IAAI,CAACA,SAAQA,KAAI,CAAC,EAAE,YAAY,IAAIA,KAAI,MAAM,CAAC,CAAC,EACjD,KAAK,KAAK;AACb,UAAI,UAAU,MAAM,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,IAAI,QAAQ;AAClE,UAAI,QAAQ;AACV,mBAAW,SAAS;AAAA,MACtB;AACA,oBAAc,KAAK;AAAA,QACjB,OAAO,iBAAiB,IAAI;AAAA,QAC5B,SAAS,GAAG,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AACD,cAAQ,WAAW,OAAO,QAAQ,GAAG,GAAG,IAAI;AAAA,IAC9C;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,YAAY;AAC1B,SAAO,SAAS;AAAA,IACd,UAAU,CAAC,EAAE;AAAA,IACb,SAAS,MAAM,WAAW,EAAE,OAAO,aAAa,CAAC,CAAC;AAAA,IAClD,SAAS,CAAC,CAAC,SAAS,aAAc,IAAI;AAAA,EACxC,CAAC;AACH;AAEO,SAAS,cAQd,MAAS,QAAY;AACrB,SAAO,YAAY;AAAA,IACjB,aAAa,CAAC,IAAI;AAAA,IAClB,YAAY,CAAC,WAAc,WAAW,EAAE,OAAa,MAAM,MAAM;AAAA,IACjE,SAAS,CAAC,MAAwD,SAAS;AACzE,cAAQ,IAAI,sBAAsB,CAAC;AACnC,YAAM,MAAM,EAAE,OAAO,SAAS;AAC9B,YAAM,SAAS,EAAE,QAAQ,OACrB,IAAI,CAACA,SAAQA,KAAI,CAAC,EAAE,YAAY,IAAIA,KAAI,MAAM,CAAC,CAAC,EACjD,KAAK,KAAK;AACb,UAAI,UAAU,MAAM,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,IAAI,QAAQ;AAClE,UAAI,QAAQ;AACV,mBAAW,SAAS;AAAA,MACtB;AACA,oBAAc,KAAK;AAAA,QACjB,OAAO,uBAAuB,IAAI;AAAA,QAClC,SAAS,GAAG,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AACD,cAAQ,WAAW,OAAO,QAAQ,GAAG,GAAG,IAAI;AAAA,IAC9C;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAEA,IAAI,kBAAkB;AACtB,IAAI,eAAe;AAGZ,SAAS,eAAe;AAC7B,QAAM,YAAY,CAAC,EAAE,IAAI,MAAkC;AACzD,aAAS,aAAc,eAAe,GAAG;AACzC,uBAAmB,MAAM;AAAA,EAC3B;AACA,QAAM,EAAE,QAAQ,UAAU,IAAI,SAAS,kBAAkB;AAAA,IACvD;AAAA,EACF,CAAC;AACD,QAAM,EAAE,QAAQ,qBAAqB,IAAI,SAAS,wBAAwB;AAAA,IACxE;AAAA,EACF,CAAC;AACD,QAAM,SAAS,IAAI,gBAAgB,SAAS,MAAM;AAElD,QAAM,WAAW,OAAO,IAAI,SAAS;AACrC,QAAM,UAAU,WACZ,KAAK,MAAM,SAAS,QAAQ,gBAAgB,QAAQ,CAAC,IACrD;AAIJ,MAAI,WAAW,CAAC,cAAc;AAC5B,cAAU,YACP,IAAI,SAAS,QAAQ,gCAAgC,OAAO,CAAC,EAC7D,KAAK,CAAC,eAAe,qBAAqB,EAAE,WAAW,CAAC,CAAC,EACzD,MAAM,CAAC,MAAM;AACZ,cAAQ,MAAM,CAAC;AACf,oBAAc,KAAK;AAAA,QACjB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AACH,mBAAe;AAAA,EACjB;AAEA,QAAM,mBAAmB,OAAO,IAAI,cAAc,MAAM;AAIxD,MAAI,oBAAoB,CAAC,iBAAiB;AACxC,cAAU,CAAC,CAAC;AACZ,sBAAkB;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,CAAC,CAAC;AAAA,IACnB,MAAM,OAAO,IAAI,MAAM,MAAM;AAAA,EAC/B;AACF;","names":["msg"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/login/index.tsx"],"sourcesContent":["import {\n Button,\n Center,\n Fieldset,\n Group,\n Loader,\n PasswordInput,\n Text,\n TextInput,\n} from \"@mantine/core\";\nimport { useForm } from \"@mantine/form\";\nimport { notifications } from \"@mantine/notifications\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { AlertTriangle, KeyRound } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport LoginHeader from \"./header\";\nimport {\n authClient,\n BackButton,\n sanitizeQuery,\n useLogin,\n useLoginOptions,\n useUserId,\n} from \"../..\";\n\nexport interface LoginBrandingProps {\n appName: string;\n iconLink: string;\n iconLinkAlt: string;\n}\n\nexport function LoginPage({\n passkeyIsPending: _passkeyIsPending,\n totpIsPending: _totpIsPending,\n onLogin,\n exampleConfigLink,\n ...branding\n}: {\n passkeyIsPending?: boolean;\n totpIsPending?: boolean;\n onLogin?: () => void;\n exampleConfigLink: string;\n} & LoginBrandingProps) {\n const options = useLoginOptions().data;\n const [passkeyIsPending, setPasskeyPending] = useState(\n _passkeyIsPending ?? false,\n );\n const [totpIsPending, setTotpPending] = useState(_totpIsPending ?? false);\n const secondFactorPending = passkeyIsPending || totpIsPending;\n\n const alreadyLoggedIn = useUserId().data?.id!!;\n\n // Auto-redirect to OIDC provider if configured and disableAutoLogin is not set\n useEffect(() => {\n if (options?.oidc_auto_redirect && options?.oidc && !secondFactorPending) {\n const params = new URLSearchParams(location.search);\n if (!params.has(\"disableAutoLogin\")) {\n authClient().externalLogin(MoghAuth.Types.ExternalLoginProvider.Oidc);\n }\n }\n }, [options?.oidc_auto_redirect, options?.oidc, secondFactorPending]);\n\n // If signing in another user, need to redirect away from /login manually\n const maybeNavigate = location.pathname.startsWith(\"/login\")\n ? () =>\n location.replace(\n new URLSearchParams(location.search).get(\"backto\") ?? \"/\",\n )\n : undefined;\n\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS.add_and_change(jwt);\n onLogin?.();\n maybeNavigate?.();\n };\n\n const secondFactorOnSuccess = (res: MoghAuth.Types.JwtResponse) => {\n sanitizeQuery();\n onSuccess(res);\n };\n\n const { mutate: signup, isPending: signupPending } = useLogin(\n \"SignUpLocalUser\",\n {\n onSuccess,\n },\n );\n\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess: secondFactorOnSuccess,\n });\n\n const { mutate: completeTotpLogin, isPending: totpPending } = useLogin(\n \"CompleteTotpLogin\",\n {\n onSuccess: secondFactorOnSuccess,\n },\n );\n\n const { mutate: login, isPending: loginPending } = useLogin(\n \"LoginLocalUser\",\n {\n onSuccess: ({ type, data }) => {\n switch (type) {\n case \"Jwt\":\n return onSuccess(data);\n case \"Passkey\":\n setPasskeyPending(true);\n return navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(data))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n case \"Totp\":\n return setTotpPending(true);\n }\n },\n },\n );\n\n const noAuthConfigured =\n options !== undefined &&\n Object.values(options).every((value) => value === false);\n\n const showSignUp = options !== undefined && !options.registration_disabled;\n\n const localForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n username: \"\",\n password: \"\",\n },\n validate: {\n username: (username) =>\n username.length ? null : \"Username cannot be empty\",\n password: (password) =>\n password.length ? null : \"Password cannot be empty\",\n },\n });\n\n const totpForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n code: \"\",\n },\n validate: {\n code: (code) => (code.length === 6 ? null : \"Code should be 6 digits\"),\n },\n });\n\n return (\n <Center h=\"80vh\">\n <Fieldset\n legend={\n <LoginHeader\n secondFactorPending={secondFactorPending}\n {...branding}\n />\n }\n component=\"form\"\n onSubmit={\n totpIsPending\n ? totpForm.onSubmit((form) => completeTotpLogin(form))\n : (localForm.onSubmit((form) => login(form)) as any)\n }\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1rem\" }}\n miw={{ base: \"95vw\", xs: \"530px\" }}\n maw=\"95vw\"\n >\n {options?.local && !secondFactorPending && (\n <>\n <TextInput\n {...localForm.getInputProps(\"username\")}\n autoFocus\n label=\"Username\"\n placeholder=\"Enter username\"\n autoComplete=\"username\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"username\")}\n />\n <PasswordInput\n {...localForm.getInputProps(\"password\")}\n label=\"Password\"\n placeholder=\"Enter password\"\n autoComplete=\"password\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"password\")}\n />\n <Group mt=\"sm\" justify=\"space-between\">\n {alreadyLoggedIn && (\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n )}\n <Group justify=\"end\">\n {showSignUp && (\n <Button\n variant=\"outline\"\n w={110}\n onClick={localForm.onSubmit((form) => signup(form)) as any}\n loading={signupPending}\n >\n Sign Up\n </Button>\n )}\n <Button w={110} type=\"submit\" loading={loginPending}>\n Log In\n </Button>\n </Group>\n </Group>\n </>\n )}\n\n {alreadyLoggedIn && !(options?.local && !secondFactorPending) && (\n <Group>\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n </Group>\n )}\n\n {passkeyIsPending && (\n <Group justify=\"center\" my=\"lg\">\n <KeyRound size=\"1.5rem\" />\n <Text size=\"lg\">Provide your passkey to finish login...</Text>\n <Loader />\n </Group>\n )}\n\n {totpIsPending && (\n <>\n <TextInput\n {...totpForm.getInputProps(\"code\")}\n label={\n <Group gap=\"sm\">\n <KeyRound size=\"1rem\" />\n 2FA Code\n </Group>\n }\n autoComplete=\"code\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n autoFocus\n />\n <Group justify=\"end\">\n <Button\n w={110}\n variant=\"filled\"\n type=\"submit\"\n loading={totpPending}\n >\n Log In\n </Button>\n </Group>\n </>\n )}\n\n {noAuthConfigured && (\n <Group my=\"lg\">\n <AlertTriangle size=\"2rem\" />\n <Text>\n No login methods have been configured. <br />\n See the{\" \"}\n <a\n href={exampleConfigLink}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"hover-underline\"\n >\n <b>example config</b>\n </a>{\" \"}\n for information on configuring auth.\n </Text>\n </Group>\n )}\n </Fieldset>\n </Center>\n );\n}\n"],"mappings":"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","names":["import_react","LoginHeader"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/login/index.tsx"],"sourcesContent":["import {\n Button,\n Center,\n Fieldset,\n Group,\n Loader,\n PasswordInput,\n Text,\n TextInput,\n} from \"@mantine/core\";\nimport { useForm } from \"@mantine/form\";\nimport { notifications } from \"@mantine/notifications\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { AlertTriangle, KeyRound } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport LoginHeader from \"./header\";\nimport {\n authClient,\n BackButton,\n sanitizeQuery,\n useLogin,\n useLoginOptions,\n useUserId,\n} from \"../..\";\n\nexport interface LoginBrandingProps {\n appName: string;\n iconLink: string;\n iconLinkAlt: string;\n}\n\nexport function LoginPage({\n passkeyIsPending: _passkeyIsPending,\n totpIsPending: _totpIsPending,\n onLogin,\n exampleConfigLink,\n ...branding\n}: {\n passkeyIsPending?: boolean;\n totpIsPending?: boolean;\n onLogin?: () => void;\n exampleConfigLink: string;\n} & LoginBrandingProps) {\n const options = useLoginOptions().data;\n const [passkeyIsPending, setPasskeyPending] = useState(\n _passkeyIsPending ?? false,\n );\n const [totpIsPending, setTotpPending] = useState(_totpIsPending ?? false);\n const secondFactorPending = passkeyIsPending || totpIsPending;\n\n const alreadyLoggedIn = useUserId().data?.id!!;\n\n // Auto-redirect to OIDC provider if configured and disableAutoLogin is not set\n useEffect(() => {\n if (options?.oidc_auto_redirect && options?.oidc && !secondFactorPending) {\n const params = new URLSearchParams(location.search);\n if (!params.has(\"disableAutoLogin\")) {\n authClient().externalLogin(MoghAuth.Types.ExternalLoginProvider.Oidc);\n }\n }\n }, [options?.oidc_auto_redirect, options?.oidc, secondFactorPending]);\n\n // If signing in another user, need to redirect away from /login manually\n const maybeNavigate = location.pathname.startsWith(\"/login\")\n ? () =>\n location.replace(\n new URLSearchParams(location.search).get(\"backto\") ?? \"/\",\n )\n : undefined;\n\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS!.add_and_change(jwt);\n onLogin?.();\n maybeNavigate?.();\n };\n\n const secondFactorOnSuccess = (res: MoghAuth.Types.JwtResponse) => {\n sanitizeQuery();\n onSuccess(res);\n };\n\n const { mutate: signup, isPending: signupPending } = useLogin(\n \"SignUpLocalUser\",\n {\n onSuccess,\n },\n );\n\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess: secondFactorOnSuccess,\n });\n\n const { mutate: completeTotpLogin, isPending: totpPending } = useLogin(\n \"CompleteTotpLogin\",\n {\n onSuccess: secondFactorOnSuccess,\n },\n );\n\n const { mutate: login, isPending: loginPending } = useLogin(\n \"LoginLocalUser\",\n {\n onSuccess: ({ type, data }) => {\n switch (type) {\n case \"Jwt\":\n return onSuccess(data);\n case \"Passkey\":\n setPasskeyPending(true);\n return navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(data))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n case \"Totp\":\n return setTotpPending(true);\n }\n },\n },\n );\n\n const noAuthConfigured =\n options !== undefined &&\n Object.values(options).every((value) => value === false);\n\n const showSignUp = options !== undefined && !options.registration_disabled;\n\n const localForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n username: \"\",\n password: \"\",\n },\n validate: {\n username: (username) =>\n username.length ? null : \"Username cannot be empty\",\n password: (password) =>\n password.length ? null : \"Password cannot be empty\",\n },\n });\n\n const totpForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n code: \"\",\n },\n validate: {\n code: (code) => (code.length === 6 ? null : \"Code should be 6 digits\"),\n },\n });\n\n return (\n <Center h=\"80vh\">\n <Fieldset\n legend={\n <LoginHeader\n secondFactorPending={secondFactorPending}\n {...branding}\n />\n }\n component=\"form\"\n onSubmit={\n totpIsPending\n ? totpForm.onSubmit((form) => completeTotpLogin(form))\n : (localForm.onSubmit((form) => login(form)) as any)\n }\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1rem\" }}\n miw={{ base: \"95vw\", xs: \"530px\" }}\n maw=\"95vw\"\n >\n {options?.local && !secondFactorPending && (\n <>\n <TextInput\n {...localForm.getInputProps(\"username\")}\n autoFocus\n label=\"Username\"\n placeholder=\"Enter username\"\n autoComplete=\"username\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"username\")}\n />\n <PasswordInput\n {...localForm.getInputProps(\"password\")}\n label=\"Password\"\n placeholder=\"Enter password\"\n autoComplete=\"password\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"password\")}\n />\n <Group mt=\"sm\" justify=\"space-between\">\n {alreadyLoggedIn && (\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n )}\n <Group justify=\"end\">\n {showSignUp && (\n <Button\n variant=\"outline\"\n w={110}\n onClick={localForm.onSubmit((form) => signup(form)) as any}\n loading={signupPending}\n >\n Sign Up\n </Button>\n )}\n <Button w={110} type=\"submit\" loading={loginPending}>\n Log In\n </Button>\n </Group>\n </Group>\n </>\n )}\n\n {alreadyLoggedIn && !(options?.local && !secondFactorPending) && (\n <Group>\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n </Group>\n )}\n\n {passkeyIsPending && (\n <Group justify=\"center\" my=\"lg\">\n <KeyRound size=\"1.5rem\" />\n <Text size=\"lg\">Provide your passkey to finish login...</Text>\n <Loader />\n </Group>\n )}\n\n {totpIsPending && (\n <>\n <TextInput\n {...totpForm.getInputProps(\"code\")}\n label={\n <Group gap=\"sm\">\n <KeyRound size=\"1rem\" />\n 2FA Code\n </Group>\n }\n autoComplete=\"code\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n autoFocus\n />\n <Group justify=\"end\">\n <Button\n w={110}\n variant=\"filled\"\n type=\"submit\"\n loading={totpPending}\n >\n Log In\n </Button>\n </Group>\n </>\n )}\n\n {noAuthConfigured && (\n <Group my=\"lg\">\n <AlertTriangle size=\"2rem\" />\n <Text>\n No login methods have been configured. <br />\n See the{\" \"}\n <a\n href={exampleConfigLink}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"hover-underline\"\n >\n <b>example config</b>\n </a>{\" \"}\n for information on configuring auth.\n </Text>\n </Group>\n )}\n </Fieldset>\n </Center>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgKU;AAiBE;AAjLZ,kBASO;AACP,kBAAwB;AACxB,2BAA8B;AAC9B,eAA0B;AAC1B,0BAAwC;AACxC,IAAAA,gBAAoC;AACpC,oBAAwB;AACxB,eAOO;AAQA,SAAS,UAAU;AAAA,EACxB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAKwB;AACtB,QAAM,cAAU,0BAAgB,EAAE;AAClC,QAAM,CAAC,kBAAkB,iBAAiB,QAAI;AAAA,IAC5C,qBAAqB;AAAA,EACvB;AACA,QAAM,CAAC,eAAe,cAAc,QAAI,wBAAS,kBAAkB,KAAK;AACxE,QAAM,sBAAsB,oBAAoB;AAEhD,QAAM,sBAAkB,oBAAU,EAAE,MAAM;AAG1C,+BAAU,MAAM;AACd,QAAI,SAAS,sBAAsB,SAAS,QAAQ,CAAC,qBAAqB;AACxE,YAAM,SAAS,IAAI,gBAAgB,SAAS,MAAM;AAClD,UAAI,CAAC,OAAO,IAAI,kBAAkB,GAAG;AACnC,iCAAW,EAAE,cAAc,SAAS,MAAM,sBAAsB,IAAI;AAAA,MACtE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,oBAAoB,SAAS,MAAM,mBAAmB,CAAC;AAGpE,QAAM,gBAAgB,SAAS,SAAS,WAAW,QAAQ,IACvD,MACE,SAAS;AAAA,IACP,IAAI,gBAAgB,SAAS,MAAM,EAAE,IAAI,QAAQ,KAAK;AAAA,EACxD,IACF;AAEJ,QAAM,YAAY,CAAC,EAAE,IAAI,MAAkC;AACzD,aAAS,aAAc,eAAe,GAAG;AACzC,cAAU;AACV,oBAAgB;AAAA,EAClB;AAEA,QAAM,wBAAwB,CAAC,QAAoC;AACjE,gCAAc;AACd,cAAU,GAAG;AAAA,EACf;AAEA,QAAM,EAAE,QAAQ,QAAQ,WAAW,cAAc,QAAI;AAAA,IACnD;AAAA,IACA;AAAA,MACE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,QAAQ,qBAAqB,QAAI,mBAAS,wBAAwB;AAAA,IACxE,WAAW;AAAA,EACb,CAAC;AAED,QAAM,EAAE,QAAQ,mBAAmB,WAAW,YAAY,QAAI;AAAA,IAC5D;AAAA,IACA;AAAA,MACE,WAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,EAAE,QAAQ,OAAO,WAAW,aAAa,QAAI;AAAA,IACjD;AAAA,IACA;AAAA,MACE,WAAW,CAAC,EAAE,MAAM,KAAK,MAAM;AAC7B,gBAAQ,MAAM;AAAA,UACZ,KAAK;AACH,mBAAO,UAAU,IAAI;AAAA,UACvB,KAAK;AACH,8BAAkB,IAAI;AACtB,mBAAO,UAAU,YACd,IAAI,SAAS,QAAQ,gCAAgC,IAAI,CAAC,EAC1D,KAAK,CAAC,eAAe,qBAAqB,EAAE,WAAW,CAAC,CAAC,EACzD,MAAM,CAAC,MAAM;AACZ,sBAAQ,MAAM,CAAC;AACf,iDAAc,KAAK;AAAA,gBACjB,OAAO;AAAA,gBACP,SAAS;AAAA,gBACT,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AAAA,UACL,KAAK;AACH,mBAAO,eAAe,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBACJ,YAAY,UACZ,OAAO,OAAO,OAAO,EAAE,MAAM,CAAC,UAAU,UAAU,KAAK;AAEzD,QAAM,aAAa,YAAY,UAAa,CAAC,QAAQ;AAErD,QAAM,gBAAY,qBAAQ;AAAA,IACxB,MAAM;AAAA,IACN,eAAe;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,IACA,UAAU;AAAA,MACR,UAAU,CAAC,aACT,SAAS,SAAS,OAAO;AAAA,MAC3B,UAAU,CAAC,aACT,SAAS,SAAS,OAAO;AAAA,IAC7B;AAAA,EACF,CAAC;AAED,QAAM,eAAW,qBAAQ;AAAA,IACvB,MAAM;AAAA,IACN,eAAe;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,MACR,MAAM,CAAC,SAAU,KAAK,WAAW,IAAI,OAAO;AAAA,IAC9C;AAAA,EACF,CAAC;AAED,SACE,4CAAC,sBAAO,GAAE,QACR;AAAA,IAAC;AAAA;AAAA,MACC,QACE;AAAA,QAAC,cAAAC;AAAA,QAAA;AAAA,UACC;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA,MAEF,WAAU;AAAA,MACV,UACE,gBACI,SAAS,SAAS,CAAC,SAAS,kBAAkB,IAAI,CAAC,IAClD,UAAU,SAAS,CAAC,SAAS,MAAM,IAAI,CAAC;AAAA,MAE/C,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,OAAO;AAAA,MAC/D,KAAK,EAAE,MAAM,QAAQ,IAAI,QAAQ;AAAA,MACjC,KAAI;AAAA,MAEH;AAAA,iBAAS,SAAS,CAAC,uBAClB,4EACE;AAAA;AAAA,YAAC;AAAA;AAAA,cACE,GAAG,UAAU,cAAc,UAAU;AAAA,cACtC,WAAS;AAAA,cACT,OAAM;AAAA,cACN,aAAY;AAAA,cACZ,cAAa;AAAA,cACb,gBAAe;AAAA,cACf,aAAY;AAAA,cACZ,KAAK,UAAU,IAAI,UAAU;AAAA;AAAA,UAC/B;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACE,GAAG,UAAU,cAAc,UAAU;AAAA,cACtC,OAAM;AAAA,cACN,aAAY;AAAA,cACZ,cAAa;AAAA,cACb,gBAAe;AAAA,cACf,aAAY;AAAA,cACZ,KAAK,UAAU,IAAI,UAAU;AAAA;AAAA,UAC/B;AAAA,UACA,6CAAC,qBAAM,IAAG,MAAK,SAAQ,iBACpB;AAAA,+BACC;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,IAAI,gBAAgB,SAAS,MAAM,EAAE,IAAI,QAAQ,KAAK;AAAA;AAAA,YAC5D;AAAA,YAEF,6CAAC,qBAAM,SAAQ,OACZ;AAAA,4BACC;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,GAAG;AAAA,kBACH,SAAS,UAAU,SAAS,CAAC,SAAS,OAAO,IAAI,CAAC;AAAA,kBAClD,SAAS;AAAA,kBACV;AAAA;AAAA,cAED;AAAA,cAEF,4CAAC,sBAAO,GAAG,KAAK,MAAK,UAAS,SAAS,cAAc,oBAErD;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA,QAGD,mBAAmB,EAAE,SAAS,SAAS,CAAC,wBACvC,4CAAC,qBACC;AAAA,UAAC;AAAA;AAAA,YACC,IAAI,IAAI,gBAAgB,SAAS,MAAM,EAAE,IAAI,QAAQ,KAAK;AAAA;AAAA,QAC5D,GACF;AAAA,QAGD,oBACC,6CAAC,qBAAM,SAAQ,UAAS,IAAG,MACzB;AAAA,sDAAC,gCAAS,MAAK,UAAS;AAAA,UACxB,4CAAC,oBAAK,MAAK,MAAK,qDAAuC;AAAA,UACvD,4CAAC,sBAAO;AAAA,WACV;AAAA,QAGD,iBACC,4EACE;AAAA;AAAA,YAAC;AAAA;AAAA,cACE,GAAG,SAAS,cAAc,MAAM;AAAA,cACjC,OACE,6CAAC,qBAAM,KAAI,MACT;AAAA,4DAAC,gCAAS,MAAK,QAAO;AAAA,gBAAE;AAAA,iBAE1B;AAAA,cAEF,cAAa;AAAA,cACb,gBAAe;AAAA,cACf,aAAY;AAAA,cACZ,WAAS;AAAA;AAAA,UACX;AAAA,UACA,4CAAC,qBAAM,SAAQ,OACb;AAAA,YAAC;AAAA;AAAA,cACC,GAAG;AAAA,cACH,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACV;AAAA;AAAA,UAED,GACF;AAAA,WACF;AAAA,QAGD,oBACC,6CAAC,qBAAM,IAAG,MACR;AAAA,sDAAC,qCAAc,MAAK,QAAO;AAAA,UAC3B,6CAAC,oBAAK;AAAA;AAAA,YACmC,4CAAC,QAAG;AAAA,YAAE;AAAA,YACrC;AAAA,YACR;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM;AAAA,gBACN,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAU;AAAA,gBAEV,sDAAC,OAAE,4BAAc;AAAA;AAAA,YACnB;AAAA,YAAK;AAAA,YAAI;AAAA,aAEX;AAAA,WACF;AAAA;AAAA;AAAA,EAEJ,GACF;AAEJ;","names":["import_react","LoginHeader"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/login/index.tsx"],"sourcesContent":["import {\n Button,\n Center,\n Fieldset,\n Group,\n Loader,\n PasswordInput,\n Text,\n TextInput,\n} from \"@mantine/core\";\nimport { useForm } from \"@mantine/form\";\nimport { notifications } from \"@mantine/notifications\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { AlertTriangle, KeyRound } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport LoginHeader from \"./header\";\nimport {\n authClient,\n BackButton,\n sanitizeQuery,\n useLogin,\n useLoginOptions,\n useUserId,\n} from \"../..\";\n\nexport interface LoginBrandingProps {\n appName: string;\n iconLink: string;\n iconLinkAlt: string;\n}\n\nexport function LoginPage({\n passkeyIsPending: _passkeyIsPending,\n totpIsPending: _totpIsPending,\n onLogin,\n exampleConfigLink,\n ...branding\n}: {\n passkeyIsPending?: boolean;\n totpIsPending?: boolean;\n onLogin?: () => void;\n exampleConfigLink: string;\n} & LoginBrandingProps) {\n const options = useLoginOptions().data;\n const [passkeyIsPending, setPasskeyPending] = useState(\n _passkeyIsPending ?? false,\n );\n const [totpIsPending, setTotpPending] = useState(_totpIsPending ?? false);\n const secondFactorPending = passkeyIsPending || totpIsPending;\n\n const alreadyLoggedIn = useUserId().data?.id!!;\n\n // Auto-redirect to OIDC provider if configured and disableAutoLogin is not set\n useEffect(() => {\n if (options?.oidc_auto_redirect && options?.oidc && !secondFactorPending) {\n const params = new URLSearchParams(location.search);\n if (!params.has(\"disableAutoLogin\")) {\n authClient().externalLogin(MoghAuth.Types.ExternalLoginProvider.Oidc);\n }\n }\n }, [options?.oidc_auto_redirect, options?.oidc, secondFactorPending]);\n\n // If signing in another user, need to redirect away from /login manually\n const maybeNavigate = location.pathname.startsWith(\"/login\")\n ? () =>\n location.replace(\n new URLSearchParams(location.search).get(\"backto\") ?? \"/\",\n )\n : undefined;\n\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS.add_and_change(jwt);\n onLogin?.();\n maybeNavigate?.();\n };\n\n const secondFactorOnSuccess = (res: MoghAuth.Types.JwtResponse) => {\n sanitizeQuery();\n onSuccess(res);\n };\n\n const { mutate: signup, isPending: signupPending } = useLogin(\n \"SignUpLocalUser\",\n {\n onSuccess,\n },\n );\n\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess: secondFactorOnSuccess,\n });\n\n const { mutate: completeTotpLogin, isPending: totpPending } = useLogin(\n \"CompleteTotpLogin\",\n {\n onSuccess: secondFactorOnSuccess,\n },\n );\n\n const { mutate: login, isPending: loginPending } = useLogin(\n \"LoginLocalUser\",\n {\n onSuccess: ({ type, data }) => {\n switch (type) {\n case \"Jwt\":\n return onSuccess(data);\n case \"Passkey\":\n setPasskeyPending(true);\n return navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(data))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n case \"Totp\":\n return setTotpPending(true);\n }\n },\n },\n );\n\n const noAuthConfigured =\n options !== undefined &&\n Object.values(options).every((value) => value === false);\n\n const showSignUp = options !== undefined && !options.registration_disabled;\n\n const localForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n username: \"\",\n password: \"\",\n },\n validate: {\n username: (username) =>\n username.length ? null : \"Username cannot be empty\",\n password: (password) =>\n password.length ? null : \"Password cannot be empty\",\n },\n });\n\n const totpForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n code: \"\",\n },\n validate: {\n code: (code) => (code.length === 6 ? null : \"Code should be 6 digits\"),\n },\n });\n\n return (\n <Center h=\"80vh\">\n <Fieldset\n legend={\n <LoginHeader\n secondFactorPending={secondFactorPending}\n {...branding}\n />\n }\n component=\"form\"\n onSubmit={\n totpIsPending\n ? totpForm.onSubmit((form) => completeTotpLogin(form))\n : (localForm.onSubmit((form) => login(form)) as any)\n }\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1rem\" }}\n miw={{ base: \"95vw\", xs: \"530px\" }}\n maw=\"95vw\"\n >\n {options?.local && !secondFactorPending && (\n <>\n <TextInput\n {...localForm.getInputProps(\"username\")}\n autoFocus\n label=\"Username\"\n placeholder=\"Enter username\"\n autoComplete=\"username\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"username\")}\n />\n <PasswordInput\n {...localForm.getInputProps(\"password\")}\n label=\"Password\"\n placeholder=\"Enter password\"\n autoComplete=\"password\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"password\")}\n />\n <Group mt=\"sm\" justify=\"space-between\">\n {alreadyLoggedIn && (\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n )}\n <Group justify=\"end\">\n {showSignUp && (\n <Button\n variant=\"outline\"\n w={110}\n onClick={localForm.onSubmit((form) => signup(form)) as any}\n loading={signupPending}\n >\n Sign Up\n </Button>\n )}\n <Button w={110} type=\"submit\" loading={loginPending}>\n Log In\n </Button>\n </Group>\n </Group>\n </>\n )}\n\n {alreadyLoggedIn && !(options?.local && !secondFactorPending) && (\n <Group>\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n </Group>\n )}\n\n {passkeyIsPending && (\n <Group justify=\"center\" my=\"lg\">\n <KeyRound size=\"1.5rem\" />\n <Text size=\"lg\">Provide your passkey to finish login...</Text>\n <Loader />\n </Group>\n )}\n\n {totpIsPending && (\n <>\n <TextInput\n {...totpForm.getInputProps(\"code\")}\n label={\n <Group gap=\"sm\">\n <KeyRound size=\"1rem\" />\n 2FA Code\n </Group>\n }\n autoComplete=\"code\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n autoFocus\n />\n <Group justify=\"end\">\n <Button\n w={110}\n variant=\"filled\"\n type=\"submit\"\n loading={totpPending}\n >\n Log In\n </Button>\n </Group>\n </>\n )}\n\n {noAuthConfigured && (\n <Group my=\"lg\">\n <AlertTriangle size=\"2rem\" />\n <Text>\n No login methods have been configured. <br />\n See the{\" \"}\n <a\n href={exampleConfigLink}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"hover-underline\"\n >\n <b>example config</b>\n </a>{\" \"}\n for information on configuring auth.\n </Text>\n </Group>\n )}\n </Fieldset>\n </Center>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/login/index.tsx"],"sourcesContent":["import {\n Button,\n Center,\n Fieldset,\n Group,\n Loader,\n PasswordInput,\n Text,\n TextInput,\n} from \"@mantine/core\";\nimport { useForm } from \"@mantine/form\";\nimport { notifications } from \"@mantine/notifications\";\nimport * as MoghAuth from \"mogh_auth_client\";\nimport { AlertTriangle, KeyRound } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport LoginHeader from \"./header\";\nimport {\n authClient,\n BackButton,\n sanitizeQuery,\n useLogin,\n useLoginOptions,\n useUserId,\n} from \"../..\";\n\nexport interface LoginBrandingProps {\n appName: string;\n iconLink: string;\n iconLinkAlt: string;\n}\n\nexport function LoginPage({\n passkeyIsPending: _passkeyIsPending,\n totpIsPending: _totpIsPending,\n onLogin,\n exampleConfigLink,\n ...branding\n}: {\n passkeyIsPending?: boolean;\n totpIsPending?: boolean;\n onLogin?: () => void;\n exampleConfigLink: string;\n} & LoginBrandingProps) {\n const options = useLoginOptions().data;\n const [passkeyIsPending, setPasskeyPending] = useState(\n _passkeyIsPending ?? false,\n );\n const [totpIsPending, setTotpPending] = useState(_totpIsPending ?? false);\n const secondFactorPending = passkeyIsPending || totpIsPending;\n\n const alreadyLoggedIn = useUserId().data?.id!!;\n\n // Auto-redirect to OIDC provider if configured and disableAutoLogin is not set\n useEffect(() => {\n if (options?.oidc_auto_redirect && options?.oidc && !secondFactorPending) {\n const params = new URLSearchParams(location.search);\n if (!params.has(\"disableAutoLogin\")) {\n authClient().externalLogin(MoghAuth.Types.ExternalLoginProvider.Oidc);\n }\n }\n }, [options?.oidc_auto_redirect, options?.oidc, secondFactorPending]);\n\n // If signing in another user, need to redirect away from /login manually\n const maybeNavigate = location.pathname.startsWith(\"/login\")\n ? () =>\n location.replace(\n new URLSearchParams(location.search).get(\"backto\") ?? \"/\",\n )\n : undefined;\n\n const onSuccess = ({ jwt }: MoghAuth.Types.JwtResponse) => {\n MoghAuth.LOGIN_TOKENS!.add_and_change(jwt);\n onLogin?.();\n maybeNavigate?.();\n };\n\n const secondFactorOnSuccess = (res: MoghAuth.Types.JwtResponse) => {\n sanitizeQuery();\n onSuccess(res);\n };\n\n const { mutate: signup, isPending: signupPending } = useLogin(\n \"SignUpLocalUser\",\n {\n onSuccess,\n },\n );\n\n const { mutate: completePasskeyLogin } = useLogin(\"CompletePasskeyLogin\", {\n onSuccess: secondFactorOnSuccess,\n });\n\n const { mutate: completeTotpLogin, isPending: totpPending } = useLogin(\n \"CompleteTotpLogin\",\n {\n onSuccess: secondFactorOnSuccess,\n },\n );\n\n const { mutate: login, isPending: loginPending } = useLogin(\n \"LoginLocalUser\",\n {\n onSuccess: ({ type, data }) => {\n switch (type) {\n case \"Jwt\":\n return onSuccess(data);\n case \"Passkey\":\n setPasskeyPending(true);\n return navigator.credentials\n .get(MoghAuth.Passkey.prepareRequestChallengeResponse(data))\n .then((credential) => completePasskeyLogin({ credential }))\n .catch((e) => {\n console.error(e);\n notifications.show({\n title: \"Failed to select passkey\",\n message: \"See console for details\",\n color: \"red\",\n });\n });\n case \"Totp\":\n return setTotpPending(true);\n }\n },\n },\n );\n\n const noAuthConfigured =\n options !== undefined &&\n Object.values(options).every((value) => value === false);\n\n const showSignUp = options !== undefined && !options.registration_disabled;\n\n const localForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n username: \"\",\n password: \"\",\n },\n validate: {\n username: (username) =>\n username.length ? null : \"Username cannot be empty\",\n password: (password) =>\n password.length ? null : \"Password cannot be empty\",\n },\n });\n\n const totpForm = useForm({\n mode: \"uncontrolled\",\n initialValues: {\n code: \"\",\n },\n validate: {\n code: (code) => (code.length === 6 ? null : \"Code should be 6 digits\"),\n },\n });\n\n return (\n <Center h=\"80vh\">\n <Fieldset\n legend={\n <LoginHeader\n secondFactorPending={secondFactorPending}\n {...branding}\n />\n }\n component=\"form\"\n onSubmit={\n totpIsPending\n ? totpForm.onSubmit((form) => completeTotpLogin(form))\n : (localForm.onSubmit((form) => login(form)) as any)\n }\n style={{ display: \"flex\", flexDirection: \"column\", gap: \"1rem\" }}\n miw={{ base: \"95vw\", xs: \"530px\" }}\n maw=\"95vw\"\n >\n {options?.local && !secondFactorPending && (\n <>\n <TextInput\n {...localForm.getInputProps(\"username\")}\n autoFocus\n label=\"Username\"\n placeholder=\"Enter username\"\n autoComplete=\"username\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"username\")}\n />\n <PasswordInput\n {...localForm.getInputProps(\"password\")}\n label=\"Password\"\n placeholder=\"Enter password\"\n autoComplete=\"password\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n key={localForm.key(\"password\")}\n />\n <Group mt=\"sm\" justify=\"space-between\">\n {alreadyLoggedIn && (\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n )}\n <Group justify=\"end\">\n {showSignUp && (\n <Button\n variant=\"outline\"\n w={110}\n onClick={localForm.onSubmit((form) => signup(form)) as any}\n loading={signupPending}\n >\n Sign Up\n </Button>\n )}\n <Button w={110} type=\"submit\" loading={loginPending}>\n Log In\n </Button>\n </Group>\n </Group>\n </>\n )}\n\n {alreadyLoggedIn && !(options?.local && !secondFactorPending) && (\n <Group>\n <BackButton\n to={new URLSearchParams(location.search).get(\"backto\") ?? \"/\"}\n />\n </Group>\n )}\n\n {passkeyIsPending && (\n <Group justify=\"center\" my=\"lg\">\n <KeyRound size=\"1.5rem\" />\n <Text size=\"lg\">Provide your passkey to finish login...</Text>\n <Loader />\n </Group>\n )}\n\n {totpIsPending && (\n <>\n <TextInput\n {...totpForm.getInputProps(\"code\")}\n label={\n <Group gap=\"sm\">\n <KeyRound size=\"1rem\" />\n 2FA Code\n </Group>\n }\n autoComplete=\"code\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n autoFocus\n />\n <Group justify=\"end\">\n <Button\n w={110}\n variant=\"filled\"\n type=\"submit\"\n loading={totpPending}\n >\n Log In\n </Button>\n </Group>\n </>\n )}\n\n {noAuthConfigured && (\n <Group my=\"lg\">\n <AlertTriangle size=\"2rem\" />\n <Text>\n No login methods have been configured. <br />\n See the{\" \"}\n <a\n href={exampleConfigLink}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"hover-underline\"\n >\n <b>example config</b>\n </a>{\" \"}\n for information on configuring auth.\n </Text>\n </Group>\n )}\n </Fieldset>\n </Center>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/formatting.cjs
CHANGED
|
@@ -28,6 +28,7 @@ __export(formatting_exports, {
|
|
|
28
28
|
fmtRateBytes: () => fmtRateBytes,
|
|
29
29
|
fmtSizeBytes: () => fmtSizeBytes,
|
|
30
30
|
fmtSnakeCaseToUpperSpaceCase: () => fmtSnakeCaseToUpperSpaceCase,
|
|
31
|
+
fmtTimeUntil: () => fmtTimeUntil,
|
|
31
32
|
fmtUpperCamelcase: () => fmtUpperCamelcase,
|
|
32
33
|
fmtUtcDate: () => fmtUtcDate
|
|
33
34
|
});
|
|
@@ -82,6 +83,16 @@ function fmtDuration(startTs, endTs) {
|
|
|
82
83
|
const remaining_seconds = seconds % 60;
|
|
83
84
|
return `${minutes > 0 ? `${minutes} minute${minutes > 1 ? "s" : ""} ` : ""}${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;
|
|
84
85
|
}
|
|
86
|
+
const MINUTE_MS = 6e4;
|
|
87
|
+
const HOUR_MS = 60 * MINUTE_MS;
|
|
88
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
89
|
+
function fmtTimeUntil(ms) {
|
|
90
|
+
const plural = (count, unit) => `${count} ${unit}${count === 1 ? "" : "s"}`;
|
|
91
|
+
if (ms >= DAY_MS) return plural(Math.floor(ms / DAY_MS), "day");
|
|
92
|
+
if (ms >= HOUR_MS) return plural(Math.floor(ms / HOUR_MS), "hour");
|
|
93
|
+
if (ms >= MINUTE_MS) return plural(Math.floor(ms / MINUTE_MS), "minute");
|
|
94
|
+
return "< 1 minute";
|
|
95
|
+
}
|
|
85
96
|
function fmtUpperCamelcase(input) {
|
|
86
97
|
return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(" ") ?? input;
|
|
87
98
|
}
|
|
@@ -118,6 +129,7 @@ function fmtRateBytes(bytes) {
|
|
|
118
129
|
fmtRateBytes,
|
|
119
130
|
fmtSizeBytes,
|
|
120
131
|
fmtSnakeCaseToUpperSpaceCase,
|
|
132
|
+
fmtTimeUntil,
|
|
121
133
|
fmtUpperCamelcase,
|
|
122
134
|
fmtUtcDate
|
|
123
135
|
});
|
package/dist/formatting.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/formatting.ts"],"sourcesContent":["export function fmtDate(d: Date) {\n const hours = d.getHours();\n const minutes = d.getMinutes();\n return `${fmtMonth(d.getMonth())} ${d.getDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtUtcDate(d: Date) {\n const hours = d.getUTCHours();\n const minutes = d.getUTCMinutes();\n return `${fmtMonth(d.getUTCMonth())} ${d.getUTCDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtMonth(month: number) {\n switch (month) {\n case 0:\n return \"Jan\";\n case 1:\n return \"Feb\";\n case 2:\n return \"Mar\";\n case 3:\n return \"Apr\";\n case 4:\n return \"May\";\n case 5:\n return \"Jun\";\n case 6:\n return \"Jul\";\n case 7:\n return \"Aug\";\n case 8:\n return \"Sep\";\n case 9:\n return \"Oct\";\n case 10:\n return \"Nov\";\n case 11:\n return \"Dec\";\n }\n}\n\nexport const fmtDateWithMinutes = (d: Date) => {\n // return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;\n return d.toLocaleString();\n};\n\nexport function fmtDuration(startTs: number, endTs: number) {\n const start = new Date(startTs);\n const end = new Date(endTs);\n const durr = end.getTime() - start.getTime();\n const seconds = durr / 1000;\n const minutes = Math.floor(seconds / 60);\n const remaining_seconds = seconds % 60;\n return `${\n minutes > 0 ? `${minutes} minute${minutes > 1 ? \"s\" : \"\"} ` : \"\"\n }${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;\n}\n\nexport function fmtUpperCamelcase(input: string) {\n return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(\" \") ?? input;\n}\n\n/// list_all_items => List All Items\nexport function fmtSnakeCaseToUpperSpaceCase(snake: string) {\n if (snake.length === 0) return \"\";\n return snake\n .split(\"_\")\n .map((item) => item[0].toUpperCase() + item.slice(1))\n .join(\" \");\n}\n\nexport const BYTES_PER_KB = 1024;\nexport const BYTES_PER_MB = 1024 * BYTES_PER_KB;\nexport const BYTES_PER_GB = 1024 * BYTES_PER_MB;\n\nexport function fmtSizeBytes(bytes: number) {\n if (bytes >= BYTES_PER_GB) {\n return (bytes / BYTES_PER_GB).toFixed(1) + \" GiB\";\n } else if (bytes >= BYTES_PER_MB) {\n return (bytes / BYTES_PER_MB).toFixed(1) + \" MiB\";\n } else if (bytes >= BYTES_PER_KB) {\n return (bytes / BYTES_PER_KB).toFixed(1) + \" KiB\";\n } else {\n return bytes.toString() + \" bytes\";\n }\n}\n\nexport function fmtRateBytes(bytes: number) {\n return fmtSizeBytes(bytes) + \"/s\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,QAAQ,GAAS;AAC/B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,UAAU,EAAE,WAAW;AAC7B,SAAO,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAC7C,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,WAAW,GAAS;AAClC,QAAM,QAAQ,EAAE,YAAY;AAC5B,QAAM,UAAU,EAAE,cAAc;AAChC,SAAO,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,IACnD,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,SAAS,OAAe;AACtC,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,MAAM,qBAAqB,CAAC,MAAY;AAE7C,SAAO,EAAE,eAAe;AAC1B;AAEO,SAAS,YAAY,SAAiB,OAAe;AAC1D,QAAM,QAAQ,IAAI,KAAK,OAAO;AAC9B,QAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,QAAM,OAAO,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAC3C,QAAM,UAAU,OAAO;AACvB,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,oBAAoB,UAAU;AACpC,SAAO,GACL,UAAU,IAAI,GAAG,OAAO,UAAU,UAAU,IAAI,MAAM,EAAE,MAAM,EAChE,GAAG,kBAAkB,QAAQ,UAAU,IAAI,IAAI,CAAC,CAAC;AACnD;AAEO,SAAS,kBAAkB,OAAe;AAC/C,SAAO,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,KAAK;AAC1D;AAGO,SAAS,6BAA6B,OAAe;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EACnD,KAAK,GAAG;AACb;AAEO,MAAM,eAAe;AACrB,MAAM,eAAe,OAAO;AAC5B,MAAM,eAAe,OAAO;AAE5B,SAAS,aAAa,OAAe;AAC1C,MAAI,SAAS,cAAc;AACzB,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,OAAO;AACL,WAAO,MAAM,SAAS,IAAI;AAAA,EAC5B;AACF;AAEO,SAAS,aAAa,OAAe;AAC1C,SAAO,aAAa,KAAK,IAAI;AAC/B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/formatting.ts"],"sourcesContent":["export function fmtDate(d: Date) {\n const hours = d.getHours();\n const minutes = d.getMinutes();\n return `${fmtMonth(d.getMonth())} ${d.getDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtUtcDate(d: Date) {\n const hours = d.getUTCHours();\n const minutes = d.getUTCMinutes();\n return `${fmtMonth(d.getUTCMonth())} ${d.getUTCDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtMonth(month: number) {\n switch (month) {\n case 0:\n return \"Jan\";\n case 1:\n return \"Feb\";\n case 2:\n return \"Mar\";\n case 3:\n return \"Apr\";\n case 4:\n return \"May\";\n case 5:\n return \"Jun\";\n case 6:\n return \"Jul\";\n case 7:\n return \"Aug\";\n case 8:\n return \"Sep\";\n case 9:\n return \"Oct\";\n case 10:\n return \"Nov\";\n case 11:\n return \"Dec\";\n }\n}\n\nexport const fmtDateWithMinutes = (d: Date) => {\n // return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;\n return d.toLocaleString();\n};\n\nexport function fmtDuration(startTs: number, endTs: number) {\n const start = new Date(startTs);\n const end = new Date(endTs);\n const durr = end.getTime() - start.getTime();\n const seconds = durr / 1000;\n const minutes = Math.floor(seconds / 60);\n const remaining_seconds = seconds % 60;\n return `${\n minutes > 0 ? `${minutes} minute${minutes > 1 ? \"s\" : \"\"} ` : \"\"\n }${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;\n}\n\nconst MINUTE_MS = 60_000;\nconst HOUR_MS = 60 * MINUTE_MS;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Coarse \"time until\" of a future timestamp: days, falling back to\n * hours / minutes once under a day. */\nexport function fmtTimeUntil(ms: number) {\n const plural = (count: number, unit: string) =>\n `${count} ${unit}${count === 1 ? \"\" : \"s\"}`;\n if (ms >= DAY_MS) return plural(Math.floor(ms / DAY_MS), \"day\");\n if (ms >= HOUR_MS) return plural(Math.floor(ms / HOUR_MS), \"hour\");\n if (ms >= MINUTE_MS) return plural(Math.floor(ms / MINUTE_MS), \"minute\");\n return \"< 1 minute\";\n}\n\nexport function fmtUpperCamelcase(input: string) {\n return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(\" \") ?? input;\n}\n\n/// list_all_items => List All Items\nexport function fmtSnakeCaseToUpperSpaceCase(snake: string) {\n if (snake.length === 0) return \"\";\n return snake\n .split(\"_\")\n .map((item) => item[0].toUpperCase() + item.slice(1))\n .join(\" \");\n}\n\nexport const BYTES_PER_KB = 1024;\nexport const BYTES_PER_MB = 1024 * BYTES_PER_KB;\nexport const BYTES_PER_GB = 1024 * BYTES_PER_MB;\n\nexport function fmtSizeBytes(bytes: number) {\n if (bytes >= BYTES_PER_GB) {\n return (bytes / BYTES_PER_GB).toFixed(1) + \" GiB\";\n } else if (bytes >= BYTES_PER_MB) {\n return (bytes / BYTES_PER_MB).toFixed(1) + \" MiB\";\n } else if (bytes >= BYTES_PER_KB) {\n return (bytes / BYTES_PER_KB).toFixed(1) + \" KiB\";\n } else {\n return bytes.toString() + \" bytes\";\n }\n}\n\nexport function fmtRateBytes(bytes: number) {\n return fmtSizeBytes(bytes) + \"/s\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,QAAQ,GAAS;AAC/B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,UAAU,EAAE,WAAW;AAC7B,SAAO,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAC7C,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,WAAW,GAAS;AAClC,QAAM,QAAQ,EAAE,YAAY;AAC5B,QAAM,UAAU,EAAE,cAAc;AAChC,SAAO,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,IACnD,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,SAAS,OAAe;AACtC,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,MAAM,qBAAqB,CAAC,MAAY;AAE7C,SAAO,EAAE,eAAe;AAC1B;AAEO,SAAS,YAAY,SAAiB,OAAe;AAC1D,QAAM,QAAQ,IAAI,KAAK,OAAO;AAC9B,QAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,QAAM,OAAO,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAC3C,QAAM,UAAU,OAAO;AACvB,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,oBAAoB,UAAU;AACpC,SAAO,GACL,UAAU,IAAI,GAAG,OAAO,UAAU,UAAU,IAAI,MAAM,EAAE,MAAM,EAChE,GAAG,kBAAkB,QAAQ,UAAU,IAAI,IAAI,CAAC,CAAC;AACnD;AAEA,MAAM,YAAY;AAClB,MAAM,UAAU,KAAK;AACrB,MAAM,SAAS,KAAK;AAIb,SAAS,aAAa,IAAY;AACvC,QAAM,SAAS,CAAC,OAAe,SAC7B,GAAG,KAAK,IAAI,IAAI,GAAG,UAAU,IAAI,KAAK,GAAG;AAC3C,MAAI,MAAM,OAAQ,QAAO,OAAO,KAAK,MAAM,KAAK,MAAM,GAAG,KAAK;AAC9D,MAAI,MAAM,QAAS,QAAO,OAAO,KAAK,MAAM,KAAK,OAAO,GAAG,MAAM;AACjE,MAAI,MAAM,UAAW,QAAO,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,QAAQ;AACvE,SAAO;AACT;AAEO,SAAS,kBAAkB,OAAe;AAC/C,SAAO,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,KAAK;AAC1D;AAGO,SAAS,6BAA6B,OAAe;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EACnD,KAAK,GAAG;AACb;AAEO,MAAM,eAAe;AACrB,MAAM,eAAe,OAAO;AAC5B,MAAM,eAAe,OAAO;AAE5B,SAAS,aAAa,OAAe;AAC1C,MAAI,SAAS,cAAc;AACzB,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,OAAO;AACL,WAAO,MAAM,SAAS,IAAI;AAAA,EAC5B;AACF;AAEO,SAAS,aAAa,OAAe;AAC1C,SAAO,aAAa,KAAK,IAAI;AAC/B;","names":[]}
|
package/dist/formatting.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export declare function fmtUtcDate(d: Date): string;
|
|
|
3
3
|
export declare function fmtMonth(month: number): "Apr" | "Aug" | "Dec" | "Feb" | "Jan" | "Jul" | "Jun" | "Mar" | "May" | "Nov" | "Oct" | "Sep" | undefined;
|
|
4
4
|
export declare const fmtDateWithMinutes: (d: Date) => string;
|
|
5
5
|
export declare function fmtDuration(startTs: number, endTs: number): string;
|
|
6
|
+
/** Coarse "time until" of a future timestamp: days, falling back to
|
|
7
|
+
* hours / minutes once under a day. */
|
|
8
|
+
export declare function fmtTimeUntil(ms: number): string;
|
|
6
9
|
export declare function fmtUpperCamelcase(input: string): string;
|
|
7
10
|
export declare function fmtSnakeCaseToUpperSpaceCase(snake: string): string;
|
|
8
11
|
export declare const BYTES_PER_KB = 1024;
|
package/dist/formatting.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../src/formatting.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,UAM9B;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,UAMjC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,6GA2BrC;AAED,eAAO,MAAM,kBAAkB,MAAO,IAAI,WAGzC,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAUzD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,UAE9C;AAGD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,UAMzD;AAED,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,eAAO,MAAM,YAAY,QAAsB,CAAC;AAChD,eAAO,MAAM,YAAY,QAAsB,CAAC;AAEhD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,UAUzC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,UAEzC"}
|
|
1
|
+
{"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../src/formatting.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,UAM9B;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,UAMjC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,6GA2BrC;AAED,eAAO,MAAM,kBAAkB,MAAO,IAAI,WAGzC,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAUzD;AAMD;uCACuC;AACvC,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,UAOtC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,UAE9C;AAGD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,UAMzD;AAED,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,eAAO,MAAM,YAAY,QAAsB,CAAC;AAChD,eAAO,MAAM,YAAY,QAAsB,CAAC;AAEhD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,UAUzC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,UAEzC"}
|
package/dist/formatting.js
CHANGED
|
@@ -48,6 +48,16 @@ function fmtDuration(startTs, endTs) {
|
|
|
48
48
|
const remaining_seconds = seconds % 60;
|
|
49
49
|
return `${minutes > 0 ? `${minutes} minute${minutes > 1 ? "s" : ""} ` : ""}${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;
|
|
50
50
|
}
|
|
51
|
+
const MINUTE_MS = 6e4;
|
|
52
|
+
const HOUR_MS = 60 * MINUTE_MS;
|
|
53
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
54
|
+
function fmtTimeUntil(ms) {
|
|
55
|
+
const plural = (count, unit) => `${count} ${unit}${count === 1 ? "" : "s"}`;
|
|
56
|
+
if (ms >= DAY_MS) return plural(Math.floor(ms / DAY_MS), "day");
|
|
57
|
+
if (ms >= HOUR_MS) return plural(Math.floor(ms / HOUR_MS), "hour");
|
|
58
|
+
if (ms >= MINUTE_MS) return plural(Math.floor(ms / MINUTE_MS), "minute");
|
|
59
|
+
return "< 1 minute";
|
|
60
|
+
}
|
|
51
61
|
function fmtUpperCamelcase(input) {
|
|
52
62
|
return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(" ") ?? input;
|
|
53
63
|
}
|
|
@@ -83,6 +93,7 @@ export {
|
|
|
83
93
|
fmtRateBytes,
|
|
84
94
|
fmtSizeBytes,
|
|
85
95
|
fmtSnakeCaseToUpperSpaceCase,
|
|
96
|
+
fmtTimeUntil,
|
|
86
97
|
fmtUpperCamelcase,
|
|
87
98
|
fmtUtcDate
|
|
88
99
|
};
|
package/dist/formatting.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/formatting.ts"],"sourcesContent":["export function fmtDate(d: Date) {\n const hours = d.getHours();\n const minutes = d.getMinutes();\n return `${fmtMonth(d.getMonth())} ${d.getDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtUtcDate(d: Date) {\n const hours = d.getUTCHours();\n const minutes = d.getUTCMinutes();\n return `${fmtMonth(d.getUTCMonth())} ${d.getUTCDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtMonth(month: number) {\n switch (month) {\n case 0:\n return \"Jan\";\n case 1:\n return \"Feb\";\n case 2:\n return \"Mar\";\n case 3:\n return \"Apr\";\n case 4:\n return \"May\";\n case 5:\n return \"Jun\";\n case 6:\n return \"Jul\";\n case 7:\n return \"Aug\";\n case 8:\n return \"Sep\";\n case 9:\n return \"Oct\";\n case 10:\n return \"Nov\";\n case 11:\n return \"Dec\";\n }\n}\n\nexport const fmtDateWithMinutes = (d: Date) => {\n // return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;\n return d.toLocaleString();\n};\n\nexport function fmtDuration(startTs: number, endTs: number) {\n const start = new Date(startTs);\n const end = new Date(endTs);\n const durr = end.getTime() - start.getTime();\n const seconds = durr / 1000;\n const minutes = Math.floor(seconds / 60);\n const remaining_seconds = seconds % 60;\n return `${\n minutes > 0 ? `${minutes} minute${minutes > 1 ? \"s\" : \"\"} ` : \"\"\n }${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;\n}\n\nexport function fmtUpperCamelcase(input: string) {\n return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(\" \") ?? input;\n}\n\n/// list_all_items => List All Items\nexport function fmtSnakeCaseToUpperSpaceCase(snake: string) {\n if (snake.length === 0) return \"\";\n return snake\n .split(\"_\")\n .map((item) => item[0].toUpperCase() + item.slice(1))\n .join(\" \");\n}\n\nexport const BYTES_PER_KB = 1024;\nexport const BYTES_PER_MB = 1024 * BYTES_PER_KB;\nexport const BYTES_PER_GB = 1024 * BYTES_PER_MB;\n\nexport function fmtSizeBytes(bytes: number) {\n if (bytes >= BYTES_PER_GB) {\n return (bytes / BYTES_PER_GB).toFixed(1) + \" GiB\";\n } else if (bytes >= BYTES_PER_MB) {\n return (bytes / BYTES_PER_MB).toFixed(1) + \" MiB\";\n } else if (bytes >= BYTES_PER_KB) {\n return (bytes / BYTES_PER_KB).toFixed(1) + \" KiB\";\n } else {\n return bytes.toString() + \" bytes\";\n }\n}\n\nexport function fmtRateBytes(bytes: number) {\n return fmtSizeBytes(bytes) + \"/s\";\n}\n"],"mappings":"AAAO,SAAS,QAAQ,GAAS;AAC/B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,UAAU,EAAE,WAAW;AAC7B,SAAO,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAC7C,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,WAAW,GAAS;AAClC,QAAM,QAAQ,EAAE,YAAY;AAC5B,QAAM,UAAU,EAAE,cAAc;AAChC,SAAO,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,IACnD,QAAQ,IAAI,QAAQ,MAAM,KAC5B,IAAI,UAAU,IAAI,UAAU,MAAM,OAAO;AAC3C;AAEO,SAAS,SAAS,OAAe;AACtC,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,MAAM,qBAAqB,CAAC,MAAY;AAE7C,SAAO,EAAE,eAAe;AAC1B;AAEO,SAAS,YAAY,SAAiB,OAAe;AAC1D,QAAM,QAAQ,IAAI,KAAK,OAAO;AAC9B,QAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,QAAM,OAAO,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAC3C,QAAM,UAAU,OAAO;AACvB,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,oBAAoB,UAAU;AACpC,SAAO,GACL,UAAU,IAAI,GAAG,OAAO,UAAU,UAAU,IAAI,MAAM,EAAE,MAAM,EAChE,GAAG,kBAAkB,QAAQ,UAAU,IAAI,IAAI,CAAC,CAAC;AACnD;AAEO,SAAS,kBAAkB,OAAe;AAC/C,SAAO,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,KAAK;AAC1D;AAGO,SAAS,6BAA6B,OAAe;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EACnD,KAAK,GAAG;AACb;AAEO,MAAM,eAAe;AACrB,MAAM,eAAe,OAAO;AAC5B,MAAM,eAAe,OAAO;AAE5B,SAAS,aAAa,OAAe;AAC1C,MAAI,SAAS,cAAc;AACzB,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,WAAW,SAAS,cAAc;AAChC,YAAQ,QAAQ,cAAc,QAAQ,CAAC,IAAI;AAAA,EAC7C,OAAO;AACL,WAAO,MAAM,SAAS,IAAI;AAAA,EAC5B;AACF;AAEO,SAAS,aAAa,OAAe;AAC1C,SAAO,aAAa,KAAK,IAAI;AAC/B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/formatting.ts"],"sourcesContent":["export function fmtDate(d: Date) {\n const hours = d.getHours();\n const minutes = d.getMinutes();\n return `${fmtMonth(d.getMonth())} ${d.getDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtUtcDate(d: Date) {\n const hours = d.getUTCHours();\n const minutes = d.getUTCMinutes();\n return `${fmtMonth(d.getUTCMonth())} ${d.getUTCDate()} ${\n hours > 9 ? hours : \"0\" + hours\n }:${minutes > 9 ? minutes : \"0\" + minutes}`;\n}\n\nexport function fmtMonth(month: number) {\n switch (month) {\n case 0:\n return \"Jan\";\n case 1:\n return \"Feb\";\n case 2:\n return \"Mar\";\n case 3:\n return \"Apr\";\n case 4:\n return \"May\";\n case 5:\n return \"Jun\";\n case 6:\n return \"Jul\";\n case 7:\n return \"Aug\";\n case 8:\n return \"Sep\";\n case 9:\n return \"Oct\";\n case 10:\n return \"Nov\";\n case 11:\n return \"Dec\";\n }\n}\n\nexport const fmtDateWithMinutes = (d: Date) => {\n // return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;\n return d.toLocaleString();\n};\n\nexport function fmtDuration(startTs: number, endTs: number) {\n const start = new Date(startTs);\n const end = new Date(endTs);\n const durr = end.getTime() - start.getTime();\n const seconds = durr / 1000;\n const minutes = Math.floor(seconds / 60);\n const remaining_seconds = seconds % 60;\n return `${\n minutes > 0 ? `${minutes} minute${minutes > 1 ? \"s\" : \"\"} ` : \"\"\n }${remaining_seconds.toFixed(minutes > 0 ? 0 : 1)} seconds`;\n}\n\nconst MINUTE_MS = 60_000;\nconst HOUR_MS = 60 * MINUTE_MS;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Coarse \"time until\" of a future timestamp: days, falling back to\n * hours / minutes once under a day. */\nexport function fmtTimeUntil(ms: number) {\n const plural = (count: number, unit: string) =>\n `${count} ${unit}${count === 1 ? \"\" : \"s\"}`;\n if (ms >= DAY_MS) return plural(Math.floor(ms / DAY_MS), \"day\");\n if (ms >= HOUR_MS) return plural(Math.floor(ms / HOUR_MS), \"hour\");\n if (ms >= MINUTE_MS) return plural(Math.floor(ms / MINUTE_MS), \"minute\");\n return \"< 1 minute\";\n}\n\nexport function fmtUpperCamelcase(input: string) {\n return input.match(/[A-Z][a-z]+|[0-9]+/g)?.join(\" \") ?? input;\n}\n\n/// list_all_items => List All Items\nexport function fmtSnakeCaseToUpperSpaceCase(snake: string) {\n if (snake.length === 0) return \"\";\n return snake\n .split(\"_\")\n .map((item) => item[0].toUpperCase() + item.slice(1))\n .join(\" \");\n}\n\nexport const BYTES_PER_KB = 1024;\nexport const BYTES_PER_MB = 1024 * BYTES_PER_KB;\nexport const BYTES_PER_GB = 1024 * BYTES_PER_MB;\n\nexport function fmtSizeBytes(bytes: number) {\n if (bytes >= BYTES_PER_GB) {\n return (bytes / BYTES_PER_GB).toFixed(1) + \" GiB\";\n } else if (bytes >= BYTES_PER_MB) {\n return (bytes / BYTES_PER_MB).toFixed(1) + \" MiB\";\n } else if (bytes >= BYTES_PER_KB) {\n return (bytes / BYTES_PER_KB).toFixed(1) + \" KiB\";\n } else {\n return bytes.toString() + \" bytes\";\n }\n}\n\nexport function fmtRateBytes(bytes: number) {\n return fmtSizeBytes(bytes) + \"/s\";\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mogh_ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Common UI components and styling used across Mogh apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@tanstack/react-table": "^9.1.2",
|
|
38
38
|
"@tanstack/react-query": "^5.102.4",
|
|
39
39
|
"lucide-react": "^1.34.0",
|
|
40
|
-
"mogh_auth_client": "^
|
|
40
|
+
"mogh_auth_client": "^2.0.0",
|
|
41
41
|
"monaco-editor": "^0.56.0",
|
|
42
42
|
"monaco-yaml": "^5.5.1",
|
|
43
43
|
"react": "^19.2.8",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@types/react": "^19.2.18",
|
|
56
56
|
"@types/react-dom": "^19.2.5",
|
|
57
57
|
"lucide-react": "^1.34.0",
|
|
58
|
-
"mogh_auth_client": "^
|
|
58
|
+
"mogh_auth_client": "^2.0.0",
|
|
59
59
|
"monaco-editor": "^0.56.0",
|
|
60
60
|
"monaco-yaml": "^5.5.1",
|
|
61
61
|
"react": "^19.2.8",
|