Skip to content
Snippets Groups Projects
Verified Commit 1b9ca404 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

feat: new input-group and password field #265

parent 4ec80042
Branches
Tags
No related merge requests found
Showing
with 715 additions and 8 deletions
...@@ -2,7 +2,7 @@ export const projectRoot = "/home/vs/workspaces/oss/monster/monster"; ...@@ -2,7 +2,7 @@ export const projectRoot = "/home/vs/workspaces/oss/monster/monster";
export const sourcePath = "/home/vs/workspaces/oss/monster/monster/source"; export const sourcePath = "/home/vs/workspaces/oss/monster/monster/source";
export const developmentPath = "/home/vs/workspaces/oss/monster/monster/development"; export const developmentPath = "/home/vs/workspaces/oss/monster/monster/development";
export const pnpxBin = "/nix/store/2viji2z5i8ifq0ymhir2z8yyk1g29ddz-pnpm-8.15.5/bin/pnpx"; export const pnpxBin = "/nix/store/2viji2z5i8ifq0ymhir2z8yyk1g29ddz-pnpm-8.15.5/bin/pnpx";
export const nodeBin = "/nix/store/if6aqyl3sl0hz14a12mndj35swb1mcwi-nodejs-20.17.0/bin/node"; export const nodeBin = "/nix/store/xziigv8xwwr10plxrh8plr5wm0cipf8r-nodejs-22.10.0/bin/node";
export const license = "/**" + "\n" + export const license = "/**" + "\n" +
" * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved." + "\n" + " * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved." + "\n" +
" * Node module: @schukai/monster" + "\n" + " * Node module: @schukai/monster" + "\n" +
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>optimize tree-menu #265</title>
<script src="265.mjs" type="module"></script>
</head>
<body>
<h1>password field #265</h1>
<p></p>
<ul>
<li class="monster-theme-primary-1"><a
href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/265">Issue #265</a></li>
<li><a href="/">Back to overview</a></li>
</ul>
<main>
<div>
<monster-input-group>
<svg viewBox="0 0 16 16">
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2m3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2M5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1"/>
</svg>
<input type="text" placeholder="placeholder">
<svg viewBox="0 0 16 16">
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2m3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2M5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1"/>
</svg>
<monster-button slot="suffix">this is a button</monster-button>
</monster-input-group>
</div>
<!--monster-password></monster-password-->
</main>
</body>
</html>
/**
* @file development/issues/open/191.mjs
* @url https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/191
* @description optimize tree-menu
* @issue 265
*/
import "../../../source/components/style/property.pcss";
import "../../../source/components/style/color.pcss";
import "../../../source/components/style/link.pcss";
import "../../../source/components/style/normalize.pcss";
import "../../../source/components/style/form.pcss";
import "../../../source/components/style/typography.pcss";
import "../../../source/components/tree-menu/tree-menu.mjs";
import "../../../source/components/layout/split-panel.mjs";
import "../../../source/components/layout/panel.mjs";
import "../../../source/components/form/password.mjs";
import "../../../source/components/form/button.mjs";
import "../../../source/components/form/input-group.mjs";
setTimeout(() => {
// setTimeout(() => {
// //obj.selectEntry("/ebay")
// console.log(obj)
// obj.selectEntry("/alvine/?cmd=9201")
// }, 5000)
}, 1000)
...@@ -48,12 +48,11 @@ export const {{CLASSNAME_LOWER_FIRST}}ElementSymbol = Symbol("{{CLASSNAME_LOWER_ ...@@ -48,12 +48,11 @@ export const {{CLASSNAME_LOWER_FIRST}}ElementSymbol = Symbol("{{CLASSNAME_LOWER_
/** /**
* A {{CLASSNAME}} * A {{CLASSNAME}}
* *
* @fragments /fragments/components/{{NAMESPACE_AS_PATH}}/{{HTML_TAG_SUFFIX}}/ * @fragments /fragments/{{NAMESPACE_AS_PATH}}/{{HTML_TAG_SUFFIX}}/
* *
* @example /examples/components/{{NAMESPACE_AS_PATH}}/{{HTML_TAG_SUFFIX}}-simple * @example /examples/{{NAMESPACE_AS_PATH}}/{{HTML_TAG_SUFFIX}}-simple
* *
* @since {{VERSION}} * @since {{VERSION}}
* @since {{VERSION}}
* @copyright schukai GmbH * @copyright schukai GmbH
* @summary A beautiful {{CLASSNAME}} that can make your life easier and also looks good. * @summary A beautiful {{CLASSNAME}} that can make your life easier and also looks good.
*/ */
......
...@@ -52,6 +52,10 @@ ...@@ -52,6 +52,10 @@
(final: prev: { (final: prev: {
version = versionPck; version = versionPck;
}) })
(final: prev: {
projectNodeJS = prev.nodejs_22;
})
]; ];
}; };
in { in {
......
...@@ -27,8 +27,6 @@ ...@@ -27,8 +27,6 @@
in in
pkgs'.writeShellScriptBin "build" '' pkgs'.writeShellScriptBin "build" ''
set -e
source ${pkgs'.common}/bin/common source ${pkgs'.common}/bin/common
${bashFktScript} ${bashFktScript}
......
...@@ -24,7 +24,7 @@ in ...@@ -24,7 +24,7 @@ in
export COMMIT=${releaseInfo.commit} export COMMIT=${releaseInfo.commit}
export PNPX_BIN=${pkgs'.nodePackages.pnpm}/bin/pnpx export PNPX_BIN=${pkgs'.nodePackages.pnpm}/bin/pnpx
export NODE_BIN=${pkgs'.nodejs_20}/bin/node export NODE_BIN=${pkgs'.projectNodeJS}/bin/node
export LOCALHOST_CERTS_DIR=${pkgs'.alvineDevCerts} export LOCALHOST_CERTS_DIR=${pkgs'.alvineDevCerts}
cd development cd development
......
/**
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
* Node module: @schukai/monster
*
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
*
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
* Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
* For more information about purchasing a commercial license, please contact schukai GmbH.
*/
import { instanceSymbol } from "../../constants.mjs";
import { addAttributeToken } from "../../dom/attributes.mjs";
import {
ATTRIBUTE_ERRORMESSAGE,
ATTRIBUTE_ROLE,
} from "../../dom/constants.mjs";
import { CustomControl } from "../../dom/customcontrol.mjs";
import { CustomElement } from "../../dom/customelement.mjs";
import {
assembleMethodSymbol,
registerCustomElement,
} from "../../dom/customelement.mjs";
import { findTargetElementFromEvent } from "../../dom/events.mjs";
import { isFunction } from "../../types/is.mjs";
import { InputGroupStyleSheet } from "./stylesheet/input-group.mjs";
import { fireCustomEvent } from "../../dom/events.mjs";
export { InputGroup };
/**
* @private
* @type {symbol}
*/
export const inputGroupElementSymbol = Symbol("inputGroupElement");
/**
* A InputGroup
*
* @fragments /fragments/components/form/input-group/
*
* @example /examples/components/form/input-group-simple
*
* @since 3.89.0
* @copyright schukai GmbH
* @summary A beautiful InputGroup that can make your life easier and also looks good.
*/
class InputGroup extends CustomElement {
/**
* This method is called by the `instanceof` operator.
* @returns {symbol}
*/
static get [instanceSymbol]() {
return Symbol.for("@schukai/monster/components/form/input-group@@instance");
}
/**
* @return {Components.Form.InputGroup
*/
[assembleMethodSymbol]() {
super[assembleMethodSymbol]();
initControlReferences.call(this);
initEventHandler.call(this);
return this;
}
/**
* To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
*
* The individual configuration values can be found in the table.
*
* @property {Object} templates Template definitions
* @property {string} templates.main Main template
* @property {Object} labels Label definitions
* @property {Object} actions Callbacks
* @property {string} actions.click="throw Error" Callback when clicked
* @property {Object} features Features
* @property {Object} classes CSS classes
* @property {boolean} disabled=false Disabled state
*/
get defaults() {
return Object.assign({}, super.defaults, {
templates: {
main: getTemplate(),
},
labels: {},
classes: {},
disabled: false,
features: {},
actions: {
click: () => {
throw new Error("the click action is not defined");
},
},
});
}
/**
* @return {string}
*/
static getTag() {
return "monster-input-group";
}
/**
* @return {CSSStyleSheet[]}
*/
static getCSSStyleSheet() {
return [InputGroupStyleSheet];
}
}
/**
* @private
* @return {initEventHandler}
* @fires monster-input-group-clicked
*/
function initEventHandler() {
const self = this;
const element = this[inputGroupElementSymbol];
const type = "click";
element.addEventListener(type, function (event) {
const callback = self.getOption("actions.click");
fireCustomEvent(self, "monster-input-group-clicked", {
element: self,
});
if (!isFunction(callback)) {
return;
}
const element = findTargetElementFromEvent(
event,
ATTRIBUTE_ROLE,
"control",
);
if (!(element instanceof Node && self.hasNode(element))) {
return;
}
callback.call(self, event);
});
return this;
}
/**
* @private
* @return {void}
*/
function initControlReferences() {
this[inputGroupElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}="control"]`,
);
}
/**
* @private
* @return {string}
*/
function getTemplate() {
// language=HTML
return `
<div data-monster-role="control" part="control">
<slot name="prefix"></slot>
<slot></slot>
<slot name="suffix"></slot>
</div>`;
}
registerCustomElement(InputGroup);
/**
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
* Node module: @schukai/monster
*
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
*
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
* Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
* For more information about purchasing a commercial license, please contact schukai GmbH.
*/
import { instanceSymbol } from "../../constants.mjs";
import { addAttributeToken } from "../../dom/attributes.mjs";
import {
ATTRIBUTE_ERRORMESSAGE,
ATTRIBUTE_ROLE,
} from "../../dom/constants.mjs";
import { CustomControl } from "../../dom/customcontrol.mjs";
import { CustomElement } from "../../dom/customelement.mjs";
import {
assembleMethodSymbol,
registerCustomElement,
} from "../../dom/customelement.mjs";
import { findTargetElementFromEvent } from "../../dom/events.mjs";
import { isFunction } from "../../types/is.mjs";
import { PasswordStyleSheet } from "./stylesheet/password.mjs";
import { fireCustomEvent } from "../../dom/events.mjs";
export { Password };
/**
* @private
* @type {symbol}
*/
export const passwordElementSymbol = Symbol("passwordElement");
/**
* A password field
*
* @fragments /fragments/components/components/form/password/
*
* @example /examples/components/components/form/password-simple
*
* @since 3.89.0
* @copyright schukai GmbH
* @summary A beautiful Password field that can make your life easier and also looks good.
*/
class Password extends CustomElement {
/**
* This method is called by the `instanceof` operator.
* @returns {symbol}
*/
static get [instanceSymbol]() {
return Symbol.for("@schukai/monster/components/form/password@@instance");
}
/**
*
* @return {Components.Form.Password
*/
[assembleMethodSymbol]() {
super[assembleMethodSymbol]();
initControlReferences.call(this);
initEventHandler.call(this);
return this;
}
/**
* To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
*
* The individual configuration values can be found in the table.
*
* @property {Object} templates Template definitions
* @property {string} templates.main Main template
* @property {Object} labels Label definitions
* @property {Object} actions Callbacks
* @property {string} actions.click="throw Error" Callback when clicked
* @property {Object} features Features
* @property {Object} classes CSS classes
* @property {boolean} disabled=false Disabled state
*/
get defaults() {
return Object.assign({}, super.defaults, {
templates: {
main: getTemplate(),
},
labels: {},
classes: {},
disabled: false,
features: {},
actions: {
click: () => {
throw new Error("the click action is not defined");
},
},
});
}
/**
* @return {string}
*/
static getTag() {
return "monster-password";
}
/**
* @return {CSSStyleSheet[]}
*/
static getCSSStyleSheet() {
return [PasswordStyleSheet];
}
}
/**
* @private
* @return {initEventHandler}
* @fires monster-password-clicked
*/
function initEventHandler() {
const self = this;
const element = this[passwordElementSymbol];
const type = "click";
element.addEventListener(type, function (event) {
const callback = self.getOption("actions.click");
fireCustomEvent(self, "monster-password-clicked", {
element: self,
});
if (!isFunction(callback)) {
return;
}
const element = findTargetElementFromEvent(
event,
ATTRIBUTE_ROLE,
"control",
);
if (!(element instanceof Node && self.hasNode(element))) {
return;
}
callback.call(self, event);
});
return this;
}
/**
* @private
* @return {void}
*/
function initControlReferences() {
this[passwordElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}="control"]`,
);
}
/**
* @private
* @return {string}
*/
function getTemplate() {
// language=HTML
return `
<div data-monster-role="control" part="control">
<!--svg class="icon-password">
<use xlink:href="#icon-password"></use>
</svg //-->
<input data-monster-attributes="
type path:type,
placeholder path:placeholder,
required path:required,
autocomplete path:autocomplete,
inputmode path:inputmode,
aria-required path:aria-required,
aria-placeholder path:aria-placeholder"
>
<div class="svg-wrapper">
<svg class="icon-eye">
<use xlink:href="#icon-password-hidden"></use>
</svg>
<svg class="icon-eye">
<use xlink:href="#icon-password-visible"></use>
</svg>
</div>
</div>
<svg class="hidden">
<symbol id="icon-password" viewBox="0 0 16 16">
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2m3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2M5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1"/>
</symbol>
<symbol id="icon-password-visible" viewBox="0 0 16 16">
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8M1.173 8a13 13 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5s3.879 1.168 5.168 2.457A13 13 0 0 1 14.828 8q-.086.13-.195.288c-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5s-3.879-1.168-5.168-2.457A13 13 0 0 1 1.172 8z"/>
<path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5M4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0"/>
</symbol>
<symbol id="icon-password-hidden" viewBox="0 0 16 16">
<path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7 7 0 0 0-2.79.588l.77.771A6 6 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13 13 0 0 1 14.828 8q-.086.13-.195.288c-.335.48-.83 1.12-1.465 1.755q-.247.248-.517.486z"/>
<path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829"/>
<path d="M3.35 5.47q-.27.24-.518.487A13 13 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7 7 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12 .708-.708 12 12z"/>
</symbol>
</svg>
`;
}
registerCustomElement(Password);
@import "../../style/display.pcss";
@import "../../style/border.pcss";
@import "../../style/form.pcss";
@import "../../style/typography.pcss";
@import "../../style/control.pcss";
:host {
border-width: var(--monster-theme-control-border-width);
border-radius: var(--monster-theme-control-border-radius);
border-style: var(--monster-theme-control-border-style);
border-color: var(--monster-theme-control-border-color);
}
[data-monster-role="control"] {
display: flex;
align-items: stretch;
flex-wrap: nowrap;
position: relative;
box-sizing: border-box;
}
[data-monster-role="control"] {
position: relative;
::slotted(*) {
height: auto;
border: none;
--monster-border-width: 0;
}
::slotted(svg) {
width: 1.1rem;
padding: 0 0.5rem 0 0.5rem;
}
::slotted(input) {
position: relative;
flex: 1 1 auto;
width: 1%;
min-width: 0;
display: block;
appearance: none;
border: none !important;
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
}
}
@import "../../style/display.pcss";
@import "../../style/control.pcss";
@import "../../style/border.pcss";
@import "../../style/typography.pcss";
svg {
width: auto; /* Reset width */
height: auto; /* Reset height */
display: block; /* Avoid inline rendering issues */
}
[data-monster-role="control"] {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: nowrap;
position: relative;
}
.svg-wrapper {
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
right: 2.6em;
height: 100%;
}
.icon-eye {
width: 2.3em;
height: 100%;
cursor: pointer;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
input {
width: 100%;
height: 4rem;
}
/*
link-row {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
margin: 2rem 0 1.5rem 0;
& a {
font-size: 0.8rem;
}
}
input::placeholder {
opacity: 0;
}
input:not(:placeholder-shown) ~ span, input:focus ~ span {
top: -1rem;
font-size: 0.7rem;
opacity: 0.5;
}
label > .icon {
width: 2.3rem;
height: 1.5rem;
}
label > .icon.prefix {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
!*color: var(--monster-color-grey-5);*!
}
label > .icon.suffix {
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
!* color: var(--monster-color-grey-5);*!
cursor: pointer;
}
label > input {
padding-left: 2.5rem;
padding-right: 2.5rem;
}
.icon {
display: inline-block;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
*/
This diff is collapsed.
This diff is collapsed.
...@@ -29,6 +29,7 @@ export * from "./components/layout/details.mjs"; ...@@ -29,6 +29,7 @@ export * from "./components/layout/details.mjs";
export * from "./components/layout/slider.mjs"; export * from "./components/layout/slider.mjs";
export * from "./components/content/copy.mjs"; export * from "./components/content/copy.mjs";
export * from "./components/form/message-state-button.mjs"; export * from "./components/form/message-state-button.mjs";
export * from "./components/form/password.mjs";
export * from "./components/form/button-bar.mjs"; export * from "./components/form/button-bar.mjs";
export * from "./components/form/reload.mjs"; export * from "./components/form/reload.mjs";
export * from "./components/form/util/popper.mjs"; export * from "./components/form/util/popper.mjs";
...@@ -46,6 +47,7 @@ export * from "./components/form/form.mjs"; ...@@ -46,6 +47,7 @@ export * from "./components/form/form.mjs";
export * from "./components/form/api-button.mjs"; export * from "./components/form/api-button.mjs";
export * from "./components/form/tree-select.mjs"; export * from "./components/form/tree-select.mjs";
export * from "./components/form/popper-button.mjs"; export * from "./components/form/popper-button.mjs";
export * from "./components/form/input-group.mjs";
export * from "./components/form/shadow-reload.mjs"; export * from "./components/form/shadow-reload.mjs";
export * from "./components/form/button.mjs"; export * from "./components/form/button.mjs";
export * from "./components/form/field-set.mjs"; export * from "./components/form/field-set.mjs";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment