web-mojo 2.2.57 → 2.2.59
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/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +1 -10105
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -588
- package/dist/auth.es.js.map +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -571
- package/dist/charts.es.js.map +1 -1
- package/dist/chunks/ChatView-D4A9rIX3.js +2 -0
- package/dist/chunks/ChatView-D4A9rIX3.js.map +1 -0
- package/dist/chunks/ChatView-nxaq8aIo.js +2 -0
- package/dist/chunks/ChatView-nxaq8aIo.js.map +1 -0
- package/dist/chunks/Collection-1sPoIFvQ.js +2 -0
- package/dist/chunks/{Collection-DaiL0uGl.js.map → Collection-1sPoIFvQ.js.map} +1 -1
- package/dist/chunks/{Collection-CxbNKOas.js → Collection-DSBRXpwK.js} +2 -2
- package/dist/chunks/{Collection-CxbNKOas.js.map → Collection-DSBRXpwK.js.map} +1 -1
- package/dist/chunks/{ContextMenu-ClwHEbbD.js → ContextMenu-BWy7WqF4.js} +2 -2
- package/dist/chunks/{ContextMenu-ClwHEbbD.js.map → ContextMenu-BWy7WqF4.js.map} +1 -1
- package/dist/chunks/ContextMenu-BvniQz-N.js +3 -0
- package/dist/chunks/{ContextMenu-sgvgSACY.js.map → ContextMenu-BvniQz-N.js.map} +1 -1
- package/dist/chunks/DataView--nUWtq6r.js +2 -0
- package/dist/chunks/{DataView-Dzo0jbs2.js.map → DataView--nUWtq6r.js.map} +1 -1
- package/dist/chunks/{DataView-1xh3GFeC.js → DataView-CK3Z0TJH.js} +2 -2
- package/dist/chunks/{DataView-1xh3GFeC.js.map → DataView-CK3Z0TJH.js.map} +1 -1
- package/dist/chunks/Dialog-BcgSR01Z.js +2 -0
- package/dist/chunks/{Dialog-DOGDalUq.js.map → Dialog-BcgSR01Z.js.map} +1 -1
- package/dist/chunks/{Dialog-CQlTDhZS.js → Dialog-DwCTFV6O.js} +2 -2
- package/dist/chunks/{Dialog-CQlTDhZS.js.map → Dialog-DwCTFV6O.js.map} +1 -1
- package/dist/chunks/FormPlugins-DvQ-G5J5.js +2 -0
- package/dist/chunks/{FormPlugins-DY6e88YT.js.map → FormPlugins-DvQ-G5J5.js.map} +1 -1
- package/dist/chunks/{FormView-DaKA4Sys.js → FormView-CRmEReTC.js} +3 -3
- package/dist/chunks/{FormView-DaKA4Sys.js.map → FormView-CRmEReTC.js.map} +1 -1
- package/dist/chunks/FormView-OLA7t-yv.js +3 -0
- package/dist/chunks/{FormView-Dz3mYasQ.js.map → FormView-OLA7t-yv.js.map} +1 -1
- package/dist/chunks/ListView-6JQ6tRXs.js +2 -0
- package/dist/chunks/{ListView-X5w5jf51.js.map → ListView-6JQ6tRXs.js.map} +1 -1
- package/dist/chunks/{ListView-CDzKIpd8.js → ListView-DVStKiMi.js} +2 -2
- package/dist/chunks/{ListView-CDzKIpd8.js.map → ListView-DVStKiMi.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-Dx2cw7ya.js → MetricsCountryMapView-CnAEbUw_.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-Dx2cw7ya.js.map → MetricsCountryMapView-CnAEbUw_.js.map} +1 -1
- package/dist/chunks/MetricsCountryMapView-J067qrrt.js +2 -0
- package/dist/chunks/{MetricsCountryMapView-B2xz6zUw.js.map → MetricsCountryMapView-J067qrrt.js.map} +1 -1
- package/dist/chunks/{MetricsMiniChartWidget-CBuso0OE.js → MetricsMiniChartWidget-BeD1slGs.js} +2 -2
- package/dist/chunks/{MetricsMiniChartWidget-CBuso0OE.js.map → MetricsMiniChartWidget-BeD1slGs.js.map} +1 -1
- package/dist/chunks/MetricsMiniChartWidget-x2gFjHOU.js +2 -0
- package/dist/chunks/{MetricsMiniChartWidget-DvKd7Qrk.js.map → MetricsMiniChartWidget-x2gFjHOU.js.map} +1 -1
- package/dist/chunks/PDFViewer-CsyKn-gh.js +2 -0
- package/dist/chunks/{PDFViewer-EJ9cOfPF.js.map → PDFViewer-CsyKn-gh.js.map} +1 -1
- package/dist/chunks/{PDFViewer-ofMGdSaj.js → PDFViewer-DSa4BZCm.js} +2 -2
- package/dist/chunks/{PDFViewer-ofMGdSaj.js.map → PDFViewer-DSa4BZCm.js.map} +1 -1
- package/dist/chunks/Rest-DHbszkuP.js +2 -0
- package/dist/chunks/Rest-DHbszkuP.js.map +1 -0
- package/dist/chunks/Rest-Ds9e8tN8.js +2 -0
- package/dist/chunks/Rest-Ds9e8tN8.js.map +1 -0
- package/dist/chunks/TokenManager-D6SjKgPZ.js +2 -0
- package/dist/chunks/{TokenManager-DoN9e6q6.js.map → TokenManager-D6SjKgPZ.js.map} +1 -1
- package/dist/chunks/{TokenManager-Gqvj7SDX.js → TokenManager-REbha1Le.js} +2 -2
- package/dist/chunks/{TokenManager-Gqvj7SDX.js.map → TokenManager-REbha1Le.js.map} +1 -1
- package/dist/chunks/WebApp-CULZpO_0.js +2 -0
- package/dist/chunks/{WebApp-6qvqmOts.js.map → WebApp-CULZpO_0.js.map} +1 -1
- package/dist/chunks/{WebApp-_dgpwtFw.js → WebApp-DovLtA60.js} +2 -2
- package/dist/chunks/{WebApp-_dgpwtFw.js.map → WebApp-DovLtA60.js.map} +1 -1
- package/dist/chunks/WebSocketClient-B-wc3mez.js +2 -0
- package/dist/chunks/{WebSocketClient-DG2olXpH.js.map → WebSocketClient-B-wc3mez.js.map} +1 -1
- package/dist/chunks/{WebSocketClient-MFkFlSue.js → WebSocketClient-BdZ9QYll.js} +2 -2
- package/dist/chunks/{WebSocketClient-MFkFlSue.js.map → WebSocketClient-BdZ9QYll.js.map} +1 -1
- package/dist/chunks/version-C3dnl1bg.js +2 -0
- package/dist/chunks/version-C3dnl1bg.js.map +1 -0
- package/dist/chunks/{version-BVADfTA5.js → version-ioN546cp.js} +2 -2
- package/dist/chunks/{version-BVADfTA5.js.map → version-ioN546cp.js.map} +1 -1
- package/dist/css/web-mojo.css +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -957
- package/dist/docit.es.js.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -3252
- package/dist/index.es.js.map +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -3737
- package/dist/lightbox.es.js.map +1 -1
- package/dist/loader.umd.js +2 -2
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1032
- package/dist/map.es.js.map +1 -1
- package/dist/mojo-auth.es.js +338 -0
- package/dist/mojo-auth.umd.js +1 -0
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -224
- package/dist/timeline.es.js.map +1 -1
- package/dist/web-mojo.lite.iife.js +14 -3
- package/dist/web-mojo.lite.iife.js.map +1 -1
- package/dist/web-mojo.lite.iife.min.js +6 -6
- package/dist/web-mojo.lite.iife.min.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunks/ChatView-9k6xBWXk.js +0 -7632
- package/dist/chunks/ChatView-9k6xBWXk.js.map +0 -1
- package/dist/chunks/ChatView-CdtuCDYm.js +0 -2
- package/dist/chunks/ChatView-CdtuCDYm.js.map +0 -1
- package/dist/chunks/Collection-DaiL0uGl.js +0 -1014
- package/dist/chunks/ContextMenu-sgvgSACY.js +0 -1535
- package/dist/chunks/DataView-Dzo0jbs2.js +0 -862
- package/dist/chunks/Dialog-DOGDalUq.js +0 -1579
- package/dist/chunks/FormPlugins-DY6e88YT.js +0 -124
- package/dist/chunks/FormView-Dz3mYasQ.js +0 -8636
- package/dist/chunks/ListView-X5w5jf51.js +0 -495
- package/dist/chunks/MetricsCountryMapView-B2xz6zUw.js +0 -1054
- package/dist/chunks/MetricsMiniChartWidget-DvKd7Qrk.js +0 -3283
- package/dist/chunks/PDFViewer-EJ9cOfPF.js +0 -946
- package/dist/chunks/Rest-CgSjfMaU.js +0 -2
- package/dist/chunks/Rest-CgSjfMaU.js.map +0 -1
- package/dist/chunks/Rest-W-sPfGh9.js +0 -4375
- package/dist/chunks/Rest-W-sPfGh9.js.map +0 -1
- package/dist/chunks/TokenManager-DoN9e6q6.js +0 -1423
- package/dist/chunks/WebApp-6qvqmOts.js +0 -1386
- package/dist/chunks/WebSocketClient-DG2olXpH.js +0 -209
- package/dist/chunks/version-OyPGnx30.js +0 -38
- package/dist/chunks/version-OyPGnx30.js.map +0 -1
package/dist/auth.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.es.js","sources":["../src/extensions/auth/index.js"],"sourcesContent":["/**\n * Simple Auth Module (KISS)\n * - Standalone, framework-agnostic\n * - Exposes:\n * - createAuthClient({ baseURL }): imperative API for auth endpoints\n * - mountAuth(container, config): renders UI and wires flows; redirects on success\n * - Future extensibility: providers (google/passkey) can be slotted via config without changing core\n */\n\nimport './css/auth.css';\n\n/**\n * Create a minimal, framework-agnostic auth client using fetch.\n *\n * Endpoints (overridable via options.endpoints):\n * - POST /login { username, password }\n * - POST /auth/forgot { email, method: 'code' | 'link' }\n * - POST /auth/password/reset/code { email, code, new_password }\n * - POST /auth/password/reset/token { token, new_password }\n */\nexport function createAuthClient({\n baseURL,\n fetchImpl = (typeof fetch !== 'undefined' ? fetch.bind(window) : null),\n storage = (typeof localStorage !== 'undefined' ? localStorage : null),\n endpoints = {}\n} = {}) {\n if (!baseURL) {\n throw new Error('createAuthClient: baseURL is required');\n }\n if (!fetchImpl) {\n throw new Error('createAuthClient: fetch implementation is not available in this environment');\n }\n if (!storage) {\n throw new Error('createAuthClient: storage (localStorage) is not available in this environment');\n }\n\n const KEYS = {\n access: 'access_token',\n refresh: 'refresh_token',\n user: 'user'\n };\n\n const EP = {\n login: '/login',\n forgot: '/auth/forgot',\n resetCode: '/auth/password/reset/code',\n resetToken: '/auth/password/reset/token',\n ...endpoints\n };\n\n async function post(path, body) {\n const res = await fetchImpl(`${baseURL}${path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body || {})\n });\n let json = {};\n try {\n json = await res.json();\n } catch (_) {\n // ignore parse error; json stays {}\n }\n if (!res.ok) {\n // Preserve parsed server error shape\n throw json || { message: `Request failed with status ${res.status}` };\n }\n return json;\n }\n\n function parseResponse(r) {\n // Normalize common API shapes:\n // - { data: { data: {...}} }\n // - { data: {...} }\n // - {...}\n return (r && r.data && r.data.data) || (r && r.data) || r;\n }\n\n function saveAuthData(resp) {\n const d = parseResponse(resp);\n if (!d || !d.access_token) {\n throw new Error('No access_token in response.');\n }\n storage.setItem(KEYS.access, d.access_token);\n if (d.refresh_token) storage.setItem(KEYS.refresh, d.refresh_token);\n if (d.user) storage.setItem(KEYS.user, JSON.stringify(d.user));\n }\n\n function getErrorMessage(err) {\n return err?.message ||\n err?.error ||\n (Array.isArray(err?.errors) && err.errors[0]?.message) ||\n 'An error occurred. Please try again.';\n }\n\n return {\n async login(username, password) {\n const resp = await post(EP.login, { username, password });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n async forgot({ email, method }) {\n return post(EP.forgot, { email, method });\n },\n async resetWithCode({ email, code, newPassword }) {\n const resp = await post(EP.resetCode, { email, code, new_password: newPassword });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n async resetWithToken({ token, newPassword }) {\n const resp = await post(EP.resetToken, { token, new_password: newPassword });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n logout() {\n storage.removeItem(KEYS.access);\n storage.removeItem(KEYS.refresh);\n storage.removeItem(KEYS.user);\n },\n isAuthenticated() {\n return !!storage.getItem(KEYS.access);\n },\n getToken() {\n return storage.getItem(KEYS.access);\n },\n getUser() {\n const raw = storage.getItem(KEYS.user);\n try { return raw ? JSON.parse(raw) : null; } catch { return null; }\n },\n getAuthHeader() {\n const t = storage.getItem(KEYS.access);\n return t ? `Bearer ${t}` : null;\n },\n getErrorMessage,\n parseResponse\n };\n}\n\n/**\n * Mount the full auth UI into a container element with flows:\n * - Sign in\n * - Forgot password (code or link)\n * - Reset with code\n * - Set password via magic link token (login_token from URL)\n *\n * Options:\n * - baseURL: string (required)\n * - onSuccessRedirect: string (final URL after successful login/reset)\n * - allowRedirectOrigins: string[] (optional allowlist of origins to prevent open redirects)\n * - branding: { title?: string, logoUrl?: string, subtitle?: string }\n * - theme: 'light' | 'dark' | string (added as a class on the root container)\n * - endpoints: override endpoints { login, forgot, resetCode, resetToken }\n * - providers: optional object for future extensions (e.g., { google: { onClick } })\n * - texts: replace labels/copy if needed\n */\nexport function mountAuth(container, options = {}) {\n if (!container || !(container instanceof Element)) {\n throw new Error('mountAuth: container must be a DOM Element');\n }\n\n const {\n baseURL,\n onSuccessRedirect,\n allowRedirectOrigins,\n branding = {},\n theme,\n endpoints,\n providers,\n texts = {}\n } = options;\n\n if (!baseURL) {\n throw new Error('mountAuth: baseURL is required');\n }\n\n // Resolve redirect target from:\n // 1) options.onSuccessRedirect\n // 2) ?redirect | ?next | ?returnTo\n // Default to '/'\n const urlParams = new URLSearchParams(window.location.search);\n const redirectParam = urlParams.get('redirect') || urlParams.get('next') || urlParams.get('returnTo');\n const redirectTarget = String(onSuccessRedirect || redirectParam || '/');\n\n function isAllowedRedirect(url) {\n // If no allowlist, allow any same-origin or absolute URLs (caller responsibility).\n if (!allowRedirectOrigins || allowRedirectOrigins.length === 0) {\n return true;\n }\n try {\n const target = new URL(url, window.location.origin);\n return allowRedirectOrigins.includes(target.origin);\n } catch {\n return false;\n }\n }\n\n function performRedirect() {\n if (!isAllowedRedirect(redirectTarget)) {\n window.location.href = '/';\n return;\n }\n window.location.href = redirectTarget.startsWith('http')\n ? redirectTarget\n : new URL(redirectTarget, window.location.origin).href;\n }\n\n const auth = createAuthClient({ baseURL, endpoints });\n\n // Basic UI template (no external framework; styles provided via imported CSS)\n const B = {\n title: branding.title || 'Sign In',\n subtitle: branding.subtitle || 'Sign in to your account',\n logoUrl: branding.logoUrl || ''\n };\n\n const T = {\n emailOrUsername: texts.emailOrUsername || 'Email or Username',\n password: texts.password || 'Password',\n signIn: texts.signIn || 'Sign In',\n forgotPassword: texts.forgotPassword || 'Forgot password?',\n resetYourPassword: texts.resetYourPassword || 'Reset Your Password',\n emailAddress: texts.emailAddress || 'Email Address',\n resetMethod: texts.resetMethod || 'Reset Method',\n emailCode: texts.emailCode || 'Email me a code',\n emailLink: texts.emailLink || 'Email me a magic link',\n sendReset: texts.sendReset || 'Send Reset',\n back: texts.back || 'Back',\n enterResetCode: texts.enterResetCode || 'Enter Reset Code',\n weSentCodeTo: texts.weSentCodeTo || 'We sent a code to',\n resetCode: texts.resetCode || 'Reset Code',\n newPassword: texts.newPassword || 'New Password',\n confirmPassword: texts.confirmPassword || 'Confirm Password',\n resetPassword: texts.resetPassword || 'Reset Password',\n setYourNewPassword: texts.setYourNewPassword || 'Set Your New Password',\n setPassword: texts.setPassword || 'Set Password',\n invalidCredentials: texts.invalidCredentials || 'Invalid credentials.',\n successRedirecting: texts.successRedirecting || 'Success! Redirecting...',\n pleaseFillAllFields: texts.pleaseFillAllFields || 'Please fill in all fields.',\n passwordsDoNotMatch: texts.passwordsDoNotMatch || 'Passwords do not match.',\n };\n\n const HTML = `\n <div class=\"auth-container\">\n <div class=\"auth-card\">\n <div class=\"auth-header\">\n ${B.logoUrl ? `<img src=\"${B.logoUrl}\" alt=\"${B.title}\" style=\"max-height:60px;margin-bottom:10px\" />` : ''}\n <h1 class=\"auth-title\">${B.title}</h1>\n <p class=\"auth-subtitle\">${B.subtitle}</p>\n </div>\n\n <div id=\"status-message\" class=\"alert\" role=\"status\" style=\"display:none;\"></div>\n\n <!-- Sign In View -->\n <div id=\"view-signin\" class=\"auth-view\">\n <form id=\"form-signin\" novalidate>\n <div class=\"mb-3\">\n <label for=\"signin-username\" class=\"form-label\">${T.emailOrUsername}</label>\n <input type=\"text\" class=\"form-control\" id=\"signin-username\" placeholder=\"${T.emailOrUsername}\" autocomplete=\"username\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"signin-password\" class=\"form-label\">${T.password}</label>\n <input type=\"password\" class=\"form-control\" id=\"signin-password\" placeholder=\"${T.password}\" autocomplete=\"current-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100 mb-3\" id=\"btn-signin\">\n <span class=\"btn-text\">${T.signIn}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n <div class=\"text-center\">\n <a href=\"#\" id=\"link-forgot\" class=\"text-decoration-none\">${T.forgotPassword}</a>\n </div>\n\n ${(providers && (providers.google || providers.passkey)) ? `\n <div class=\"position-relative my-3\">\n <hr class=\"text-muted\" />\n <span class=\"position-absolute top-50 start-50 translate-middle bg-white px-3 text-muted small\">OR</span>\n </div>\n <div class=\"d-grid gap-2\">\n ${providers.google ? `<button type=\"button\" class=\"btn btn-outline-primary\" id=\"btn-google\"><i class=\"bi bi-google me-2\"></i>Continue with Google</button>` : ''}\n ${providers.passkey ? `<button type=\"button\" class=\"btn btn-outline-secondary\" id=\"btn-passkey\"><i class=\"bi bi-fingerprint me-2\"></i>Sign in with Passkey</button>` : ''}\n </div>\n ` : ''}\n </form>\n </div>\n\n <!-- Forgot Password View -->\n <div id=\"view-forgot\" class=\"auth-view\" style=\"display:none;\">\n <button type=\"button\" class=\"btn btn-link p-0 mb-3\" id=\"btn-back-signin\">\n <span aria-hidden=\"true\">←</span> ${T.back}\n </button>\n <h2 class=\"h5 mb-3\">${T.resetYourPassword}</h2>\n <form id=\"form-forgot\" novalidate>\n <div class=\"mb-3\">\n <label for=\"forgot-email\" class=\"form-label\">${T.emailAddress}</label>\n <input type=\"email\" class=\"form-control\" id=\"forgot-email\" placeholder=\"${T.emailAddress}\" autocomplete=\"email\" required />\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">${T.resetMethod}</label>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"radio\" name=\"reset-method\" id=\"method-code\" value=\"code\" checked />\n <label class=\"form-check-label\" for=\"method-code\">${T.emailCode}</label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"radio\" name=\"reset-method\" id=\"method-link\" value=\"link\" />\n <label class=\"form-check-label\" for=\"method-link\">${T.emailLink}</label>\n </div>\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-forgot\">\n <span class=\"btn-text\">${T.sendReset}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n\n <!-- Reset with Code View -->\n <div id=\"view-reset-code\" class=\"auth-view\" style=\"display:none;\">\n <button type=\"button\" class=\"btn btn-link p-0 mb-3\" id=\"btn-back-forgot\">\n <span aria-hidden=\"true\">←</span> ${T.back}\n </button>\n <h2 class=\"h5 mb-3\">${T.enterResetCode}</h2>\n <p class=\"text-muted small mb-3\">${T.weSentCodeTo} <strong id=\"reset-email-display\"></strong></p>\n <form id=\"form-reset-code\" novalidate>\n <div class=\"mb-3\">\n <label for=\"reset-code\" class=\"form-label\">${T.resetCode}</label>\n <input type=\"text\" class=\"form-control\" id=\"reset-code\" placeholder=\"${T.resetCode}\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"reset-password\" class=\"form-label\">${T.newPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"reset-password\" placeholder=\"${T.newPassword}\" autocomplete=\"new-password\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"reset-password-confirm\" class=\"form-label\">${T.confirmPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"reset-password-confirm\" placeholder=\"${T.confirmPassword}\" autocomplete=\"new-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-reset-code\">\n <span class=\"btn-text\">${T.resetPassword}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n\n <!-- Set Password via Magic Link View -->\n <div id=\"view-set-password\" class=\"auth-view\" style=\"display:none;\">\n <h2 class=\"h5 mb-3\">${T.setYourNewPassword}</h2>\n <form id=\"form-set-password\" novalidate>\n <div class=\"mb-3\">\n <label for=\"set-password\" class=\"form-label\">${T.newPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"set-password\" placeholder=\"${T.newPassword}\" autocomplete=\"new-password\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"set-password-confirm\" class=\"form-label\">${T.confirmPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"set-password-confirm\" placeholder=\"${T.confirmPassword}\" autocomplete=\"new-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-set-password\">\n <span class=\"btn-text\">${T.setPassword}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n </div>\n </div>\n `;\n\n // Render\n container.innerHTML = HTML;\n if (theme) {\n container.classList.add(String(theme));\n }\n\n // DOM refs\n const els = {\n views: {\n signin: container.querySelector('#view-signin'),\n forgot: container.querySelector('#view-forgot'),\n resetCode: container.querySelector('#view-reset-code'),\n setPassword: container.querySelector('#view-set-password')\n },\n forms: {\n signin: container.querySelector('#form-signin'),\n forgot: container.querySelector('#form-forgot'),\n resetCode: container.querySelector('#form-reset-code'),\n setPassword: container.querySelector('#form-set-password')\n },\n buttons: {\n signin: container.querySelector('#btn-signin'),\n forgot: container.querySelector('#btn-forgot'),\n resetCode: container.querySelector('#btn-reset-code'),\n setPassword: container.querySelector('#btn-set-password'),\n backSignin: container.querySelector('#btn-back-signin'),\n backForgot: container.querySelector('#btn-back-forgot'),\n google: container.querySelector('#btn-google'),\n passkey: container.querySelector('#btn-passkey')\n },\n inputs: {\n signinUsername: container.querySelector('#signin-username'),\n signinPassword: container.querySelector('#signin-password'),\n forgotEmail: container.querySelector('#forgot-email'),\n resetCode: container.querySelector('#reset-code'),\n resetPassword: container.querySelector('#reset-password'),\n resetPasswordConfirm: container.querySelector('#reset-password-confirm'),\n setPassword: container.querySelector('#set-password'),\n setPasswordConfirm: container.querySelector('#set-password-confirm')\n },\n radios: {\n resetMethodCode: container.querySelector('#method-code'),\n resetMethodLink: container.querySelector('#method-link')\n },\n labels: {\n resetEmailDisplay: container.querySelector('#reset-email-display')\n },\n links: {\n forgot: container.querySelector('#link-forgot')\n },\n message: container.querySelector('#status-message')\n };\n\n // Utility helpers\n function showView(name) {\n Object.entries(els.views).forEach(([key, el]) => {\n if (el) el.style.display = key === name ? 'block' : 'none';\n });\n // Focus management\n setTimeout(() => {\n const view = els.views[name];\n const heading = view?.querySelector('h1, h2, .auth-title, .h5');\n if (heading) {\n heading.setAttribute('tabindex', '-1');\n heading.focus?.();\n } else {\n const firstInput = view?.querySelector('input, button');\n firstInput?.focus?.();\n }\n }, 60);\n }\n\n function showMessage(message, type = 'info') {\n const el = els.message;\n if (!el) return;\n el.textContent = message;\n el.className = `alert alert-${type}`;\n el.style.display = 'block';\n el.setAttribute('role', type === 'danger' ? 'alert' : 'status');\n }\n\n function hideMessage() {\n const el = els.message;\n if (!el) return;\n el.style.display = 'none';\n }\n\n function setButtonLoading(button, loading) {\n if (!button) return;\n const textSpan = button.querySelector('.btn-text');\n const spinner = button.querySelector('.btn-spinner');\n\n button.disabled = !!loading;\n if (textSpan) textSpan.style.display = loading ? 'none' : 'inline';\n if (spinner) spinner.style.display = loading ? 'inline-block' : 'none';\n }\n\n function getResetMethod() {\n if (els.radios.resetMethodCode?.checked) return 'code';\n if (els.radios.resetMethodLink?.checked) return 'link';\n return 'code';\n }\n\n // Handlers\n async function handleSignin(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const username = els.inputs.signinUsername?.value?.trim();\n const password = els.inputs.signinPassword?.value;\n\n if (!username || !password) {\n showMessage('Please enter both username and password.', 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.signin, true);\n try {\n await auth.login(username, password);\n showMessage(`${T.successRedirecting}`, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || T.invalidCredentials, 'danger');\n setButtonLoading(els.buttons.signin, false);\n }\n }\n\n async function handleForgot(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const email = els.inputs.forgotEmail?.value?.trim();\n const method = getResetMethod();\n\n if (!email) {\n showMessage('Please enter your email address.', 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.forgot, true);\n try {\n await auth.forgot({ email, method });\n\n if (method === 'code') {\n sessionStorage.setItem('reset_email', email);\n sessionStorage.setItem('reset_method', method);\n if (els.labels.resetEmailDisplay) els.labels.resetEmailDisplay.textContent = email;\n showView('resetCode');\n showMessage('Reset code sent! Check your email.', 'success');\n } else {\n showMessage('Magic link sent! Check your email and click the link.', 'success');\n }\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Something went wrong. Please try again.', 'danger');\n } finally {\n setButtonLoading(els.buttons.forgot, false);\n }\n }\n\n async function handleResetCode(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const code = els.inputs.resetCode?.value?.trim();\n const newPassword = els.inputs.resetPassword?.value;\n const confirmPassword = els.inputs.resetPasswordConfirm?.value;\n const email = sessionStorage.getItem('reset_email');\n\n if (!email) {\n showMessage('Session expired. Please restart the password reset process.', 'danger');\n showView('forgot');\n return;\n }\n\n if (!code || !newPassword) {\n showMessage(T.pleaseFillAllFields, 'danger');\n return;\n }\n if (newPassword !== confirmPassword) {\n showMessage(T.passwordsDoNotMatch, 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.resetCode, true);\n try {\n await auth.resetWithCode({ email, code, newPassword });\n sessionStorage.removeItem('reset_email');\n sessionStorage.removeItem('reset_method');\n showMessage(T.successRedirecting, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Invalid code or code expired.', 'danger');\n setButtonLoading(els.buttons.resetCode, false);\n }\n }\n\n async function handleSetPassword(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const newPassword = els.inputs.setPassword?.value;\n const confirmPassword = els.inputs.setPasswordConfirm?.value;\n const token = sessionStorage.getItem('login_token');\n\n if (!token) {\n showMessage('Invalid or expired link. Please request a new one.', 'danger');\n showView('forgot');\n return;\n }\n if (!newPassword) {\n showMessage('Please enter a new password.', 'danger');\n return;\n }\n if (newPassword !== confirmPassword) {\n showMessage(T.passwordsDoNotMatch, 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.setPassword, true);\n try {\n await auth.resetWithToken({ token, newPassword });\n sessionStorage.removeItem('login_token');\n showMessage(T.successRedirecting, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Invalid or expired link.', 'danger');\n setButtonLoading(els.buttons.setPassword, false);\n }\n }\n\n // Navigation\n function goToForgot(e) {\n e?.preventDefault?.();\n hideMessage();\n showView('forgot');\n }\n function backToSignin() {\n hideMessage();\n showView('signin');\n }\n function backToForgot() {\n hideMessage();\n showView('forgot');\n }\n\n // Provider buttons (future extensibility)\n function bindProviders() {\n if (providers?.google && els.buttons.google) {\n els.buttons.google.addEventListener('click', (e) => {\n e?.preventDefault?.();\n providers.google.onClick?.({ container, auth, redirect: performRedirect, showMessage });\n });\n }\n if (providers?.passkey && els.buttons.passkey) {\n els.buttons.passkey.addEventListener('click', (e) => {\n e?.preventDefault?.();\n providers.passkey.onClick?.({ container, auth, redirect: performRedirect, showMessage });\n });\n }\n }\n\n // Wire events\n els.forms.signin?.addEventListener('submit', handleSignin);\n els.forms.forgot?.addEventListener('submit', handleForgot);\n els.forms.resetCode?.addEventListener('submit', handleResetCode);\n els.forms.setPassword?.addEventListener('submit', handleSetPassword);\n els.links.forgot?.addEventListener('click', goToForgot);\n els.buttons.backSignin?.addEventListener('click', backToSignin);\n els.buttons.backForgot?.addEventListener('click', backToForgot);\n\n bindProviders();\n\n // Initialize view based on URL token (magic link flow)\n (function init() {\n // Check magic link token\n const params = new URLSearchParams(window.location.search);\n const loginToken = params.get('login_token');\n\n if (loginToken) {\n sessionStorage.setItem('login_token', loginToken);\n\n // Clean URL (remove login_token)\n params.delete('login_token');\n const newUrl = params.toString()\n ? `${window.location.pathname}?${params.toString()}`\n : window.location.pathname;\n window.history.replaceState({}, '', newUrl);\n\n showView('setPassword');\n showMessage('Please set your new password.', 'info');\n return;\n }\n\n // If forgot flow was started (code method)\n const resetEmail = sessionStorage.getItem('reset_email');\n if (resetEmail) {\n if (els.labels.resetEmailDisplay) els.labels.resetEmailDisplay.textContent = resetEmail;\n showView('resetCode');\n return;\n }\n\n // Default view\n showView('signin');\n })();\n\n // Return unmount/destroy function for cleanup\n return {\n destroy() {\n els.forms.signin?.removeEventListener('submit', handleSignin);\n els.forms.forgot?.removeEventListener('submit', handleForgot);\n els.forms.resetCode?.removeEventListener('submit', handleResetCode);\n els.forms.setPassword?.removeEventListener('submit', handleSetPassword);\n els.links.forgot?.removeEventListener('click', goToForgot);\n els.buttons.backSignin?.removeEventListener('click', backToSignin);\n els.buttons.backForgot?.removeEventListener('click', backToForgot);\n if (providers?.google && els.buttons.google) {\n els.buttons.google.replaceWith(els.buttons.google.cloneNode(true));\n }\n if (providers?.passkey && els.buttons.passkey) {\n els.buttons.passkey.replaceWith(els.buttons.passkey.cloneNode(true));\n }\n container.innerHTML = '';\n }\n };\n}\n\nexport default {\n mountAuth,\n createAuthClient\n};"],"names":["d","B"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth.es.js","sources":["../src/extensions/auth/index.js"],"sourcesContent":["/**\n * Simple Auth Module (KISS)\n * - Standalone, framework-agnostic\n * - Exposes:\n * - createAuthClient({ baseURL }): imperative API for auth endpoints\n * - mountAuth(container, config): renders UI and wires flows; redirects on success\n * - Future extensibility: providers (google/passkey) can be slotted via config without changing core\n */\n\nimport './css/auth.css';\n\n/**\n * Create a minimal, framework-agnostic auth client using fetch.\n *\n * Endpoints (overridable via options.endpoints):\n * - POST /login { username, password }\n * - POST /auth/forgot { email, method: 'code' | 'link' }\n * - POST /auth/password/reset/code { email, code, new_password }\n * - POST /auth/password/reset/token { token, new_password }\n */\nexport function createAuthClient({\n baseURL,\n fetchImpl = (typeof fetch !== 'undefined' ? fetch.bind(window) : null),\n storage = (typeof localStorage !== 'undefined' ? localStorage : null),\n endpoints = {}\n} = {}) {\n if (!baseURL) {\n throw new Error('createAuthClient: baseURL is required');\n }\n if (!fetchImpl) {\n throw new Error('createAuthClient: fetch implementation is not available in this environment');\n }\n if (!storage) {\n throw new Error('createAuthClient: storage (localStorage) is not available in this environment');\n }\n\n const KEYS = {\n access: 'access_token',\n refresh: 'refresh_token',\n user: 'user'\n };\n\n const EP = {\n login: '/login',\n forgot: '/auth/forgot',\n resetCode: '/auth/password/reset/code',\n resetToken: '/auth/password/reset/token',\n ...endpoints\n };\n\n async function post(path, body) {\n const res = await fetchImpl(`${baseURL}${path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body || {})\n });\n let json = {};\n try {\n json = await res.json();\n } catch (_) {\n // ignore parse error; json stays {}\n }\n if (!res.ok) {\n // Preserve parsed server error shape\n throw json || { message: `Request failed with status ${res.status}` };\n }\n return json;\n }\n\n function parseResponse(r) {\n // Normalize common API shapes:\n // - { data: { data: {...}} }\n // - { data: {...} }\n // - {...}\n return (r && r.data && r.data.data) || (r && r.data) || r;\n }\n\n function saveAuthData(resp) {\n const d = parseResponse(resp);\n if (!d || !d.access_token) {\n throw new Error('No access_token in response.');\n }\n storage.setItem(KEYS.access, d.access_token);\n if (d.refresh_token) storage.setItem(KEYS.refresh, d.refresh_token);\n if (d.user) storage.setItem(KEYS.user, JSON.stringify(d.user));\n }\n\n function getErrorMessage(err) {\n return err?.message ||\n err?.error ||\n (Array.isArray(err?.errors) && err.errors[0]?.message) ||\n 'An error occurred. Please try again.';\n }\n\n return {\n async login(username, password) {\n const resp = await post(EP.login, { username, password });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n async forgot({ email, method }) {\n return post(EP.forgot, { email, method });\n },\n async resetWithCode({ email, code, newPassword }) {\n const resp = await post(EP.resetCode, { email, code, new_password: newPassword });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n async resetWithToken({ token, newPassword }) {\n const resp = await post(EP.resetToken, { token, new_password: newPassword });\n saveAuthData(resp);\n return parseResponse(resp);\n },\n logout() {\n storage.removeItem(KEYS.access);\n storage.removeItem(KEYS.refresh);\n storage.removeItem(KEYS.user);\n },\n isAuthenticated() {\n return !!storage.getItem(KEYS.access);\n },\n getToken() {\n return storage.getItem(KEYS.access);\n },\n getUser() {\n const raw = storage.getItem(KEYS.user);\n try { return raw ? JSON.parse(raw) : null; } catch { return null; }\n },\n getAuthHeader() {\n const t = storage.getItem(KEYS.access);\n return t ? `Bearer ${t}` : null;\n },\n getErrorMessage,\n parseResponse\n };\n}\n\n/**\n * Mount the full auth UI into a container element with flows:\n * - Sign in\n * - Forgot password (code or link)\n * - Reset with code\n * - Set password via magic link token (login_token from URL)\n *\n * Options:\n * - baseURL: string (required)\n * - onSuccessRedirect: string (final URL after successful login/reset)\n * - allowRedirectOrigins: string[] (optional allowlist of origins to prevent open redirects)\n * - branding: { title?: string, logoUrl?: string, subtitle?: string }\n * - theme: 'light' | 'dark' | string (added as a class on the root container)\n * - endpoints: override endpoints { login, forgot, resetCode, resetToken }\n * - providers: optional object for future extensions (e.g., { google: { onClick } })\n * - texts: replace labels/copy if needed\n */\nexport function mountAuth(container, options = {}) {\n if (!container || !(container instanceof Element)) {\n throw new Error('mountAuth: container must be a DOM Element');\n }\n\n const {\n baseURL,\n onSuccessRedirect,\n allowRedirectOrigins,\n branding = {},\n theme,\n endpoints,\n providers,\n texts = {}\n } = options;\n\n if (!baseURL) {\n throw new Error('mountAuth: baseURL is required');\n }\n\n // Resolve redirect target from:\n // 1) options.onSuccessRedirect\n // 2) ?redirect | ?next | ?returnTo\n // Default to '/'\n const urlParams = new URLSearchParams(window.location.search);\n const redirectParam = urlParams.get('redirect') || urlParams.get('next') || urlParams.get('returnTo');\n const redirectTarget = String(onSuccessRedirect || redirectParam || '/');\n\n function isAllowedRedirect(url) {\n // If no allowlist, allow any same-origin or absolute URLs (caller responsibility).\n if (!allowRedirectOrigins || allowRedirectOrigins.length === 0) {\n return true;\n }\n try {\n const target = new URL(url, window.location.origin);\n return allowRedirectOrigins.includes(target.origin);\n } catch {\n return false;\n }\n }\n\n function performRedirect() {\n if (!isAllowedRedirect(redirectTarget)) {\n window.location.href = '/';\n return;\n }\n window.location.href = redirectTarget.startsWith('http')\n ? redirectTarget\n : new URL(redirectTarget, window.location.origin).href;\n }\n\n const auth = createAuthClient({ baseURL, endpoints });\n\n // Basic UI template (no external framework; styles provided via imported CSS)\n const B = {\n title: branding.title || 'Sign In',\n subtitle: branding.subtitle || 'Sign in to your account',\n logoUrl: branding.logoUrl || ''\n };\n\n const T = {\n emailOrUsername: texts.emailOrUsername || 'Email or Username',\n password: texts.password || 'Password',\n signIn: texts.signIn || 'Sign In',\n forgotPassword: texts.forgotPassword || 'Forgot password?',\n resetYourPassword: texts.resetYourPassword || 'Reset Your Password',\n emailAddress: texts.emailAddress || 'Email Address',\n resetMethod: texts.resetMethod || 'Reset Method',\n emailCode: texts.emailCode || 'Email me a code',\n emailLink: texts.emailLink || 'Email me a magic link',\n sendReset: texts.sendReset || 'Send Reset',\n back: texts.back || 'Back',\n enterResetCode: texts.enterResetCode || 'Enter Reset Code',\n weSentCodeTo: texts.weSentCodeTo || 'We sent a code to',\n resetCode: texts.resetCode || 'Reset Code',\n newPassword: texts.newPassword || 'New Password',\n confirmPassword: texts.confirmPassword || 'Confirm Password',\n resetPassword: texts.resetPassword || 'Reset Password',\n setYourNewPassword: texts.setYourNewPassword || 'Set Your New Password',\n setPassword: texts.setPassword || 'Set Password',\n invalidCredentials: texts.invalidCredentials || 'Invalid credentials.',\n successRedirecting: texts.successRedirecting || 'Success! Redirecting...',\n pleaseFillAllFields: texts.pleaseFillAllFields || 'Please fill in all fields.',\n passwordsDoNotMatch: texts.passwordsDoNotMatch || 'Passwords do not match.',\n };\n\n const HTML = `\n <div class=\"auth-container\">\n <div class=\"auth-card\">\n <div class=\"auth-header\">\n ${B.logoUrl ? `<img src=\"${B.logoUrl}\" alt=\"${B.title}\" style=\"max-height:60px;margin-bottom:10px\" />` : ''}\n <h1 class=\"auth-title\">${B.title}</h1>\n <p class=\"auth-subtitle\">${B.subtitle}</p>\n </div>\n\n <div id=\"status-message\" class=\"alert\" role=\"status\" style=\"display:none;\"></div>\n\n <!-- Sign In View -->\n <div id=\"view-signin\" class=\"auth-view\">\n <form id=\"form-signin\" novalidate>\n <div class=\"mb-3\">\n <label for=\"signin-username\" class=\"form-label\">${T.emailOrUsername}</label>\n <input type=\"text\" class=\"form-control\" id=\"signin-username\" placeholder=\"${T.emailOrUsername}\" autocomplete=\"username\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"signin-password\" class=\"form-label\">${T.password}</label>\n <input type=\"password\" class=\"form-control\" id=\"signin-password\" placeholder=\"${T.password}\" autocomplete=\"current-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100 mb-3\" id=\"btn-signin\">\n <span class=\"btn-text\">${T.signIn}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n <div class=\"text-center\">\n <a href=\"#\" id=\"link-forgot\" class=\"text-decoration-none\">${T.forgotPassword}</a>\n </div>\n\n ${(providers && (providers.google || providers.passkey)) ? `\n <div class=\"position-relative my-3\">\n <hr class=\"text-muted\" />\n <span class=\"position-absolute top-50 start-50 translate-middle bg-white px-3 text-muted small\">OR</span>\n </div>\n <div class=\"d-grid gap-2\">\n ${providers.google ? `<button type=\"button\" class=\"btn btn-outline-primary\" id=\"btn-google\"><i class=\"bi bi-google me-2\"></i>Continue with Google</button>` : ''}\n ${providers.passkey ? `<button type=\"button\" class=\"btn btn-outline-secondary\" id=\"btn-passkey\"><i class=\"bi bi-fingerprint me-2\"></i>Sign in with Passkey</button>` : ''}\n </div>\n ` : ''}\n </form>\n </div>\n\n <!-- Forgot Password View -->\n <div id=\"view-forgot\" class=\"auth-view\" style=\"display:none;\">\n <button type=\"button\" class=\"btn btn-link p-0 mb-3\" id=\"btn-back-signin\">\n <span aria-hidden=\"true\">←</span> ${T.back}\n </button>\n <h2 class=\"h5 mb-3\">${T.resetYourPassword}</h2>\n <form id=\"form-forgot\" novalidate>\n <div class=\"mb-3\">\n <label for=\"forgot-email\" class=\"form-label\">${T.emailAddress}</label>\n <input type=\"email\" class=\"form-control\" id=\"forgot-email\" placeholder=\"${T.emailAddress}\" autocomplete=\"email\" required />\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">${T.resetMethod}</label>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"radio\" name=\"reset-method\" id=\"method-code\" value=\"code\" checked />\n <label class=\"form-check-label\" for=\"method-code\">${T.emailCode}</label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"radio\" name=\"reset-method\" id=\"method-link\" value=\"link\" />\n <label class=\"form-check-label\" for=\"method-link\">${T.emailLink}</label>\n </div>\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-forgot\">\n <span class=\"btn-text\">${T.sendReset}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n\n <!-- Reset with Code View -->\n <div id=\"view-reset-code\" class=\"auth-view\" style=\"display:none;\">\n <button type=\"button\" class=\"btn btn-link p-0 mb-3\" id=\"btn-back-forgot\">\n <span aria-hidden=\"true\">←</span> ${T.back}\n </button>\n <h2 class=\"h5 mb-3\">${T.enterResetCode}</h2>\n <p class=\"text-muted small mb-3\">${T.weSentCodeTo} <strong id=\"reset-email-display\"></strong></p>\n <form id=\"form-reset-code\" novalidate>\n <div class=\"mb-3\">\n <label for=\"reset-code\" class=\"form-label\">${T.resetCode}</label>\n <input type=\"text\" class=\"form-control\" id=\"reset-code\" placeholder=\"${T.resetCode}\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"reset-password\" class=\"form-label\">${T.newPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"reset-password\" placeholder=\"${T.newPassword}\" autocomplete=\"new-password\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"reset-password-confirm\" class=\"form-label\">${T.confirmPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"reset-password-confirm\" placeholder=\"${T.confirmPassword}\" autocomplete=\"new-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-reset-code\">\n <span class=\"btn-text\">${T.resetPassword}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n\n <!-- Set Password via Magic Link View -->\n <div id=\"view-set-password\" class=\"auth-view\" style=\"display:none;\">\n <h2 class=\"h5 mb-3\">${T.setYourNewPassword}</h2>\n <form id=\"form-set-password\" novalidate>\n <div class=\"mb-3\">\n <label for=\"set-password\" class=\"form-label\">${T.newPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"set-password\" placeholder=\"${T.newPassword}\" autocomplete=\"new-password\" required />\n </div>\n <div class=\"mb-3\">\n <label for=\"set-password-confirm\" class=\"form-label\">${T.confirmPassword}</label>\n <input type=\"password\" class=\"form-control\" id=\"set-password-confirm\" placeholder=\"${T.confirmPassword}\" autocomplete=\"new-password\" required />\n </div>\n <button type=\"submit\" class=\"btn btn-primary w-100\" id=\"btn-set-password\">\n <span class=\"btn-text\">${T.setPassword}</span>\n <span class=\"btn-spinner spinner-border spinner-border-sm\" style=\"display:none;\"></span>\n </button>\n </form>\n </div>\n </div>\n </div>\n `;\n\n // Render\n container.innerHTML = HTML;\n if (theme) {\n container.classList.add(String(theme));\n }\n\n // DOM refs\n const els = {\n views: {\n signin: container.querySelector('#view-signin'),\n forgot: container.querySelector('#view-forgot'),\n resetCode: container.querySelector('#view-reset-code'),\n setPassword: container.querySelector('#view-set-password')\n },\n forms: {\n signin: container.querySelector('#form-signin'),\n forgot: container.querySelector('#form-forgot'),\n resetCode: container.querySelector('#form-reset-code'),\n setPassword: container.querySelector('#form-set-password')\n },\n buttons: {\n signin: container.querySelector('#btn-signin'),\n forgot: container.querySelector('#btn-forgot'),\n resetCode: container.querySelector('#btn-reset-code'),\n setPassword: container.querySelector('#btn-set-password'),\n backSignin: container.querySelector('#btn-back-signin'),\n backForgot: container.querySelector('#btn-back-forgot'),\n google: container.querySelector('#btn-google'),\n passkey: container.querySelector('#btn-passkey')\n },\n inputs: {\n signinUsername: container.querySelector('#signin-username'),\n signinPassword: container.querySelector('#signin-password'),\n forgotEmail: container.querySelector('#forgot-email'),\n resetCode: container.querySelector('#reset-code'),\n resetPassword: container.querySelector('#reset-password'),\n resetPasswordConfirm: container.querySelector('#reset-password-confirm'),\n setPassword: container.querySelector('#set-password'),\n setPasswordConfirm: container.querySelector('#set-password-confirm')\n },\n radios: {\n resetMethodCode: container.querySelector('#method-code'),\n resetMethodLink: container.querySelector('#method-link')\n },\n labels: {\n resetEmailDisplay: container.querySelector('#reset-email-display')\n },\n links: {\n forgot: container.querySelector('#link-forgot')\n },\n message: container.querySelector('#status-message')\n };\n\n // Utility helpers\n function showView(name) {\n Object.entries(els.views).forEach(([key, el]) => {\n if (el) el.style.display = key === name ? 'block' : 'none';\n });\n // Focus management\n setTimeout(() => {\n const view = els.views[name];\n const heading = view?.querySelector('h1, h2, .auth-title, .h5');\n if (heading) {\n heading.setAttribute('tabindex', '-1');\n heading.focus?.();\n } else {\n const firstInput = view?.querySelector('input, button');\n firstInput?.focus?.();\n }\n }, 60);\n }\n\n function showMessage(message, type = 'info') {\n const el = els.message;\n if (!el) return;\n el.textContent = message;\n el.className = `alert alert-${type}`;\n el.style.display = 'block';\n el.setAttribute('role', type === 'danger' ? 'alert' : 'status');\n }\n\n function hideMessage() {\n const el = els.message;\n if (!el) return;\n el.style.display = 'none';\n }\n\n function setButtonLoading(button, loading) {\n if (!button) return;\n const textSpan = button.querySelector('.btn-text');\n const spinner = button.querySelector('.btn-spinner');\n\n button.disabled = !!loading;\n if (textSpan) textSpan.style.display = loading ? 'none' : 'inline';\n if (spinner) spinner.style.display = loading ? 'inline-block' : 'none';\n }\n\n function getResetMethod() {\n if (els.radios.resetMethodCode?.checked) return 'code';\n if (els.radios.resetMethodLink?.checked) return 'link';\n return 'code';\n }\n\n // Handlers\n async function handleSignin(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const username = els.inputs.signinUsername?.value?.trim();\n const password = els.inputs.signinPassword?.value;\n\n if (!username || !password) {\n showMessage('Please enter both username and password.', 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.signin, true);\n try {\n await auth.login(username, password);\n showMessage(`${T.successRedirecting}`, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || T.invalidCredentials, 'danger');\n setButtonLoading(els.buttons.signin, false);\n }\n }\n\n async function handleForgot(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const email = els.inputs.forgotEmail?.value?.trim();\n const method = getResetMethod();\n\n if (!email) {\n showMessage('Please enter your email address.', 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.forgot, true);\n try {\n await auth.forgot({ email, method });\n\n if (method === 'code') {\n sessionStorage.setItem('reset_email', email);\n sessionStorage.setItem('reset_method', method);\n if (els.labels.resetEmailDisplay) els.labels.resetEmailDisplay.textContent = email;\n showView('resetCode');\n showMessage('Reset code sent! Check your email.', 'success');\n } else {\n showMessage('Magic link sent! Check your email and click the link.', 'success');\n }\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Something went wrong. Please try again.', 'danger');\n } finally {\n setButtonLoading(els.buttons.forgot, false);\n }\n }\n\n async function handleResetCode(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const code = els.inputs.resetCode?.value?.trim();\n const newPassword = els.inputs.resetPassword?.value;\n const confirmPassword = els.inputs.resetPasswordConfirm?.value;\n const email = sessionStorage.getItem('reset_email');\n\n if (!email) {\n showMessage('Session expired. Please restart the password reset process.', 'danger');\n showView('forgot');\n return;\n }\n\n if (!code || !newPassword) {\n showMessage(T.pleaseFillAllFields, 'danger');\n return;\n }\n if (newPassword !== confirmPassword) {\n showMessage(T.passwordsDoNotMatch, 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.resetCode, true);\n try {\n await auth.resetWithCode({ email, code, newPassword });\n sessionStorage.removeItem('reset_email');\n sessionStorage.removeItem('reset_method');\n showMessage(T.successRedirecting, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Invalid code or code expired.', 'danger');\n setButtonLoading(els.buttons.resetCode, false);\n }\n }\n\n async function handleSetPassword(e) {\n e?.preventDefault?.();\n hideMessage();\n\n const newPassword = els.inputs.setPassword?.value;\n const confirmPassword = els.inputs.setPasswordConfirm?.value;\n const token = sessionStorage.getItem('login_token');\n\n if (!token) {\n showMessage('Invalid or expired link. Please request a new one.', 'danger');\n showView('forgot');\n return;\n }\n if (!newPassword) {\n showMessage('Please enter a new password.', 'danger');\n return;\n }\n if (newPassword !== confirmPassword) {\n showMessage(T.passwordsDoNotMatch, 'danger');\n return;\n }\n\n setButtonLoading(els.buttons.setPassword, true);\n try {\n await auth.resetWithToken({ token, newPassword });\n sessionStorage.removeItem('login_token');\n showMessage(T.successRedirecting, 'success');\n setTimeout(performRedirect, 350);\n } catch (err) {\n showMessage(auth.getErrorMessage(err) || 'Invalid or expired link.', 'danger');\n setButtonLoading(els.buttons.setPassword, false);\n }\n }\n\n // Navigation\n function goToForgot(e) {\n e?.preventDefault?.();\n hideMessage();\n showView('forgot');\n }\n function backToSignin() {\n hideMessage();\n showView('signin');\n }\n function backToForgot() {\n hideMessage();\n showView('forgot');\n }\n\n // Provider buttons (future extensibility)\n function bindProviders() {\n if (providers?.google && els.buttons.google) {\n els.buttons.google.addEventListener('click', (e) => {\n e?.preventDefault?.();\n providers.google.onClick?.({ container, auth, redirect: performRedirect, showMessage });\n });\n }\n if (providers?.passkey && els.buttons.passkey) {\n els.buttons.passkey.addEventListener('click', (e) => {\n e?.preventDefault?.();\n providers.passkey.onClick?.({ container, auth, redirect: performRedirect, showMessage });\n });\n }\n }\n\n // Wire events\n els.forms.signin?.addEventListener('submit', handleSignin);\n els.forms.forgot?.addEventListener('submit', handleForgot);\n els.forms.resetCode?.addEventListener('submit', handleResetCode);\n els.forms.setPassword?.addEventListener('submit', handleSetPassword);\n els.links.forgot?.addEventListener('click', goToForgot);\n els.buttons.backSignin?.addEventListener('click', backToSignin);\n els.buttons.backForgot?.addEventListener('click', backToForgot);\n\n bindProviders();\n\n // Initialize view based on URL token (magic link flow)\n (function init() {\n // Check magic link token\n const params = new URLSearchParams(window.location.search);\n const loginToken = params.get('login_token');\n\n if (loginToken) {\n sessionStorage.setItem('login_token', loginToken);\n\n // Clean URL (remove login_token)\n params.delete('login_token');\n const newUrl = params.toString()\n ? `${window.location.pathname}?${params.toString()}`\n : window.location.pathname;\n window.history.replaceState({}, '', newUrl);\n\n showView('setPassword');\n showMessage('Please set your new password.', 'info');\n return;\n }\n\n // If forgot flow was started (code method)\n const resetEmail = sessionStorage.getItem('reset_email');\n if (resetEmail) {\n if (els.labels.resetEmailDisplay) els.labels.resetEmailDisplay.textContent = resetEmail;\n showView('resetCode');\n return;\n }\n\n // Default view\n showView('signin');\n })();\n\n // Return unmount/destroy function for cleanup\n return {\n destroy() {\n els.forms.signin?.removeEventListener('submit', handleSignin);\n els.forms.forgot?.removeEventListener('submit', handleForgot);\n els.forms.resetCode?.removeEventListener('submit', handleResetCode);\n els.forms.setPassword?.removeEventListener('submit', handleSetPassword);\n els.links.forgot?.removeEventListener('click', goToForgot);\n els.buttons.backSignin?.removeEventListener('click', backToSignin);\n els.buttons.backForgot?.removeEventListener('click', backToForgot);\n if (providers?.google && els.buttons.google) {\n els.buttons.google.replaceWith(els.buttons.google.cloneNode(true));\n }\n if (providers?.passkey && els.buttons.passkey) {\n els.buttons.passkey.replaceWith(els.buttons.passkey.cloneNode(true));\n }\n container.innerHTML = '';\n }\n };\n}\n\nexport default {\n mountAuth,\n createAuthClient\n};"],"names":["createAuthClient","baseURL","fetchImpl","fetch","bind","window","storage","localStorage","endpoints","Error","KEYS","EP","login","forgot","resetCode","resetToken","async","post","path","body","res","method","headers","JSON","stringify","json","_","ok","message","status","parseResponse","r","data","saveAuthData","resp","d","access_token","setItem","refresh_token","user","username","password","email","resetWithCode","code","newPassword","new_password","resetWithToken","token","logout","removeItem","isAuthenticated","getItem","getToken","getUser","raw","parse","getAuthHeader","t","getErrorMessage","err","error","Array","isArray","errors","mountAuth","container","options","Element","onSuccessRedirect","allowRedirectOrigins","branding","theme","providers","texts","urlParams","URLSearchParams","location","search","redirectParam","get","redirectTarget","String","performRedirect","url","length","target","URL","origin","includes","isAllowedRedirect","href","startsWith","auth","B","title","subtitle","logoUrl","T","emailOrUsername","signIn","forgotPassword","resetYourPassword","emailAddress","resetMethod","emailCode","emailLink","sendReset","back","enterResetCode","weSentCodeTo","confirmPassword","resetPassword","setYourNewPassword","setPassword","invalidCredentials","successRedirecting","pleaseFillAllFields","passwordsDoNotMatch","HTML","google","passkey","innerHTML","classList","add","els","views","signin","querySelector","forms","buttons","backSignin","backForgot","inputs","signinUsername","signinPassword","forgotEmail","resetPasswordConfirm","setPasswordConfirm","radios","resetMethodCode","resetMethodLink","labels","resetEmailDisplay","links","showView","name","Object","entries","forEach","key","el","style","display","setTimeout","view","heading","setAttribute","focus","firstInput","showMessage","type","textContent","className","hideMessage","setButtonLoading","button","loading","textSpan","spinner","disabled","handleSignin","e","preventDefault","value","trim","handleForgot","checked","sessionStorage","handleResetCode","handleSetPassword","goToForgot","backToSignin","backToForgot","addEventListener","onClick","redirect","params","loginToken","delete","newUrl","toString","pathname","history","replaceState","resetEmail","destroy","removeEventListener","replaceWith","cloneNode","index"],"mappings":"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"}
|
package/dist/charts.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/MetricsMiniChartWidget-CBuso0OE.js"),e=require("./chunks/Rest-CgSjfMaU.js"),s=require("./chunks/WebApp-_dgpwtFw.js"),i=require("./chunks/version-BVADfTA5.js");class CircularProgress extends e.View{constructor(t={}){super({className:`circular-progress ${t.className||""}`,...t}),this.SIZE_PRESETS={xs:40,sm:60,md:80,lg:120,xl:180},this.STROKE_PRESETS={xs:4,sm:6,md:8,lg:12,xl:16},this.value=void 0!==t.value?t.value:0,this.min=void 0!==t.min?t.min:0,this.max=void 0!==t.max?t.max:100,this.sizePreset="string"==typeof t.size&&this.SIZE_PRESETS[t.size]?t.size:null,this.size=this.resolveSize(void 0!==t.size?t.size:"md"),this.strokeWidth="auto"===t.strokeWidth||void 0===t.strokeWidth?this.getAutoStrokeWidth(t.size):t.strokeWidth,this.theme=t.theme||"basic",this.variant=t.variant||"default",this.color=t.color,this.trackColor=t.trackColor,this.textColor=t.textColor,this.gradientColors=t.gradientColors||null,this.applyTheme(),this.applyVariant(),this.rotation=void 0!==t.rotation?t.rotation:-90,this.gap=t.gap||0,this.showValue=!1!==t.showValue,this.valueFormat=t.valueFormat||"percentage",this.valueFormatter=t.valueFormatter||null,this.label=t.label||null,this.labelHtml=t.labelHtml||null,this.icon=t.icon||null,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||600,this.animationEasing=t.animationEasing||"ease-out",this.rounded=!1!==t.rounded,this.shadow=t.shadow||!1,this.clickable=t.clickable||!1,this.tooltip=t.tooltip||null,this.tooltipPlacement=t.tooltipPlacement||"top",this.segments=t.segments||null,this.segmentGap=t.segmentGap||2,this.dataFormatter=e.dataFormatter,this.svg=null,this.centerElement=null,this.popover=null,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`}resolveSize(t){return"string"==typeof t&&this.SIZE_PRESETS[t]?this.SIZE_PRESETS[t]:"number"==typeof t?t:this.SIZE_PRESETS.md}getAutoStrokeWidth(t){if("string"==typeof t&&this.STROKE_PRESETS[t])return this.STROKE_PRESETS[t];const e=this.resolveSize(t);return e<=40?4:e<=60?6:e<=80?8:e<=120?12:16}applyTheme(){const t={basic:{trackColor:"#e9ecef",textColor:null,backgroundColor:null},shadowed:{trackColor:"#d1d5db",textColor:null,backgroundColor:null,shadow:!0},dark:{trackColor:"#374151",textColor:"#e5e7eb",backgroundColor:"#1f2937"},light:{trackColor:"#f3f4f6",textColor:"#111827",backgroundColor:"#ffffff"}},e=t[this.theme]||t.basic;this.trackColor||(this.trackColor=e.trackColor),!this.textColor&&e.textColor&&(this.textColor=e.textColor),e.shadow&&!1===this.shadow&&(this.shadow=e.shadow)}applyVariant(){const t={success:{color:"#198754",trackColor:"rgba(25, 135, 84, 0.1)"},danger:{color:"#dc3545",trackColor:"rgba(220, 53, 69, 0.1)"},warning:{color:"#ffc107",trackColor:"rgba(255, 193, 7, 0.1)"},info:{color:"#0dcaf0",trackColor:"rgba(13, 202, 240, 0.1)"},default:{color:"#0d6efd"}};if(t[this.variant]){const e=t[this.variant];this.color||(this.color=e.color),e.trackColor&&this.trackColor===this.applyTheme.trackColor&&(this.trackColor=e.trackColor)}this.color||(this.color="#0d6efd")}getTemplate(){const t=this.sizePreset?`circular-progress-${this.sizePreset}`:"",e="default"!==this.variant?`circular-progress-${this.variant}`:"",s="basic"!==this.theme?`circular-progress-theme-${this.theme}`:"",i=this.clickable?"circular-progress-clickable":"",r=this.shadow?"circular-progress-shadow":"",o=this.textColor?`color: ${this.textColor};`:"";return`\n <div class="circular-progress-container ${t} ${e} ${s} ${i} ${r}"\n style="width: ${this.size}px; height: ${this.size}px;">\n <svg class="circular-progress-svg" \n width="${this.size}" \n height="${this.size}"\n viewBox="0 0 ${this.size} ${this.size}">\n </svg>\n <div class="circular-progress-center" style="${o}">\n <div class="circular-progress-content"></div>\n </div>\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".circular-progress-svg"),this.centerElement=this.element.querySelector(".circular-progress-content"),this.containerElement=this.element.querySelector(".circular-progress-container"),this.renderProgress(),this.renderCenterContent(),this.clickable&&this.setupClickHandler(),this.tooltip&&this.clickable&&this.setupTooltip()}renderProgress(){if(!this.svg)return;this.svg.innerHTML="";const t=this.size/2,e=(this.size-this.strokeWidth)/2,s=2*Math.PI*e;this.gradientColors&&this.gradientColors.length>1&&this.createGradient(),this.segments&&Array.isArray(this.segments)&&this.segments.length>0?this.renderSegments(t,e,s):this.renderSingleProgress(t,e,s)}renderSingleProgress(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r);const o=i-this.getPercentage()/100*i,a=this.gradientColors?`url(#${this.gradientId})`:this.color,n=this.createCircle(t,e,{stroke:a,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${i} ${s}`,strokeDashoffset:this.animate?i:o,transform:`rotate(${this.rotation} ${t} ${t})`,class:"circular-progress-bar"});this.svg.appendChild(n),this.animate&&this.animateProgress(n,o)}renderSegments(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r),this.segments.reduce((t,e)=>t+(e.value||0),0)>this.max&&console.warn("CircularProgress: Segment total exceeds max value. Clamping to max.");let o=0;this.segments.forEach((r,a)=>{const n=(r.value||0)/(this.max-this.min)*100/100*i,h=this.segmentGap/360*s;if(n>0){const l=this.createCircle(t,e,{stroke:r.color||this.color,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${n} ${s}`,strokeDashoffset:this.animate?i:-o,transform:`rotate(${this.rotation} ${t} ${t})`,class:`circular-progress-segment circular-progress-segment-${a}`,"data-segment-index":a});this.svg.appendChild(l),this.animate&&this.animateProgress(l,-o,100*a),o+=n+h}})}createCircle(t,e,s={}){const i=document.createElementNS("http://www.w3.org/2000/svg","circle");return i.setAttribute("cx",t),i.setAttribute("cy",t),i.setAttribute("r",e),Object.entries(s).forEach(([t,e])=>{"strokeWidth"===t?i.setAttribute("stroke-width",e):"strokeLinecap"===t?i.setAttribute("stroke-linecap",e):"strokeDasharray"===t?i.setAttribute("stroke-dasharray",e):"strokeDashoffset"===t?i.setAttribute("stroke-dashoffset",e):i.setAttribute(t,e)}),i}createGradient(){const t=document.createElementNS("http://www.w3.org/2000/svg","defs"),e=document.createElementNS("http://www.w3.org/2000/svg","linearGradient");e.setAttribute("id",this.gradientId),e.setAttribute("x1","0%"),e.setAttribute("y1","0%"),e.setAttribute("x2","100%"),e.setAttribute("y2","100%"),this.gradientColors.forEach((t,s)=>{const i=document.createElementNS("http://www.w3.org/2000/svg","stop"),r=s/(this.gradientColors.length-1)*100;i.setAttribute("offset",`${r}%`),i.setAttribute("stop-color",t),e.appendChild(i)}),t.appendChild(e),this.svg.appendChild(t)}animateProgress(t,e,s=0){setTimeout(()=>{t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=e},s)}renderCenterContent(){if(this.centerElement)if(this.labelHtml)this.centerElement.innerHTML=this.labelHtml;else if(this.icon)this.centerElement.innerHTML=`<i class="${this.icon}"></i>`;else if(this.showValue){let t=`<div class="circular-progress-value">${this.getFormattedValue()}</div>`;this.label&&(t+=`<div class="circular-progress-label">${this.label}</div>`),this.centerElement.innerHTML=t}}getFormattedValue(){const t=this.value,e=this.min,s=this.max;if(this.valueFormatter&&"function"==typeof this.valueFormatter)return this.valueFormatter(t,e,s);switch(this.valueFormat){case"percentage":return`${Math.round(this.getPercentage())}%`;case"fraction":return`${t}/${s}`;case"value":return t.toString();default:if(this.dataFormatter)try{return this.dataFormatter.pipe(t,this.valueFormat)}catch(i){return console.warn("CircularProgress: DataFormatter error, falling back to percentage",i),`${Math.round(this.getPercentage())}%`}return`${Math.round(this.getPercentage())}%`}}getPercentage(){const t=this.max-this.min;return 0===t?0:(this.value-this.min)/t*100}setupClickHandler(){this.containerElement&&(this.containerElement.style.cursor="pointer",this.containerElement.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const e=this.getPercentage();this.emit("progress:clicked",{value:this.value,percentage:e,min:this.min,max:this.max}),this.tooltip&&this.togglePopover()}))}setupTooltip(){}togglePopover(){if(this.containerElement&&void 0!==window.bootstrap){if(!this.popover){const t=this.getTooltipContent(),e="object"==typeof this.tooltip&&this.tooltip.title?this.tooltip.title:void 0,s={content:t,html:!0,placement:this.tooltipPlacement,trigger:"manual",container:"body"};e&&(s.title=e),this.popover=new window.bootstrap.Popover(this.containerElement,s)}window.bootstrap.Popover.getInstance(this.containerElement)&&this.containerElement.getAttribute("aria-describedby")?this.popover.hide():(this.popover.setContent({".popover-body":this.getTooltipContent()}),this.popover.show())}else console.warn("CircularProgress: Bootstrap is required for tooltip support")}getTooltipContent(){return"function"==typeof this.tooltip?this.tooltip(this.value,{min:this.min,max:this.max,percentage:this.getPercentage()}):"object"==typeof this.tooltip?this.tooltip.html||this.tooltip.content||"":this.tooltip||""}setValue(t,e=!0){if(this.value,this.value=Math.max(this.min,Math.min(this.max,t)),this.renderCenterContent(),this.svg&&!this.segments){const t=this.svg.querySelector(".circular-progress-bar");if(t){const s=this.size/2-this.strokeWidth/2,i=2*Math.PI*s,r=(this.gap>0?360-this.gap:360)/360*i,o=r-this.getPercentage()/100*r;e?(t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=o):(t.style.transition="none",t.style.strokeDashoffset=o)}}else{const t=this.animate;this.animate=e,this.renderProgress(),this.animate=t}}setRange(t,e){this.min=t,this.max=e,this.renderProgress(),this.renderCenterContent()}increment(t=1){this.setValue(this.value+t)}decrement(t=1){this.setValue(this.value-t)}setColor(t){if(this.color=t,this.gradientColors=null,this.svg&&!this.segments){const e=this.svg.querySelector(".circular-progress-bar");e&&e.setAttribute("stroke",t)}else this.renderProgress()}setGradient(t){Array.isArray(t)&&t.length>1&&(this.gradientColors=t,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`,this.renderProgress())}setSize(t){this.containerElement&&this.sizePreset&&this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`),this.sizePreset="string"==typeof t&&this.SIZE_PRESETS[t]?t:null,this.size=this.resolveSize(t),this.strokeWidth=this.getAutoStrokeWidth(t),this.containerElement&&(this.containerElement.style.width=`${this.size}px`,this.containerElement.style.height=`${this.size}px`,this.sizePreset&&this.containerElement.classList.add(`circular-progress-${this.sizePreset}`)),this.svg&&(this.svg.setAttribute("width",this.size),this.svg.setAttribute("height",this.size),this.svg.setAttribute("viewBox",`0 0 ${this.size} ${this.size}`)),this.renderProgress()}animateTo(t,e=1e3){const s=this.value,i=t-s,r=performance.now(),o=a=>{const n=a-r,h=Math.min(n/e,1),l=1-Math.pow(1-h,3),c=s+i*l;this.setValue(c,!1),h<1?requestAnimationFrame(o):this.setValue(t,!1)};requestAnimationFrame(o)}pulse(){this.containerElement&&(this.containerElement.style.animation="none",setTimeout(()=>{this.containerElement.style.animation="circular-progress-pulse 0.5s ease-out"},10),setTimeout(()=>{this.containerElement.style.animation=""},500))}complete(){this.variant="success",this.applyVariant(),this.setValue(this.max),this.pulse()}reset(){this.setValue(this.min)}hide(){this.element&&(this.element.style.display="none")}show(){this.element&&(this.element.style.display="")}getValue(){return this.value}getPercentageValue(){return this.getPercentage()}async onBeforeDestroy(){this.popover&&(this.popover.dispose(),this.popover=null),await super.onBeforeDestroy()}}exports.BaseChart=t.BaseChart,exports.MetricsChart=t.MetricsChart,exports.MetricsMiniChart=t.MetricsMiniChart,exports.MetricsMiniChartWidget=t.MetricsMiniChartWidget,exports.MiniChart=t.MiniChart,exports.PieChart=t.PieChart,exports.SeriesChart=t.SeriesChart,exports.WebApp=s.WebApp,exports.BUILD_TIME=i.BUILD_TIME,exports.VERSION=i.VERSION,exports.VERSION_INFO=i.VERSION_INFO,exports.VERSION_MAJOR=i.VERSION_MAJOR,exports.VERSION_MINOR=i.VERSION_MINOR,exports.VERSION_REVISION=i.VERSION_REVISION,exports.CircularProgress=CircularProgress;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/MetricsMiniChartWidget-BeD1slGs.js"),e=require("./chunks/Rest-Ds9e8tN8.js"),s=require("./chunks/WebApp-DovLtA60.js"),i=require("./chunks/version-ioN546cp.js");class CircularProgress extends e.View{constructor(t={}){super({className:`circular-progress ${t.className||""}`,...t}),this.SIZE_PRESETS={xs:40,sm:60,md:80,lg:120,xl:180},this.STROKE_PRESETS={xs:4,sm:6,md:8,lg:12,xl:16},this.value=void 0!==t.value?t.value:0,this.min=void 0!==t.min?t.min:0,this.max=void 0!==t.max?t.max:100,this.sizePreset="string"==typeof t.size&&this.SIZE_PRESETS[t.size]?t.size:null,this.size=this.resolveSize(void 0!==t.size?t.size:"md"),this.strokeWidth="auto"===t.strokeWidth||void 0===t.strokeWidth?this.getAutoStrokeWidth(t.size):t.strokeWidth,this.theme=t.theme||"basic",this.variant=t.variant||"default",this.color=t.color,this.trackColor=t.trackColor,this.textColor=t.textColor,this.gradientColors=t.gradientColors||null,this.applyTheme(),this.applyVariant(),this.rotation=void 0!==t.rotation?t.rotation:-90,this.gap=t.gap||0,this.showValue=!1!==t.showValue,this.valueFormat=t.valueFormat||"percentage",this.valueFormatter=t.valueFormatter||null,this.label=t.label||null,this.labelHtml=t.labelHtml||null,this.icon=t.icon||null,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||600,this.animationEasing=t.animationEasing||"ease-out",this.rounded=!1!==t.rounded,this.shadow=t.shadow||!1,this.clickable=t.clickable||!1,this.tooltip=t.tooltip||null,this.tooltipPlacement=t.tooltipPlacement||"top",this.segments=t.segments||null,this.segmentGap=t.segmentGap||2,this.dataFormatter=e.dataFormatter,this.svg=null,this.centerElement=null,this.popover=null,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`}resolveSize(t){return"string"==typeof t&&this.SIZE_PRESETS[t]?this.SIZE_PRESETS[t]:"number"==typeof t?t:this.SIZE_PRESETS.md}getAutoStrokeWidth(t){if("string"==typeof t&&this.STROKE_PRESETS[t])return this.STROKE_PRESETS[t];const e=this.resolveSize(t);return e<=40?4:e<=60?6:e<=80?8:e<=120?12:16}applyTheme(){const t={basic:{trackColor:"#e9ecef",textColor:null,backgroundColor:null},shadowed:{trackColor:"#d1d5db",textColor:null,backgroundColor:null,shadow:!0},dark:{trackColor:"#374151",textColor:"#e5e7eb",backgroundColor:"#1f2937"},light:{trackColor:"#f3f4f6",textColor:"#111827",backgroundColor:"#ffffff"}},e=t[this.theme]||t.basic;this.trackColor||(this.trackColor=e.trackColor),!this.textColor&&e.textColor&&(this.textColor=e.textColor),e.shadow&&!1===this.shadow&&(this.shadow=e.shadow)}applyVariant(){const t={success:{color:"#198754",trackColor:"rgba(25, 135, 84, 0.1)"},danger:{color:"#dc3545",trackColor:"rgba(220, 53, 69, 0.1)"},warning:{color:"#ffc107",trackColor:"rgba(255, 193, 7, 0.1)"},info:{color:"#0dcaf0",trackColor:"rgba(13, 202, 240, 0.1)"},default:{color:"#0d6efd"}};if(t[this.variant]){const e=t[this.variant];this.color||(this.color=e.color),e.trackColor&&this.trackColor===this.applyTheme.trackColor&&(this.trackColor=e.trackColor)}this.color||(this.color="#0d6efd")}getTemplate(){const t=this.sizePreset?`circular-progress-${this.sizePreset}`:"",e="default"!==this.variant?`circular-progress-${this.variant}`:"",s="basic"!==this.theme?`circular-progress-theme-${this.theme}`:"",i=this.clickable?"circular-progress-clickable":"",r=this.shadow?"circular-progress-shadow":"",o=this.textColor?`color: ${this.textColor};`:"";return`\n <div class="circular-progress-container ${t} ${e} ${s} ${i} ${r}"\n style="width: ${this.size}px; height: ${this.size}px;">\n <svg class="circular-progress-svg" \n width="${this.size}" \n height="${this.size}"\n viewBox="0 0 ${this.size} ${this.size}">\n </svg>\n <div class="circular-progress-center" style="${o}">\n <div class="circular-progress-content"></div>\n </div>\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".circular-progress-svg"),this.centerElement=this.element.querySelector(".circular-progress-content"),this.containerElement=this.element.querySelector(".circular-progress-container"),this.renderProgress(),this.renderCenterContent(),this.clickable&&this.setupClickHandler(),this.tooltip&&this.clickable&&this.setupTooltip()}renderProgress(){if(!this.svg)return;this.svg.innerHTML="";const t=this.size/2,e=(this.size-this.strokeWidth)/2,s=2*Math.PI*e;this.gradientColors&&this.gradientColors.length>1&&this.createGradient(),this.segments&&Array.isArray(this.segments)&&this.segments.length>0?this.renderSegments(t,e,s):this.renderSingleProgress(t,e,s)}renderSingleProgress(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r);const o=i-this.getPercentage()/100*i,a=this.gradientColors?`url(#${this.gradientId})`:this.color,n=this.createCircle(t,e,{stroke:a,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${i} ${s}`,strokeDashoffset:this.animate?i:o,transform:`rotate(${this.rotation} ${t} ${t})`,class:"circular-progress-bar"});this.svg.appendChild(n),this.animate&&this.animateProgress(n,o)}renderSegments(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r),this.segments.reduce((t,e)=>t+(e.value||0),0)>this.max&&console.warn("CircularProgress: Segment total exceeds max value. Clamping to max.");let o=0;this.segments.forEach((r,a)=>{const n=(r.value||0)/(this.max-this.min)*100/100*i,h=this.segmentGap/360*s;if(n>0){const l=this.createCircle(t,e,{stroke:r.color||this.color,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${n} ${s}`,strokeDashoffset:this.animate?i:-o,transform:`rotate(${this.rotation} ${t} ${t})`,class:`circular-progress-segment circular-progress-segment-${a}`,"data-segment-index":a});this.svg.appendChild(l),this.animate&&this.animateProgress(l,-o,100*a),o+=n+h}})}createCircle(t,e,s={}){const i=document.createElementNS("http://www.w3.org/2000/svg","circle");return i.setAttribute("cx",t),i.setAttribute("cy",t),i.setAttribute("r",e),Object.entries(s).forEach(([t,e])=>{"strokeWidth"===t?i.setAttribute("stroke-width",e):"strokeLinecap"===t?i.setAttribute("stroke-linecap",e):"strokeDasharray"===t?i.setAttribute("stroke-dasharray",e):"strokeDashoffset"===t?i.setAttribute("stroke-dashoffset",e):i.setAttribute(t,e)}),i}createGradient(){const t=document.createElementNS("http://www.w3.org/2000/svg","defs"),e=document.createElementNS("http://www.w3.org/2000/svg","linearGradient");e.setAttribute("id",this.gradientId),e.setAttribute("x1","0%"),e.setAttribute("y1","0%"),e.setAttribute("x2","100%"),e.setAttribute("y2","100%"),this.gradientColors.forEach((t,s)=>{const i=document.createElementNS("http://www.w3.org/2000/svg","stop"),r=s/(this.gradientColors.length-1)*100;i.setAttribute("offset",`${r}%`),i.setAttribute("stop-color",t),e.appendChild(i)}),t.appendChild(e),this.svg.appendChild(t)}animateProgress(t,e,s=0){setTimeout(()=>{t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=e},s)}renderCenterContent(){if(this.centerElement)if(this.labelHtml)this.centerElement.innerHTML=this.labelHtml;else if(this.icon)this.centerElement.innerHTML=`<i class="${this.icon}"></i>`;else if(this.showValue){let t=`<div class="circular-progress-value">${this.getFormattedValue()}</div>`;this.label&&(t+=`<div class="circular-progress-label">${this.label}</div>`),this.centerElement.innerHTML=t}}getFormattedValue(){const t=this.value,e=this.min,s=this.max;if(this.valueFormatter&&"function"==typeof this.valueFormatter)return this.valueFormatter(t,e,s);switch(this.valueFormat){case"percentage":return`${Math.round(this.getPercentage())}%`;case"fraction":return`${t}/${s}`;case"value":return t.toString();default:if(this.dataFormatter)try{return this.dataFormatter.pipe(t,this.valueFormat)}catch(i){return console.warn("CircularProgress: DataFormatter error, falling back to percentage",i),`${Math.round(this.getPercentage())}%`}return`${Math.round(this.getPercentage())}%`}}getPercentage(){const t=this.max-this.min;return 0===t?0:(this.value-this.min)/t*100}setupClickHandler(){this.containerElement&&(this.containerElement.style.cursor="pointer",this.containerElement.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const e=this.getPercentage();this.emit("progress:clicked",{value:this.value,percentage:e,min:this.min,max:this.max}),this.tooltip&&this.togglePopover()}))}setupTooltip(){}togglePopover(){if(this.containerElement&&void 0!==window.bootstrap){if(!this.popover){const t=this.getTooltipContent(),e="object"==typeof this.tooltip&&this.tooltip.title?this.tooltip.title:void 0,s={content:t,html:!0,placement:this.tooltipPlacement,trigger:"manual",container:"body"};e&&(s.title=e),this.popover=new window.bootstrap.Popover(this.containerElement,s)}window.bootstrap.Popover.getInstance(this.containerElement)&&this.containerElement.getAttribute("aria-describedby")?this.popover.hide():(this.popover.setContent({".popover-body":this.getTooltipContent()}),this.popover.show())}else console.warn("CircularProgress: Bootstrap is required for tooltip support")}getTooltipContent(){return"function"==typeof this.tooltip?this.tooltip(this.value,{min:this.min,max:this.max,percentage:this.getPercentage()}):"object"==typeof this.tooltip?this.tooltip.html||this.tooltip.content||"":this.tooltip||""}setValue(t,e=!0){if(this.value,this.value=Math.max(this.min,Math.min(this.max,t)),this.renderCenterContent(),this.svg&&!this.segments){const t=this.svg.querySelector(".circular-progress-bar");if(t){const s=this.size/2-this.strokeWidth/2,i=2*Math.PI*s,r=(this.gap>0?360-this.gap:360)/360*i,o=r-this.getPercentage()/100*r;e?(t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=o):(t.style.transition="none",t.style.strokeDashoffset=o)}}else{const t=this.animate;this.animate=e,this.renderProgress(),this.animate=t}}setRange(t,e){this.min=t,this.max=e,this.renderProgress(),this.renderCenterContent()}increment(t=1){this.setValue(this.value+t)}decrement(t=1){this.setValue(this.value-t)}setColor(t){if(this.color=t,this.gradientColors=null,this.svg&&!this.segments){const e=this.svg.querySelector(".circular-progress-bar");e&&e.setAttribute("stroke",t)}else this.renderProgress()}setGradient(t){Array.isArray(t)&&t.length>1&&(this.gradientColors=t,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`,this.renderProgress())}setSize(t){this.containerElement&&this.sizePreset&&this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`),this.sizePreset="string"==typeof t&&this.SIZE_PRESETS[t]?t:null,this.size=this.resolveSize(t),this.strokeWidth=this.getAutoStrokeWidth(t),this.containerElement&&(this.containerElement.style.width=`${this.size}px`,this.containerElement.style.height=`${this.size}px`,this.sizePreset&&this.containerElement.classList.add(`circular-progress-${this.sizePreset}`)),this.svg&&(this.svg.setAttribute("width",this.size),this.svg.setAttribute("height",this.size),this.svg.setAttribute("viewBox",`0 0 ${this.size} ${this.size}`)),this.renderProgress()}animateTo(t,e=1e3){const s=this.value,i=t-s,r=performance.now(),o=a=>{const n=a-r,h=Math.min(n/e,1),l=1-Math.pow(1-h,3),c=s+i*l;this.setValue(c,!1),h<1?requestAnimationFrame(o):this.setValue(t,!1)};requestAnimationFrame(o)}pulse(){this.containerElement&&(this.containerElement.style.animation="none",setTimeout(()=>{this.containerElement.style.animation="circular-progress-pulse 0.5s ease-out"},10),setTimeout(()=>{this.containerElement.style.animation=""},500))}complete(){this.variant="success",this.applyVariant(),this.setValue(this.max),this.pulse()}reset(){this.setValue(this.min)}hide(){this.element&&(this.element.style.display="none")}show(){this.element&&(this.element.style.display="")}getValue(){return this.value}getPercentageValue(){return this.getPercentage()}async onBeforeDestroy(){this.popover&&(this.popover.dispose(),this.popover=null),await super.onBeforeDestroy()}}exports.BaseChart=t.BaseChart,exports.MetricsChart=t.MetricsChart,exports.MetricsMiniChart=t.MetricsMiniChart,exports.MetricsMiniChartWidget=t.MetricsMiniChartWidget,exports.MiniChart=t.MiniChart,exports.PieChart=t.PieChart,exports.SeriesChart=t.SeriesChart,exports.WebApp=s.WebApp,exports.BUILD_TIME=i.BUILD_TIME,exports.VERSION=i.VERSION,exports.VERSION_INFO=i.VERSION_INFO,exports.VERSION_MAJOR=i.VERSION_MAJOR,exports.VERSION_MINOR=i.VERSION_MINOR,exports.VERSION_REVISION=i.VERSION_REVISION,exports.CircularProgress=CircularProgress;
|
|
2
2
|
//# sourceMappingURL=charts.cjs.js.map
|