diff --git a/package-lock.json b/package-lock.json
index 17e1548a..5c69d128 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,9 +46,6 @@
"webpack": "^5.88.2",
"webpack-cli": "^5.1.1"
},
- "engines": {
- "node": ">=20.0.0"
- },
"optionalDependencies": {
"sharp": "^0.34.3",
"sharp-bmp": "^0.1.5",
@@ -2316,7 +2313,7 @@
"resolved": "src/puter-wisp",
"link": true
},
- "node_modules/@heyputer/puter.js": {
+ "node_modules/@heyputer/puterjs": {
"resolved": "src/puter-js",
"link": true
},
@@ -20241,7 +20238,7 @@
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"mocha": "^10.8.2",
- "rollup": "^3.29.5",
+ "rollup": "^3.21.4",
"rollup-plugin-copy": "^3.4.0"
},
"optionalDependencies": {
@@ -20376,12 +20373,11 @@
"license": "AGPL-3.0-only"
},
"src/puter-js": {
- "name": "@heyputer/puter.js",
- "version": "2.0.11",
+ "name": "@heyputer/puterjs",
+ "version": "1.0.0",
"license": "Apache-2.0",
"dependencies": {
- "@heyputer/kv.js": "^0.1.92",
- "@heyputer/putility": "^1.0.3"
+ "@heyputer/kv.js": "^0.1.92"
},
"devDependencies": {
"concurrently": "^8.2.2",
@@ -20395,7 +20391,7 @@
},
"src/putility": {
"name": "@heyputer/putility",
- "version": "1.0.3",
+ "version": "1.0.2",
"license": "AGPL-3.0-only"
},
"src/terminal": {
@@ -20412,7 +20408,7 @@
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-replace": "^5.0.2",
"http-server": "^14.1.1",
- "mocha": "^10.8.2",
+ "mocha": "^10.2.0",
"rollup": "^3.29.5",
"rollup-plugin-copy": "^3.4.0"
}
diff --git a/src/gui/src/UI/Components/PasswordEntry.js b/src/gui/src/UI/Components/PasswordEntry.js
index da5e3ee1..90ecaf93 100644
--- a/src/gui/src/UI/Components/PasswordEntry.js
+++ b/src/gui/src/UI/Components/PasswordEntry.js
@@ -1,12 +1,23 @@
/**
- * Improved PasswordEntry Component for Puter GUI
- * Features:
- * - DRY: input styles reused from shared CSS class
- * - Password strength meter (weak/medium/strong)
- * - Caps Lock warning
- * - Accessible show/hide toggle button
+ * Copyright (C) 2024-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
*/
+
const Component = use('util.Component');
export default def(class PasswordEntry extends Component {
@@ -25,73 +36,80 @@ export default def(class PasswordEntry extends Component {
display: flex;
flex-direction: column;
}
+ input {
+ flex-grow: 1;
+ }
+ /* TODO: I'd rather not duplicate this */
+ .error {
+ display: none;
+ color: red;
+ border: 1px solid red;
+ border-radius: 4px;
+ padding: 9px;
+ margin-bottom: 15px;
+ text-align: center;
+ font-size: 13px;
+ }
.error-message {
display: none;
color: rgb(215 2 2);
font-size: 14px;
- margin: 10px 0;
+ margin-top: 10px;
+ margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
border: 1px solid rgb(215 2 2);
text-align: center;
}
-
.password-and-toggle {
display: flex;
align-items: center;
gap: 10px;
}
-
.password-and-toggle input {
flex-grow: 1;
}
- .strength-meter {
- height: 6px;
+
+ /* TODO: DRY: This is from style.css */
+ input[type=text], input[type=password], input[type=email], select {
+ width: 100%;
+ padding: 8px;
+ border: 1px solid #ccc;
border-radius: 4px;
- margin-top: 6px;
- background: #eee;
- overflow: hidden;
+ box-sizing: border-box;
+ outline: none;
+ -webkit-font-smoothing: antialiased;
+ color: #393f46;
+ font-size: 14px;
}
- .strength-bar {
- height: 100%;
- width: 0%;
- transition: width 0.3s;
+ /* to prevent auto-zoom on input focus in mobile */
+ .device-phone input[type=text], .device-phone input[type=password], .device-phone input[type=email], .device-phone select {
+ font-size: 17px;
}
- .strength-weak { background: #e74c3c; }
- .strength-medium { background: #f39c12; }
- .strength-strong { background: #2ecc71; }
-
- .caps-warning {
- display: none;
- font-size: 12px;
- margin-top: 5px;
- color: #e67e22;
+ input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, select:focus {
+ border: 2px solid #01a0fd;
+ padding: 7px;
}
`;
create_template ({ template }) {
$(template).html(/*html*/`
`);
}
@@ -101,73 +119,38 @@ export default def(class PasswordEntry extends Component {
}
on_ready ({ listen }) {
- const input = $(this.dom_).find('#password');
- const strengthBar = $(this.dom_).find('.strength-bar');
- const capsWarning = $(this.dom_).find('.caps-warning');
- const errorBox = $(this.dom_).find('.error-message');
-
- // Show errors
listen('error', (error) => {
- if (!error) return errorBox.hide();
- errorBox.text(error).show();
+ if ( ! error ) return $(this.dom_).find('.error').hide();
+ $(this.dom_).find('.error').text(error).show();
});
- // Reset input value if cleared
listen('value', (value) => {
- if (value === undefined) input.val('');
+ // clear input
+ if ( value === undefined ) {
+ $(this.dom_).find('input').val('');
+ }
});
- // Input listener
+ const input = $(this.dom_).find('input');
input.on('input', () => {
- const value = input.val();
- this.set('value', value);
- this.updateStrength(value, strengthBar);
+ this.set('value', input.val());
});
- // Caps Lock detection
- input.on('keyup keydown', (e) => {
- const isCaps = e.getModifierState && e.getModifierState('CapsLock');
- capsWarning.toggle(isCaps);
- });
-
- // Submit on Enter
const on_submit = this.get('on_submit');
- if (on_submit) {
- input.on('keyup', (e) => {
- if (e.key === 'Enter') on_submit();
+ if ( on_submit ) {
+ $(this.dom_).find('input').on('keyup', (e) => {
+ if ( e.key === 'Enter' ) {
+ on_submit();
+ }
});
}
-
- // Toggle password visibility
- $(this.dom_).find('#toggle-show-password').on('click', () => {
+
+ $(this.dom_).find("#toggle-show-password").on("click", () => {
this.set('show_password', !this.get('show_password'));
const show_password = this.get('show_password');
-
- input.attr("type", show_password ? "text" : "password");
-
- const icon = show_password
- ? window.icons["eye-closed.svg"]
- : window.icons["eye-open.svg"];
- $(this.dom_).find("#toggle-show-password img").attr("src", icon);
+ // hide/show password and update icon
+ $(this.dom_).find("input").attr("type", show_password ? "text" : "password");
+ $(this.dom_).find("#toggle-show-password").attr("src", show_password ? window.icons["eye-closed.svg"] : window.icons["eye-open.svg"])
});
}
-
- updateStrength(value, bar) {
- let strength = 0;
- if (value.length > 5) strength++;
- if (/[A-Z]/.test(value)) strength++;
- if (/[0-9]/.test(value)) strength++;
- if (/[^A-Za-z0-9]/.test(value)) strength++;
-
- let width = "0%";
- let cls = "";
-
- if (strength === 1) { width = "33%"; cls = "strength-weak"; }
- if (strength === 2) { width = "66%"; cls = "strength-medium"; }
- if (strength >= 3) { width = "100%"; cls = "strength-strong"; }
-
- bar.removeClass("strength-weak strength-medium strength-strong")
- .addClass(cls)
- .css("width", width);
- }
});