commit 6cd0cd5a603332b0493cf37343949766f1e8d826 Author: @lukin Date: Mon Jul 5 18:40:00 2021 +0700 Initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7c1e13a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a84bfe --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# dependencies +node_modules/ + +# misc +.DS_Store diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/META-INF/keycloak-themes.json b/META-INF/keycloak-themes.json new file mode 100644 index 0000000..2352cc0 --- /dev/null +++ b/META-INF/keycloak-themes.json @@ -0,0 +1,8 @@ +{ + "themes": [ + { + "name": "keywind", + "types": ["login"] + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5eea85 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# :wind_face: Keywind + +Keywind is a component-based Keycloak Login Theme built with [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss) and [Alpine.js](https://github.com/alpinejs/alpine). + +![Preview](./preview.png) + +## Installation + +Keywind has been designed with component-based architecture from the start, and **you can customize as little or as much Keywind as you need**: + +1. [Deploy Keywind Login Theme](https://www.keycloak.org/docs/latest/server_development/#deploying-themes) +2. [Create your own Login Theme](https://www.keycloak.org/docs/latest/server_development/#creating-a-theme) +3. Specify parent theme in [theme properties](https://www.keycloak.org/docs/latest/server_development/#theme-properties): + +``` +parent=keywind +``` + +4. Brand and Customize components with [FreeMaker](https://freemarker.apache.org/docs/dgui_quickstart_template.html) + +## Features + +### Styled Pages + +* Login +* Password Reset +* Register + +## Examples + +### Color Theme + +When you do need to customize a palette, you can configure your colors under the `colors` key in the `theme` section of `tailwind.config.js` file: + +```js +// tailwind.config.js +module.exports = { + theme: { + extend: { + colors: { + primary: colors.red, + }, + }, + }, +} +``` + +Read more about Tailwind CSS configuration in the [documentation](https://tailwindcss.com/docs/configuration). + +### Primary Button Size + +You can inherit Keywind components in your own theme. For example, to resize the primary button you should create a styled `theme/mytheme/components/button/primary.ftl` file: + +``` +<#macro kw component="button" rest...> + <${component} + class="bg-primary-600 flex justify-center px-6 py-3 relative rounded-lg text-md text-white w-full focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2 hover:bg-primary-700" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#nested> + + +``` + +### Build + +When you're ready to deploy your own theme, run the build command to generate a static production build. + +```bash +yarn build +``` diff --git a/package.json b/package.json new file mode 100644 index 0000000..a794beb --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "scripts": { + "start": "snowpack dev", + "build": "snowpack build" + }, + "devDependencies": { + "@snowpack/plugin-postcss": "^1.4.3", + "@tailwindcss/forms": "^0.3.3", + "@types/tailwindcss": "^2.2.1", + "autoprefixer": "^10.2.6", + "cssnano": "^5.0.6", + "postcss": "^8.3.5", + "snowpack": "^3.7.1", + "tailwindcss": "^2.2.4" + }, + "dependencies": { + "alpinejs": "^3.2.1" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..12023fa --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + autoprefixer: {}, + cssnano: {}, + tailwindcss: {}, + }, +}; diff --git a/preview.png b/preview.png new file mode 100644 index 0000000..c59d328 Binary files /dev/null and b/preview.png differ diff --git a/snowpack.config.js b/snowpack.config.js new file mode 100644 index 0000000..c25c236 --- /dev/null +++ b/snowpack.config.js @@ -0,0 +1,21 @@ +/** + * @type { import("snowpack").SnowpackUserConfig } + */ +module.exports = { + buildOptions: { + out: './theme/keywind/login/resources', + }, + devOptions: { + tailwindConfig: './tailwind.config.js', + }, + mount: { + src: '/dist', + }, + optimize: { + bundle: true, + entrypoints: ['./src/index.js'], + minify: true, + target: 'es2017', + }, + plugins: ['@snowpack/plugin-postcss'], +}; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..675bc24 --- /dev/null +++ b/src/index.css @@ -0,0 +1,26 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer components { + /* Separate + ======================================================================== */ + + .separate { + @apply flex items-center text-center; + } + + .separate::after, + .separate::before { + content: ''; + @apply border-b border-gray-300 flex-1; + } + + .separate:not(:empty)::after { + @apply ml-2; + } + + .separate:not(:empty)::before { + @apply mr-2; + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..df80acc --- /dev/null +++ b/src/index.js @@ -0,0 +1,5 @@ +import Alpine from 'alpinejs'; + +window.Alpine = Alpine; + +Alpine.start(); diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..948b6ed --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,18 @@ +const colors = require('tailwindcss/colors'); + +/** + * @type { import('@types/tailwindcss/tailwind-config').TailwindConfig } + */ +module.exports = { + darkMode: 'class', + plugins: [require('@tailwindcss/forms')], + purge: ['./theme/**/*.ftl'], + mode: 'jit', + theme: { + extend: { + colors: { + primary: colors.blue, + }, + }, + }, +}; diff --git a/theme/keywind/login/components/button/icon.ftl b/theme/keywind/login/components/button/icon.ftl new file mode 100644 index 0000000..76b4896 --- /dev/null +++ b/theme/keywind/login/components/button/icon.ftl @@ -0,0 +1,10 @@ +<#macro kw component="span" rest...> + <${component} + class="absolute left-0 ml-3 text-lg" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#nested> + + diff --git a/theme/keywind/login/components/button/primary.ftl b/theme/keywind/login/components/button/primary.ftl new file mode 100644 index 0000000..4b740e6 --- /dev/null +++ b/theme/keywind/login/components/button/primary.ftl @@ -0,0 +1,10 @@ +<#macro kw component="button" rest...> + <${component} + class="bg-primary-600 flex justify-center px-4 py-2 relative rounded-lg text-sm text-white w-full focus:outline-none focus:ring-2 focus:ring-primary-600 focus:ring-offset-2 hover:bg-primary-700" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#nested> + + diff --git a/theme/keywind/login/components/checkbox/primary.ftl b/theme/keywind/login/components/checkbox/primary.ftl new file mode 100644 index 0000000..05c9c07 --- /dev/null +++ b/theme/keywind/login/components/checkbox/primary.ftl @@ -0,0 +1,17 @@ +<#macro kw name checked=false rest...> +
+ checked + class="border-gray-300 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50" + id="${name}" + name="${name}" + type="checkbox" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + +
+ diff --git a/theme/keywind/login/components/document.ftl b/theme/keywind/login/components/document.ftl new file mode 100644 index 0000000..4ea53ff --- /dev/null +++ b/theme/keywind/login/components/document.ftl @@ -0,0 +1,31 @@ +<#macro kw> + ${msg("loginTitle", (realm.displayName!""))} + + + + + + <#if properties.meta?has_content> + <#list properties.meta?split(" ") as meta> + + + + + <#if properties.favicons?has_content> + <#list properties.favicons?split(" ") as favicon> + + + + + <#if properties.styles?has_content> + <#list properties.styles?split(" ") as style> + + + + + <#if properties.scripts?has_content> + <#list properties.scripts?split(" ") as script> + + + + diff --git a/theme/keywind/login/components/icon/chevron-down.ftl b/theme/keywind/login/components/icon/chevron-down.ftl new file mode 100644 index 0000000..9e21e8f --- /dev/null +++ b/theme/keywind/login/components/icon/chevron-down.ftl @@ -0,0 +1,6 @@ +<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/outline/chevron-down.svg --> +<#macro kw> + + + + diff --git a/theme/keywind/login/components/icon/external-link.ftl b/theme/keywind/login/components/icon/external-link.ftl new file mode 100644 index 0000000..f18b6b2 --- /dev/null +++ b/theme/keywind/login/components/icon/external-link.ftl @@ -0,0 +1,6 @@ +<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/outline/external-link.svg --> +<#macro kw> + + + + diff --git a/theme/keywind/login/components/input/primary.ftl b/theme/keywind/login/components/input/primary.ftl new file mode 100644 index 0000000..4cba2e2 --- /dev/null +++ b/theme/keywind/login/components/input/primary.ftl @@ -0,0 +1,23 @@ +<#macro kw invalid name autofocus=false disabled=false message=true required=true rest...> + + autofocus + <#if disabled>disabled + <#if required>required + aria-invalid="${messagesPerField.existsError(invalid)?c}" + class="block border-gray-300 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" + id="${name}" + name="${name}" + placeholder="<#compress><#nested>" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#if message && messagesPerField.existsError(invalid)> +
+ ${kcSanitize(messagesPerField.getFirstError(invalid))?no_esc} +
+ + diff --git a/theme/keywind/login/components/label/username.ftl b/theme/keywind/login/components/label/username.ftl new file mode 100644 index 0000000..6c01d6b --- /dev/null +++ b/theme/keywind/login/components/label/username.ftl @@ -0,0 +1,11 @@ +<#macro kw> + <#compress> + <#if !realm.loginWithEmailAllowed> + ${msg("username")} + <#elseif !realm.registrationEmailAsUsername> + ${msg("usernameOrEmail")} + <#else> + ${msg("email")} + + + diff --git a/theme/keywind/login/components/layout/alerts.ftl b/theme/keywind/login/components/layout/alerts.ftl new file mode 100644 index 0000000..da6b3f1 --- /dev/null +++ b/theme/keywind/login/components/layout/alerts.ftl @@ -0,0 +1,18 @@ +<#macro kw> + <#switch message.type> + <#case "error"> + <#assign color="bg-red-100 text-red-600"> + <#case "info"> + <#assign color="bg-blue-100 text-blue-600"> + <#case "success"> + <#assign color="bg-green-100 text-green-600"> + <#case "warning"> + <#assign color="bg-orange-100 text-orange-600"> + <#default> + <#assign color="bg-blue-100 text-blue-600"> + + + + diff --git a/theme/keywind/login/components/layout/another-way.ftl b/theme/keywind/login/components/layout/another-way.ftl new file mode 100644 index 0000000..24f464e --- /dev/null +++ b/theme/keywind/login/components/layout/another-way.ftl @@ -0,0 +1,10 @@ +<#import "../button/primary.ftl" as buttonPrimary> + +<#macro kw> +
+ + <@buttonPrimary.kw type="submit"> + ${msg("doTryAnotherWay")} + +
+ diff --git a/theme/keywind/login/components/layout/card-footer.ftl b/theme/keywind/login/components/layout/card-footer.ftl new file mode 100644 index 0000000..4d502ff --- /dev/null +++ b/theme/keywind/login/components/layout/card-footer.ftl @@ -0,0 +1,5 @@ +<#macro kw> + + diff --git a/theme/keywind/login/components/layout/card-header.ftl b/theme/keywind/login/components/layout/card-header.ftl new file mode 100644 index 0000000..4dd3be4 --- /dev/null +++ b/theme/keywind/login/components/layout/card-header.ftl @@ -0,0 +1,5 @@ +<#macro kw> +
+ <#nested> +
+ diff --git a/theme/keywind/login/components/layout/card-main.ftl b/theme/keywind/login/components/layout/card-main.ftl new file mode 100644 index 0000000..2848132 --- /dev/null +++ b/theme/keywind/login/components/layout/card-main.ftl @@ -0,0 +1,5 @@ +<#macro kw> +
+ <#nested> +
+ diff --git a/theme/keywind/login/components/layout/card.ftl b/theme/keywind/login/components/layout/card.ftl new file mode 100644 index 0000000..836fff6 --- /dev/null +++ b/theme/keywind/login/components/layout/card.ftl @@ -0,0 +1,5 @@ +<#macro kw> +
+ <#nested> +
+ diff --git a/theme/keywind/login/components/layout/container.ftl b/theme/keywind/login/components/layout/container.ftl new file mode 100644 index 0000000..985284b --- /dev/null +++ b/theme/keywind/login/components/layout/container.ftl @@ -0,0 +1,7 @@ +<#macro kw> +
+
+ <#nested> +
+
+ diff --git a/theme/keywind/login/components/layout/locales.ftl b/theme/keywind/login/components/layout/locales.ftl new file mode 100644 index 0000000..5bf69de --- /dev/null +++ b/theme/keywind/login/components/layout/locales.ftl @@ -0,0 +1,28 @@ +<#import "../icon/chevron-down.ftl" as iconChevronDown> +<#import "../link/secondary.ftl" as linkSecondary> + +<#macro kw> +
+ <@linkSecondary.kw component="button" type="button" @click="open = true"> +
+ ${locale.current} + <@iconChevronDown.kw /> +
+ +
+ <#list locale.supported as locales> + <#if locale.current != locales.label> +
+ <@linkSecondary.kw href=locales.url> + ${locales.label} + +
+ + + +
+ diff --git a/theme/keywind/login/components/layout/nav.ftl b/theme/keywind/login/components/layout/nav.ftl new file mode 100644 index 0000000..81a4abf --- /dev/null +++ b/theme/keywind/login/components/layout/nav.ftl @@ -0,0 +1,5 @@ +<#macro kw> +
+ <#nested> +
+ diff --git a/theme/keywind/login/components/layout/required-fields.ftl b/theme/keywind/login/components/layout/required-fields.ftl new file mode 100644 index 0000000..5789ac1 --- /dev/null +++ b/theme/keywind/login/components/layout/required-fields.ftl @@ -0,0 +1,3 @@ +<#macro kw> +
* ${msg("requiredFields")}
+ diff --git a/theme/keywind/login/components/layout/subtitle.ftl b/theme/keywind/login/components/layout/subtitle.ftl new file mode 100644 index 0000000..984bc9c --- /dev/null +++ b/theme/keywind/login/components/layout/subtitle.ftl @@ -0,0 +1,3 @@ +<#macro kw> +

<#nested "header">

+ diff --git a/theme/keywind/login/components/layout/title.ftl b/theme/keywind/login/components/layout/title.ftl new file mode 100644 index 0000000..ea381bf --- /dev/null +++ b/theme/keywind/login/components/layout/title.ftl @@ -0,0 +1,5 @@ +<#macro kw> +
+ ${kcSanitize(msg("loginTitleHtml", (realm.displayNameHtml!"")))?no_esc} +
+ diff --git a/theme/keywind/login/components/layout/username.ftl b/theme/keywind/login/components/layout/username.ftl new file mode 100644 index 0000000..c0ccf8b --- /dev/null +++ b/theme/keywind/login/components/layout/username.ftl @@ -0,0 +1,16 @@ +<#import "../button/icon.ftl" as buttonIcon > +<#import "../button/primary.ftl" as buttonPrimary> +<#import "../icon/external-link.ftl" as iconExternalLink> + +<#macro kw> + <#nested "show-username"> +
+
${auth.attemptedUsername}
+ <@buttonPrimary.kw component="a" href="${url.loginRestartFlowUrl}"> + <@buttonIcon.kw> + <@iconExternalLink.kw /> + + ${msg("restartLoginTooltip")} + +
+ diff --git a/theme/keywind/login/components/link/primary.ftl b/theme/keywind/login/components/link/primary.ftl new file mode 100644 index 0000000..c66d3a3 --- /dev/null +++ b/theme/keywind/login/components/link/primary.ftl @@ -0,0 +1,10 @@ +<#macro kw component="a" rest...> + <${component} + class="text-primary-600 hover:text-primary-500" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#nested> + + diff --git a/theme/keywind/login/components/link/secondary.ftl b/theme/keywind/login/components/link/secondary.ftl new file mode 100644 index 0000000..84590df --- /dev/null +++ b/theme/keywind/login/components/link/secondary.ftl @@ -0,0 +1,10 @@ +<#macro kw component="a" rest...> + <${component} + class="text-gray-600 hover:text-black" + <#list rest as attrName, attrValue> + ${attrName}="${attrValue}" + + > + <#nested> + + diff --git a/theme/keywind/login/components/provider.ftl b/theme/keywind/login/components/provider.ftl new file mode 100644 index 0000000..dfcba4c --- /dev/null +++ b/theme/keywind/login/components/provider.ftl @@ -0,0 +1,22 @@ +<#import "./socials.ftl" as socials> + +<#macro kw> +
${msg("identity-provider-login-label")}
+ + diff --git a/theme/keywind/login/components/socials.ftl b/theme/keywind/login/components/socials.ftl new file mode 100644 index 0000000..fa99fcb --- /dev/null +++ b/theme/keywind/login/components/socials.ftl @@ -0,0 +1,37 @@ +<#-- https://facebookbrand.com/facebookapp/assets/f-logo/ --> +<#macro facebook> + + + + + + +<#-- https://github.com/logos --> +<#macro github> + + + + + + +<#-- https://developers.google.com/identity/branding-guidelines --> +<#macro google> + + + + + + + + + +<#-- https://docs.microsoft.com/azure/active-directory/develop/howto-add-branding-in-azure-ad-apps --> +<#macro microsoft> + + + + + + + + diff --git a/theme/keywind/login/login-reset-password.ftl b/theme/keywind/login/login-reset-password.ftl new file mode 100644 index 0000000..6c42a97 --- /dev/null +++ b/theme/keywind/login/login-reset-password.ftl @@ -0,0 +1,42 @@ +<#import "template.ftl" as layout> +<#import "components/button/primary.ftl" as buttonPrimary> +<#import "components/input/primary.ftl" as inputPrimary> +<#import "components/label/username.ftl" as labelUsername> +<#import "components/link/secondary.ftl" as linkSecondary> + +<@layout.registrationLayout + displayInfo=true + displayMessage=!messagesPerField.existsError("username") + ; + section +> + <#if section="header"> + ${msg("emailForgotTitle")} + <#elseif section="form"> +
+
+ <@inputPrimary.kw + autocomplete=realm.loginWithEmailAllowed?string("email", "username") + autofocus=true + invalid=["username"] + name="username" + type=realm.loginWithEmailAllowed?string("email", "text") + value=(auth?has_content && auth.showUsername())?then(auth.attemptedUsername, '') + > + <@labelUsername.kw /> + +
+
+ <@buttonPrimary.kw type="submit"> + ${msg("doSubmit")} + +
+
+ <#elseif section="info"> + ${msg("emailInstruction")} + <#elseif section="nav"> + <@linkSecondary.kw href=url.loginUrl> + ${kcSanitize(msg("backToLogin"))?no_esc} + + + diff --git a/theme/keywind/login/login.ftl b/theme/keywind/login/login.ftl new file mode 100644 index 0000000..c704742 --- /dev/null +++ b/theme/keywind/login/login.ftl @@ -0,0 +1,85 @@ +<#import "template.ftl" as layout> +<#import "components/provider.ftl" as provider> +<#import "components/button/primary.ftl" as buttonPrimary> +<#import "components/checkbox/primary.ftl" as checkboxPrimary> +<#import "components/input/primary.ftl" as inputPrimary> +<#import "components/label/username.ftl" as labelUsername> +<#import "components/link/primary.ftl" as linkPrimary> + +<@layout.registrationLayout + displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled?? + displayMessage=!messagesPerField.existsError("username", "password") + ; + section +> + <#if section="header"> + ${msg("loginAccountTitle")} + <#elseif section="form"> + <#if realm.password> +
+ +
+ <@inputPrimary.kw + autocomplete=realm.loginWithEmailAllowed?string("email", "username") + autofocus=true + disabled=usernameEditDisabled?? + invalid=["username", "password"] + name="username" + type=realm.loginWithEmailAllowed?string("email", "text") + value=(login.username)!'' + > + <@labelUsername.kw /> + +
+
+ <@inputPrimary.kw + invalid=["username", "password"] + message=false + name="password" + type="password" + > + ${msg("password")} + +
+
+ <#if realm.rememberMe && !usernameEditDisabled??> + <@checkboxPrimary.kw checked=login.rememberMe?? name="rememberMe"> + ${msg("rememberMe")} + + + <#if realm.resetPasswordAllowed> + <@linkPrimary.kw href=url.loginResetCredentialsUrl> + ${msg("doForgotPassword")} + + +
+
+ <@buttonPrimary.kw name="login" type="submit"> + ${msg("doLogIn")} + +
+
+ + <#if realm.password && social.providers??> + <@provider.kw /> + + <#elseif section="info"> + <#if realm.password && realm.registrationAllowed && !registrationDisabled??> +
+ ${msg("noAccount")} + <@linkPrimary.kw href=url.registrationUrl> + ${msg("doRegister")} + +
+ + + diff --git a/theme/keywind/login/register.ftl b/theme/keywind/login/register.ftl new file mode 100644 index 0000000..2033d2d --- /dev/null +++ b/theme/keywind/login/register.ftl @@ -0,0 +1,101 @@ +<#import "template.ftl" as layout> +<#import "components/button/primary.ftl" as buttonPrimary> +<#import "components/input/primary.ftl" as inputPrimary> +<#import "components/link/secondary.ftl" as linkSecondary> + +<@layout.registrationLayout + displayMessage=!messagesPerField.existsError("firstName", "lastName", "email", "username", "password", "password-confirm") + ; + section +> + <#if section="header"> + ${msg("registerTitle")} + <#elseif section="form"> +
+
+ <@inputPrimary.kw + autocomplete="given-name" + autofocus=true + invalid=["firstName"] + name="firstName" + type="text" + value=(register.formData.firstName)!'' + > + ${msg("firstName")} + +
+
+ <@inputPrimary.kw + autocomplete="family-name" + invalid=["lastName"] + name="lastName" + type="text" + value=(register.formData.lastName)!'' + > + ${msg("lastName")} + +
+
+ <@inputPrimary.kw + autocomplete="email" + invalid=["email"] + name="email" + type="email" + value=(register.formData.email)!'' + > + ${msg("email")} + +
+ <#if !realm.registrationEmailAsUsername> +
+ <@inputPrimary.kw + autocomplete="username" + invalid=["username"] + name="username" + type="text" + value=(register.formData.username)!'' + > + ${msg("username")} + +
+ + <#if passwordRequired??> +
+ <@inputPrimary.kw + autocomplete="new-password" + invalid=["password", "password-confirm"] + message=false + name="password" + type="password" + > + ${msg("password")} + +
+
+ <@inputPrimary.kw + autocomplete="new-password" + invalid=["password-confirm"] + name="password-confirm" + type="password" + > + ${msg("passwordConfirm")} + +
+ + <#if recaptchaRequired??> +
+
+
+ +
+ <@buttonPrimary.kw type="submit"> + ${msg("doRegister")} + +
+
+ <#elseif section="nav"> + <@linkSecondary.kw href=url.loginUrl> + ${kcSanitize(msg("backToLogin"))?no_esc} + + + diff --git a/theme/keywind/login/resources/dist/index.css b/theme/keywind/login/resources/dist/index.css new file mode 100644 index 0000000..399f603 --- /dev/null +++ b/theme/keywind/login/resources/dist/index.css @@ -0,0 +1 @@ +/*! tailwindcss v2.2.4 | MIT License | https://tailwindcss.com*//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */html{-webkit-text-size-adjust:100%;line-height:1.15;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;margin:0}hr{color:inherit;height:0}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}:-moz-ui-invalid{box-shadow:none}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:transparent;background-image:none}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{font-family:inherit;line-height:inherit}*,:after,:before{border:0 solid;box-sizing:border-box}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{color:inherit;line-height:inherit;padding:0}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}*,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-border-opacity:1;--tw-shadow:0 0 #0000;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-blur:var(--tw-empty,/*!*/ /*!*/);--tw-brightness:var(--tw-empty,/*!*/ /*!*/);--tw-contrast:var(--tw-empty,/*!*/ /*!*/);--tw-grayscale:var(--tw-empty,/*!*/ /*!*/);--tw-hue-rotate:var(--tw-empty,/*!*/ /*!*/);--tw-invert:var(--tw-empty,/*!*/ /*!*/);--tw-saturate:var(--tw-empty,/*!*/ /*!*/);--tw-sepia:var(--tw-empty,/*!*/ /*!*/);--tw-drop-shadow:var(--tw-empty,/*!*/ /*!*/);--tw-filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);--tw-backdrop-blur:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-brightness:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-contrast:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-grayscale:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-hue-rotate:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-invert:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-opacity:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-saturate:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-sepia:var(--tw-empty,/*!*/ /*!*/);--tw-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);border-color:rgba(229,231,235,var(--tw-border-opacity))}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);outline:2px solid transparent;outline-offset:2px}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select{-webkit-print-color-adjust:exact;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;color-adjust:exact;padding-right:2.5rem}[multiple]{-webkit-print-color-adjust:unset;background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;color-adjust:unset;padding-right:.75rem}[type=checkbox],[type=radio]{-webkit-print-color-adjust:exact;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-origin:border-box;border-color:#6b7280;border-width:1px;color:#2563eb;color-adjust:exact;display:inline-block;flex-shrink:0;height:1rem;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1rem}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);outline:2px solid transparent;outline-offset:2px}[type=checkbox]:checked,[type=radio]:checked{background-color:currentColor;background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{background-color:currentColor;border-color:transparent}[type=checkbox]:indeterminate{background-color:currentColor;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{background-color:currentColor;border-color:transparent}[type=file]{background:unset;border-color:inherit;border-radius:0;border-width:0;font-size:unset;line-height:inherit;padding:0}[type=file]:focus{outline:1px auto -webkit-focus-ring-color}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.separate{align-items:center;display:flex;text-align:center}.separate:after,.separate:before{--tw-border-opacity:1;border-bottom-width:1px;border-color:rgba(209,213,219,var(--tw-border-opacity));content:"";flex:1 1 0%}.separate:not(:empty):after{margin-left:.5rem}.separate:not(:empty):before{margin-right:.5rem}.sr-only{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.absolute{position:absolute}.relative{position:relative}.left-0{left:0}.bottom-0{bottom:0}.-left-4{left:-1rem}.m-0{margin:0}.ml-3{margin-left:.75rem}.ml-2{margin-left:.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.mb-6{margin-bottom:1.5rem}.mb-4{margin-bottom:1rem}.mb-2{margin-bottom:.5rem}.block{display:block}.flex{display:flex}.hidden{display:none}.h-4{height:1rem}.max-h-80{max-height:20rem}.min-h-screen{min-height:100vh}.w-full{width:100%}.w-4{width:1rem}.max-w-md{max-width:28rem}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.overflow-y-scroll{overflow-y:scroll}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.border-gray-300{--tw-border-opacity:1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgba(37,99,235,var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgba(254,226,226,var(--tw-bg-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgba(219,234,254,var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgba(209,250,229,var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.p-4{padding:1rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.text-sm{font-size:.875rem;line-height:1.25rem}.text-5xl{font-size:3rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.font-bold{font-weight:700}.text-white{--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgba(37,99,235,var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgba(17,24,39,var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgba(220,38,38,var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgba(37,99,235,var(--tw-text-opacity))}.text-green-600{--tw-text-opacity:1;color:rgba(5,150,105,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}@layer components{.separate{align-items:center;display:flex;text-align:center}.separate:after,.separate:before{--tw-border-opacity:1;border-bottom-width:1px;border-color:rgba(209,213,219,var(--tw-border-opacity));content:"";flex:1 1 0%}.separate:not(:empty):after{margin-left:.5rem}.separate:not(:empty):before{margin-right:.5rem}}.hover\:bg-primary-700:hover{--tw-bg-opacity:1;background-color:rgba(29,78,216,var(--tw-bg-opacity))}.hover\:text-primary-500:hover{--tw-text-opacity:1;color:rgba(59,130,246,var(--tw-text-opacity))}.hover\:text-black:hover{--tw-text-opacity:1;color:rgba(0,0,0,var(--tw-text-opacity))}.focus\:border-primary-300:focus{--tw-border-opacity:1;border-color:rgba(147,197,253,var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-primary-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgba(37,99,235,var(--tw-ring-opacity))}.focus\:ring-primary-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgba(191,219,254,var(--tw-ring-opacity))}.focus\:ring-opacity-50:focus{--tw-ring-opacity:0.5}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}@media (min-width:640px){.sm\:py-16{padding-bottom:4rem;padding-top:4rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}} \ No newline at end of file diff --git a/theme/keywind/login/resources/dist/index.js b/theme/keywind/login/resources/dist/index.js new file mode 100644 index 0000000..d57e545 --- /dev/null +++ b/theme/keywind/login/resources/dist/index.js @@ -0,0 +1,7 @@ +var Dr=Object.defineProperty;var $r=Object.prototype.hasOwnProperty;var Jt=Object.getOwnPropertySymbols,zr=Object.prototype.propertyIsEnumerable;var Qt=(e,t,n)=>t in e?Dr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,yt=(e,t)=>{for(var n in t||(t={}))$r.call(t,n)&&Qt(e,n,t[n]);if(Jt)for(var n of Jt(t))zr.call(t,n)&&Qt(e,n,t[n]);return e};var Hr=Object.create,vt=Object.defineProperty,Br=Object.getPrototypeOf,qr=Object.prototype.hasOwnProperty,Ur=Object.getOwnPropertyNames,Gr=Object.getOwnPropertyDescriptor,Vr=e=>vt(e,"__esModule",{value:!0}),We=(e,t)=>()=>(t||(t={exports:{}},e(t.exports,t)),t.exports),Wr=(e,t,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Ur(t))!qr.call(e,i)&&i!=="default"&&vt(e,i,{get:()=>t[i],enumerable:!(n=Gr(t,i))||n.enumerable});return e},Yr=e=>Wr(Vr(vt(e!=null?Hr(Br(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e),Jr=We(e=>{Object.defineProperty(e,"__esModule",{value:!0});function t(l,d){let p=Object.create(null),v=l.split(",");for(let S=0;S!!p[S.toLowerCase()]:S=>!!p[S]}var n={[1]:"TEXT",[2]:"CLASS",[4]:"STYLE",[8]:"PROPS",[16]:"FULL_PROPS",[32]:"HYDRATE_EVENTS",[64]:"STABLE_FRAGMENT",[128]:"KEYED_FRAGMENT",[256]:"UNKEYED_FRAGMENT",[512]:"NEED_PATCH",[1024]:"DYNAMIC_SLOTS",[2048]:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},i={[1]:"STABLE",[2]:"DYNAMIC",[3]:"FORWARDED"},s="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt",a=t(s),o=2;function u(l,d=0,p=l.length){let v=l.split(/\r?\n/),S=0,C=[];for(let P=0;P=d){for(let K=P-o;K<=P+o||p>S;K++){if(K<0||K>=v.length)continue;let J=K+1;C.push(`${J}${" ".repeat(Math.max(3-String(J).length,0))}| ${v[K]}`);let pe=v[K].length;if(K===P){let he=d-(S-pe)+1,_t=Math.max(1,p>S?pe-he:p-d);C.push(" | "+" ".repeat(he)+"^".repeat(_t))}else if(K>P){if(p>S){let he=Math.max(Math.min(p-S,pe),1);C.push(" | "+"^".repeat(he))}S+=pe+1}}break}return C.join(` +`)}var g="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",m=t(g),E=t(g+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected"),x=/[>/="'\u0009\u000a\u000c\u0020]/,D={};function N(l){if(D.hasOwnProperty(l))return D[l];let d=x.test(l);return d&&console.error(`unsafe attribute name: ${l}`),D[l]=!d}var H={acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},V=t("animation-iteration-count,border-image-outset,border-image-slice,border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-miterlimit,stroke-opacity,stroke-width"),y=t("accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap");function T(l){if(q(l)){let d={};for(let p=0;p{if(p){let v=p.split(R);v.length>1&&(d[v[0].trim()]=v[1].trim())}}),d}function B(l){let d="";if(!l)return d;for(let p in l){let v=l[p],S=p.startsWith("--")?p:ee(p);(Y(v)||typeof v=="number"&&V(S))&&(d+=`${S}:${v};`)}return d}function W(l){let d="";if(Y(l))d=l;else if(q(l))for(let p=0;p]/;function Le(l){let d=""+l,p=it.exec(d);if(!p)return d;let v="",S,C,P=0;for(C=p.index;C||--!>|Q(p,d))}var lt=l=>l==null?"":z(l)?JSON.stringify(l,ct,2):String(l),ct=(l,d)=>U(d)?{[`Map(${d.size})`]:[...d.entries()].reduce((p,[v,S])=>(p[`${v} =>`]=S,p),{})}:Oe(d)?{[`Set(${d.size})`]:[...d.values()]}:z(d)&&!q(d)&&!xe(d)?String(d):d,Se=["bigInt","optionalChaining","nullishCoalescingOperator"],Ae=Object.freeze({}),Ee=Object.freeze([]),ie=()=>{},ae=()=>!1,se=/^on[^a-z]/,oe=l=>se.test(l),De=l=>l.startsWith("onUpdate:"),$e=Object.assign,ze=(l,d)=>{let p=l.indexOf(d);p>-1&&l.splice(p,1)},He=Object.prototype.hasOwnProperty,le=(l,d)=>He.call(l,d),q=Array.isArray,U=l=>Z(l)==="[object Map]",Oe=l=>Z(l)==="[object Set]",ce=l=>l instanceof Date,ue=l=>typeof l=="function",Y=l=>typeof l=="string",ut=l=>typeof l=="symbol",z=l=>l!==null&&typeof l=="object",ft=l=>z(l)&&ue(l.then)&&ue(l.catch),Be=Object.prototype.toString,Z=l=>Be.call(l),dt=l=>Z(l).slice(8,-1),xe=l=>Z(l)==="[object Object]",qe=l=>Y(l)&&l!=="NaN"&&l[0]!=="-"&&""+parseInt(l,10)===l,Ue=t(",key,ref,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),X=l=>{let d=Object.create(null);return p=>d[p]||(d[p]=l(p))},Ge=/-(\w)/g,pt=X(l=>l.replace(Ge,(d,p)=>p?p.toUpperCase():"")),ht=/\B([A-Z])/g,ee=X(l=>l.replace(ht,"-$1").toLowerCase()),Ve=X(l=>l.charAt(0).toUpperCase()+l.slice(1)),Te=X(l=>l?`on${Ve(l)}`:""),gt=(l,d)=>l!==d&&(l===l||d===d),fe=(l,d)=>{for(let p=0;p{Object.defineProperty(l,d,{configurable:!0,enumerable:!1,value:p})},Re=l=>{let d=parseFloat(l);return isNaN(d)?l:d},Me,O=()=>Me||(Me=typeof globalThis!="undefined"?globalThis:typeof self!="undefined"?self:typeof window!="undefined"?window:typeof global!="undefined"?global:{});e.EMPTY_ARR=Ee,e.EMPTY_OBJ=Ae,e.NO=ae,e.NOOP=ie,e.PatchFlagNames=n,e.babelParserDefaultPlugins=Se,e.camelize=pt,e.capitalize=Ve,e.def=de,e.escapeHtml=Le,e.escapeHtmlComment=st,e.extend=$e,e.generateCodeFrame=u,e.getGlobalThis=O,e.hasChanged=gt,e.hasOwn=le,e.hyphenate=ee,e.invokeArrayFns=fe,e.isArray=q,e.isBooleanAttr=E,e.isDate=ce,e.isFunction=ue,e.isGloballyWhitelisted=a,e.isHTMLTag=re,e.isIntegerKey=qe,e.isKnownAttr=y,e.isMap=U,e.isModelListener=De,e.isNoUnitNumericStyleProp=V,e.isObject=z,e.isOn=oe,e.isPlainObject=xe,e.isPromise=ft,e.isReservedProp=Ue,e.isSSRSafeAttrName=N,e.isSVGTag=ne,e.isSet=Oe,e.isSpecialBooleanAttr=m,e.isString=Y,e.isSymbol=ut,e.isVoidTag=nt,e.looseEqual=Q,e.looseIndexOf=Ke,e.makeMap=t,e.normalizeClass=W,e.normalizeStyle=T,e.objectToString=Be,e.parseStringStyle=$,e.propsToAttrMap=H,e.remove=ze,e.slotFlagsText=i,e.stringifyStyle=B,e.toDisplayString=lt,e.toHandlerKey=Te,e.toNumber=Re,e.toRawType=dt,e.toTypeString=Z}),Qr=We((e,t)=>{t.exports=Jr()}),Zr=We(e=>{Object.defineProperty(e,"__esModule",{value:!0});var t=Qr(),n=new WeakMap,i=[],s,a=Symbol("iterate"),o=Symbol("Map key iterate");function u(r){return r&&r._isEffect===!0}function g(r,c=t.EMPTY_OBJ){u(r)&&(r=r.raw);let f=x(r,c);return c.lazy||f(),f}function m(r){r.active&&(D(r),r.options.onStop&&r.options.onStop(),r.active=!1)}var E=0;function x(r,c){let f=function(){if(!f.active)return r();if(!i.includes(f)){D(f);try{return y(),i.push(f),s=f,r()}finally{i.pop(),T(),s=i[i.length-1]}}};return f.id=E++,f.allowRecurse=!!c.allowRecurse,f._isEffect=!0,f.active=!0,f.raw=r,f.deps=[],f.options=c,f}function D(r){let{deps:c}=r;if(c.length){for(let f=0;f{k&&k.forEach(G=>{(G!==s||G.allowRecurse)&&M.add(G)})};if(c==="clear")b.forEach(I);else if(f==="length"&&t.isArray(r))b.forEach((k,G)=>{(G==="length"||G>=_)&&I(k)});else switch(f!==void 0&&I(b.get(f)),c){case"add":t.isArray(r)?t.isIntegerKey(f)&&I(b.get("length")):(I(b.get(a)),t.isMap(r)&&I(b.get(o)));break;case"delete":t.isArray(r)||(I(b.get(a)),t.isMap(r)&&I(b.get(o)));break;case"set":t.isMap(r)&&I(b.get(a));break}let Ce=k=>{k.options.onTrigger&&k.options.onTrigger({effect:k,target:r,key:f,type:c,newValue:_,oldValue:h,oldTarget:A}),k.options.scheduler?k.options.scheduler(k):k()};M.forEach(Ce)}var $=t.makeMap("__proto__,__v_isRef,__isVue"),B=new Set(Object.getOwnPropertyNames(Symbol).map(r=>Symbol[r]).filter(t.isSymbol)),W=ne(),et=ne(!1,!0),tt=ne(!0),rt=ne(!0,!0),re={};["includes","indexOf","lastIndexOf"].forEach(r=>{let c=Array.prototype[r];re[r]=function(...f){let _=O(this);for(let A=0,b=this.length;A{let c=Array.prototype[r];re[r]=function(...f){V();let _=c.apply(this,f);return T(),_}});function ne(r=!1,c=!1){return function(_,h,A){if(h==="__v_isReactive")return!r;if(h==="__v_isReadonly")return r;if(h==="__v_raw"&&A===(r?c?Ge:X:c?Ue:qe).get(_))return _;let b=t.isArray(_);if(!r&&b&&t.hasOwn(re,h))return Reflect.get(re,h,A);let M=Reflect.get(_,h,A);return(t.isSymbol(h)?B.has(h):$(h))||(r||w(_,"get",h),c)?M:p(M)?!b||!t.isIntegerKey(h)?M.value:M:t.isObject(M)?r?Te(M):ee(M):M}}var nt=Le(),it=Le(!0);function Le(r=!1){return function(f,_,h,A){let b=f[_];if(!r&&(h=O(h),b=O(b),!t.isArray(f)&&p(b)&&!p(h)))return b.value=h,!0;let M=t.isArray(f)&&t.isIntegerKey(_)?Number(_)t.isObject(r)?ee(r):r,Ae=r=>t.isObject(r)?Te(r):r,Ee=r=>r,ie=r=>Reflect.getPrototypeOf(r);function ae(r,c,f=!1,_=!1){r=r.__v_raw;let h=O(r),A=O(c);c!==A&&!f&&w(h,"get",c),!f&&w(h,"get",A);let{has:b}=ie(h),M=_?Ee:f?Ae:Se;if(b.call(h,c))return M(r.get(c));if(b.call(h,A))return M(r.get(A));r!==h&&r.get(c)}function se(r,c=!1){let f=this.__v_raw,_=O(f),h=O(r);return r!==h&&!c&&w(_,"has",r),!c&&w(_,"has",h),r===h?f.has(r):f.has(r)||f.has(h)}function oe(r,c=!1){return r=r.__v_raw,!c&&w(O(r),"iterate",a),Reflect.get(r,"size",r)}function De(r){r=O(r);let c=O(this);return ie(c).has.call(c,r)||(c.add(r),R(c,"add",r,r)),this}function $e(r,c){c=O(c);let f=O(this),{has:_,get:h}=ie(f),A=_.call(f,r);A?xe(f,_,r):(r=O(r),A=_.call(f,r));let b=h.call(f,r);return f.set(r,c),A?t.hasChanged(c,b)&&R(f,"set",r,c,b):R(f,"add",r,c),this}function ze(r){let c=O(this),{has:f,get:_}=ie(c),h=f.call(c,r);h?xe(c,f,r):(r=O(r),h=f.call(c,r));let A=_?_.call(c,r):void 0,b=c.delete(r);return h&&R(c,"delete",r,void 0,A),b}function He(){let r=O(this),c=r.size!==0,f=t.isMap(r)?new Map(r):new Set(r),_=r.clear();return c&&R(r,"clear",void 0,void 0,f),_}function le(r,c){return function(_,h){let A=this,b=A.__v_raw,M=O(b),I=c?Ee:r?Ae:Se;return!r&&w(M,"iterate",a),b.forEach((Ce,k)=>_.call(h,I(Ce),I(k),A))}}function q(r,c,f){return function(..._){let h=this.__v_raw,A=O(h),b=t.isMap(A),M=r==="entries"||r===Symbol.iterator&&b,I=r==="keys"&&b,Ce=h[r](..._),k=f?Ee:c?Ae:Se;return!c&&w(A,"iterate",I?o:a),{next(){let{value:G,done:mt}=Ce.next();return mt?{value:G,done:mt}:{value:M?[k(G[0]),k(G[1])]:k(G),done:mt}},[Symbol.iterator](){return this}}}}function U(r){return function(...c){{let f=c[0]?`on key "${c[0]}" `:"";console.warn(`${t.capitalize(r)} operation ${f}failed: target is readonly.`,O(this))}return r==="delete"?!1:this}}var Oe={get(r){return ae(this,r)},get size(){return oe(this)},has:se,add:De,set:$e,delete:ze,clear:He,forEach:le(!1,!1)},ce={get(r){return ae(this,r,!1,!0)},get size(){return oe(this)},has:se,add:De,set:$e,delete:ze,clear:He,forEach:le(!1,!0)},ue={get(r){return ae(this,r,!0)},get size(){return oe(this,!0)},has(r){return se.call(this,r,!0)},add:U("add"),set:U("set"),delete:U("delete"),clear:U("clear"),forEach:le(!0,!1)},Y={get(r){return ae(this,r,!0,!0)},get size(){return oe(this,!0)},has(r){return se.call(this,r,!0)},add:U("add"),set:U("set"),delete:U("delete"),clear:U("clear"),forEach:le(!0,!0)},ut=["keys","values","entries",Symbol.iterator];ut.forEach(r=>{Oe[r]=q(r,!1,!1),ue[r]=q(r,!0,!1),ce[r]=q(r,!1,!0),Y[r]=q(r,!0,!0)});function z(r,c){let f=c?r?Y:ce:r?ue:Oe;return(_,h,A)=>h==="__v_isReactive"?!r:h==="__v_isReadonly"?r:h==="__v_raw"?_:Reflect.get(t.hasOwn(f,h)&&h in _?f:_,h,A)}var ft={get:z(!1,!1)},Be={get:z(!1,!0)},Z={get:z(!0,!1)},dt={get:z(!0,!0)};function xe(r,c,f){let _=O(f);if(_!==f&&c.call(r,_)){let h=t.toRawType(r);console.warn(`Reactive ${h} contains both the raw and reactive versions of the same object${h==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var qe=new WeakMap,Ue=new WeakMap,X=new WeakMap,Ge=new WeakMap;function pt(r){switch(r){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ht(r){return r.__v_skip||!Object.isExtensible(r)?0:pt(t.toRawType(r))}function ee(r){return r&&r.__v_isReadonly?r:fe(r,!1,Q,ft,qe)}function Ve(r){return fe(r,!1,lt,Be,Ue)}function Te(r){return fe(r,!0,Ke,Z,X)}function gt(r){return fe(r,!0,ct,dt,Ge)}function fe(r,c,f,_,h){if(!t.isObject(r))return console.warn(`value cannot be made reactive: ${String(r)}`),r;if(r.__v_raw&&!(c&&r.__v_isReactive))return r;let A=h.get(r);if(A)return A;let b=ht(r);if(b===0)return r;let M=new Proxy(r,b===2?_:f);return h.set(r,M),M}function de(r){return Re(r)?de(r.__v_raw):!!(r&&r.__v_isReactive)}function Re(r){return!!(r&&r.__v_isReadonly)}function Me(r){return de(r)||Re(r)}function O(r){return r&&O(r.__v_raw)||r}function l(r){return t.def(r,"__v_skip",!0),r}var d=r=>t.isObject(r)?ee(r):r;function p(r){return Boolean(r&&r.__v_isRef===!0)}function v(r){return P(r)}function S(r){return P(r,!0)}var C=class{constructor(r,c){this._rawValue=r,this._shallow=c,this.__v_isRef=!0,this._value=c?r:d(r)}get value(){return w(O(this),"get","value"),this._value}set value(r){t.hasChanged(O(r),this._rawValue)&&(this._rawValue=r,this._value=this._shallow?r:d(r),R(O(this),"set","value",r))}};function P(r,c=!1){return p(r)?r:new C(r,c)}function K(r){R(O(r),"set","value",r.value)}function J(r){return p(r)?r.value:r}var pe={get:(r,c,f)=>J(Reflect.get(r,c,f)),set:(r,c,f,_)=>{let h=r[c];return p(h)&&!p(f)?(h.value=f,!0):Reflect.set(r,c,f,_)}};function he(r){return de(r)?r:new Proxy(r,pe)}var _t=class{constructor(r){this.__v_isRef=!0;let{get:c,set:f}=r(()=>w(this,"get","value"),()=>R(this,"set","value"));this._get=c,this._set=f}get value(){return this._get()}set value(r){this._set(r)}};function Nr(r){return new _t(r)}function jr(r){Me(r)||console.warn("toRefs() expects a reactive object but received a plain one.");let c=t.isArray(r)?new Array(r.length):{};for(let f in r)c[f]=Yt(r,f);return c}var Fr=class{constructor(r,c){this._object=r,this._key=c,this.__v_isRef=!0}get value(){return this._object[this._key]}set value(r){this._object[this._key]=r}};function Yt(r,c){return p(r[c])?r[c]:new Fr(r,c)}var Lr=class{constructor(r,c,f){this._setter=c,this._dirty=!0,this.__v_isRef=!0,this.effect=g(r,{lazy:!0,scheduler:()=>{this._dirty||(this._dirty=!0,R(O(this),"set","value"))}}),this.__v_isReadonly=f}get value(){let r=O(this);return r._dirty&&(r._value=this.effect(),r._dirty=!1),w(r,"get","value"),r._value}set value(r){this._setter(r)}};function Kr(r){let c,f;return t.isFunction(r)?(c=r,f=()=>{console.warn("Write operation failed: computed value is readonly")}):(c=r.get,f=r.set),new Lr(c,f,t.isFunction(r)||!r.set)}e.ITERATE_KEY=a,e.computed=Kr,e.customRef=Nr,e.effect=g,e.enableTracking=y,e.isProxy=Me,e.isReactive=de,e.isReadonly=Re,e.isRef=p,e.markRaw=l,e.pauseTracking=V,e.proxyRefs=he,e.reactive=ee,e.readonly=Te,e.ref=v,e.resetTracking=T,e.shallowReactive=Ve,e.shallowReadonly=gt,e.shallowRef=S,e.stop=m,e.toRaw=O,e.toRef=Yt,e.toRefs=jr,e.track=w,e.trigger=R,e.triggerRef=K,e.unref=J}),Xr=We((e,t)=>{t.exports=Zr()}),bt=!1,wt=!1,Pe=[];function tn(e){en(e)}function en(e){Pe.includes(e)||Pe.push(e),rn()}function rn(){!wt&&!bt&&(bt=!0,queueMicrotask(nn))}function nn(){bt=!1,wt=!0;for(let e=0;ee.effect(t,{scheduler:n=>{St?tn(n):n()}}),Zt=e.raw}function Xt(e){_e=e}function on(e){let t=()=>{};return[i=>{let s=_e(i);e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(a=>a())}),e._x_effects.add(s),t=()=>{s!==void 0&&(e._x_effects.delete(s),Ye(s))}},()=>{t()}]}var er=[],tr=[],rr=[];function ln(e){rr.push(e)}function cn(e){tr.push(e)}function un(e){er.push(e)}function fn(e,t,n){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(n)}function nr(e,t){!e._x_attributeCleanups||Object.entries(e._x_attributeCleanups).forEach(([n,i])=>{(t===void 0||t.includes(n))&&i.forEach(s=>s()),delete e._x_attributeCleanups[n]})}var At=new MutationObserver(ir),Et=!1;function ar(){At.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),Et=!0}function dn(){At.disconnect(),Et=!1}var ke=[],Ot=!1;function hn(){ke=ke.concat(At.takeRecords()),ke.length&&!Ot&&(Ot=!0,queueMicrotask(()=>{pn(),Ot=!1}))}function pn(){ir(ke),ke.length=0}function j(e){if(!Et)return e();hn(),dn();let t=e();return ar(),t}function ir(e){let t=[],n=[],i=new Map,s=new Map;for(let a=0;ao.nodeType===1&&t.push(o)),e[a].removedNodes.forEach(o=>o.nodeType===1&&n.push(o))),e[a].type==="attributes")){let o=e[a].target,u=e[a].attributeName,g=e[a].oldValue,m=()=>{i.has(o)||i.set(o,[]),i.get(o).push({name:u,value:o.getAttribute(u)})},E=()=>{s.has(o)||s.set(o,[]),s.get(o).push(u)};o.hasAttribute(u)&&g===null?m():o.hasAttribute(u)?(E(),m()):E()}s.forEach((a,o)=>{nr(o,a)}),i.forEach((a,o)=>{er.forEach(u=>u(o,a))});for(let a of t)n.includes(a)||rr.forEach(o=>o(a));for(let a of n)t.includes(a)||tr.forEach(o=>o(a));t=null,n=null,i=null,s=null}function xt(e,t,n){return e._x_dataStack=[t,...Je(n||e)],()=>{e._x_dataStack=e._x_dataStack.filter(i=>i!==t)}}function sr(e,t){let n=e._x_dataStack[0];Object.entries(t).forEach(([i,s])=>{n[i]=s})}function Je(e){return e._x_dataStack?e._x_dataStack:e instanceof ShadowRoot?Je(e.host):e.parentNode?Je(e.parentNode):[]}function or(e){return new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(t=>Object.keys(t)))),has:(t,n)=>e.some(i=>i.hasOwnProperty(n)),get:(t,n)=>(e.find(i=>i.hasOwnProperty(n))||{})[n],set:(t,n,i)=>{let s=e.find(a=>a.hasOwnProperty(n));return s?s[n]=i:e[e.length-1][n]=i,!0}})}function gn(e){let t=i=>typeof i=="object"&&!Array.isArray(i)&&i!==null,n=(i,s="")=>{Object.entries(i).forEach(([a,o])=>{let u=s===""?a:`${s}.${a}`;typeof o=="object"&&o!==null&&o._x_interceptor?i[a]=o.initialize(e,u,a):t(o)&&o!==i&&!(o instanceof Element)&&n(o,u)})};return n(e)}function lr(e,t=()=>{}){let n={initialValue:void 0,_x_interceptor:!0,initialize(i,s,a){return e(this.initialValue,()=>_n(i,s),o=>Tt(i,s,o),s,a)}};return t(n),i=>{if(typeof i=="object"&&i!==null&&i._x_interceptor){let s=n.initialize.bind(n);n.initialize=(a,o,u)=>{let g=i.initialize(a,o,u);return n.initialValue=g,s(a,o,u)}}else n.initialValue=i;return n}}function _n(e,t){return t.split(".").reduce((n,i)=>n[i],e)}function Tt(e,t,n){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=n;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),Tt(e[t[0]],t.slice(1),n)}}var cr={};function te(e,t){cr[e]=t}function Rt(e,t){return Object.entries(cr).forEach(([n,i])=>{Object.defineProperty(e,`$${n}`,{get(){return i(t,{Alpine:me,interceptor:lr})},enumerable:!1})}),e}function Ie(e,t,n={}){let i;return L(e,t)(s=>i=s,n),i}function L(...e){return ur(...e)}var ur=fr;function mn(e){ur=e}function fr(e,t){let n={};Rt(n,e);let i=[n,...Je(e)];if(typeof t=="function")return yn(i,t);let s=vn(i,t);return bn.bind(null,e,t,s)}function yn(e,t){return(n=()=>{},{scope:i={},params:s=[]}={})=>{let a=t.apply(or([i,...e]),s);Qe(n,a)}}var Mt={};function wn(e){if(Mt[e])return Mt[e];let t=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)/.test(e)?`(() => { ${e} })()`:e,i=new t(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`);return Mt[e]=i,i}function vn(e,t){let n=wn(t);return(i=()=>{},{scope:s={},params:a=[]}={})=>{n.result=void 0,n.finished=!1;let o=or([s,...e]),u=n(n,o);n.finished?Qe(i,n.result,o,a):u.then(g=>{Qe(i,g,o,a)})}}function Qe(e,t,n,i){if(typeof t=="function"){let s=t.apply(n,i);s instanceof Promise?s.then(a=>Qe(e,a,n,i)):e(s)}else e(t)}function bn(e,t,n,...i){try{return n(...i)}catch(s){throw console.warn(`Alpine Expression Error: ${s.message} + +Expression: "${t}" + +`,e),s}}var Ct="x-";function Ne(e=""){return Ct+e}function Sn(e){Ct=e}var dr={};function F(e,t){dr[e]=t}function Pt(e,t,n){let i={};return Array.from(t).map(En((a,o)=>i[a]=o)).filter(On).map(xn(i,n)).sort(Tn).map(a=>An(e,a))}var kt=!1,It=[];function Rn(e){kt=!0;let t=()=>{for(;It.length;)It.shift()()},n=()=>{kt=!1,t()};e(t),n()}function An(e,t){let n=()=>{},i=dr[t.type]||n,s=[],a=x=>s.push(x),[o,u]=on(e);s.push(u);let g={Alpine:me,effect:o,cleanup:a,evaluateLater:L.bind(L,e),evaluate:Ie.bind(Ie,e)},m=()=>s.forEach(x=>x());fn(e,t.original,m);let E=()=>{e._x_ignore||e._x_ignoreSelf||(i.inline&&i.inline(e,t,g),i=i.bind(i,e,t,g),kt?It.push(i):i())};return E.runCleanups=m,E}var pr=(e,t)=>({name:n,value:i})=>(n.startsWith(e)&&(n=n.replace(e,t)),{name:n,value:i}),hr=e=>e;function En(e){return({name:t,value:n})=>{let{name:i,value:s}=gr.reduce((a,o)=>o(a),{name:t,value:n});return i!==t&&e(i,t),{name:i,value:s}}}var gr=[];function Nt(e){gr.push(e)}function On({name:e}){return _r().test(e)}var _r=()=>new RegExp(`^${Ct}([^:^.]+)\\b`);function xn(e,t){return({name:n,value:i})=>{let s=n.match(_r()),a=n.match(/:([a-zA-Z0-9\-:]+)/),o=n.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],u=t||e[n]||n;return{type:s?s[1]:null,value:a?a[1]:null,modifiers:o.map(g=>g.replace(".","")),expression:i,original:u}}}var jt="DEFAULT",Ze=["ignore","ref","data","bind","init","for","model","transition","show","if",jt,"element"];function Tn(e,t){let n=Ze.indexOf(e.type)===-1?jt:e.type,i=Ze.indexOf(t.type)===-1?jt:t.type;return Ze.indexOf(n)-Ze.indexOf(i)}function je(e,t,n={}){e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}var Ft=[],Lt=!1;function Dt(e){Ft.push(e),queueMicrotask(()=>{Lt||setTimeout(()=>{Kt()})})}function Kt(){for(Lt=!1;Ft.length;)Ft.shift()()}function Mn(){Lt=!0}function ye(e,t){if(e instanceof ShadowRoot){Array.from(e.children).forEach(s=>ye(s,t));return}let n=!1;if(t(e,()=>n=!0),n)return;let i=e.firstElementChild;for(;i;)ye(i,t),i=i.nextElementSibling}function mr(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function kn(){document.body||mr("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `