;
diff --git a/lerna.json b/lerna.json
index e5e6310c19..002a59debf 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,12 +1,9 @@
{
"packages": [
- "packages/adapters/angular/v11",
- "packages/adapters/angular/v12",
- "packages/adapters/angular/v13",
- "packages/adapters/angular/v14",
"packages/adapters/angular/v15",
"packages/adapters/angular/v16",
"packages/adapters/angular/v17",
+ "packages/adapters/angular/v18",
"packages/adapters/hydrate",
"packages/adapters/preact",
"packages/adapters/react",
@@ -14,18 +11,15 @@
"packages/adapters/solid",
"packages/adapters/vue",
"packages/components",
- "packages/create-kolibri",
"packages/designer",
"packages/samples/react",
"packages/schema",
"packages/themes",
- "packages/themes/bmf",
"packages/themes/default",
"packages/themes/ecl",
- "packages/themes/itzbund",
"packages/tools/kolibri-cli",
"packages/tools/visual-tests"
],
"useNx": true,
- "version": "2.0.14"
+ "version": "3.0.0-rc.2"
}
diff --git a/package.json b/package.json
index 8de3de4b7e..c3473f77aa 100644
--- a/package.json
+++ b/package.json
@@ -1,41 +1,45 @@
{
- "name": "root",
+ "devDependencies": {
+ "@commitlint/cli": "19.6.1",
+ "@commitlint/config-conventional": "19.6.0",
+ "cross-env": "7.0.3",
+ "husky": "9.1.7",
+ "js-yaml": "4.1.0",
+ "lerna": "8.1.9",
+ "license-report": "6.7.1",
+ "lint-staged": "15.4.3",
+ "npm-check-updates": "17.1.14",
+ "npm-run-all": "4.1.5",
+ "prettier": "3.4.2",
+ "rimraf": "6.0.1",
+ "ts-node": "10.9.2",
+ "ts-prune": "0.10.3",
+ "typescript": "5.7.3"
+ },
+ "engines": {
+ "pnpm": "^9"
+ },
"private": true,
"scripts": {
+ "build": "pnpm -r build",
"clean": "git clean -f -d -X",
"clean:branches": "git branch --merged | grep -v \\* | xargs git branch -D",
"clean:pnpm": "pnpm -r exec rimraf pnpm-lock.yaml && rimraf pnpm-lock.yaml && pnpm clean",
"format": "pnpm -r format",
"lint": "pnpm -r lint",
+ "lint-staged": "lint-staged",
"unused": "pnpm -r unused",
"ts-prune": "git clean -f -d -X packages/adapters/**/src && pnpm -r exec npx ts-prune src -e",
"ncu:major": "ncu && pnpm -r exec ncu",
- "ncu:minor": "ncu -t minor -u && pnpm -r exec ncu -t minor -u",
- "ncu:patch": "ncu -t patch -u && pnpm -r exec ncu -t patch -u",
+ "ncu:minor": "ncu -t minor -u && pnpm -r exec ncu -t minor -u -x @types/react,@stencil/core,@unocss/*",
+ "ncu:patch": "ncu -t patch -u && pnpm -r exec ncu -t patch -u -x @types/react",
"pack": "pnpm -r exec pnpm pack",
- "prepare": "pnpm exec playwright install && husky && echo \"Don't forget to build all packages once: pnpm -r build\"",
+ "prepare": "husky",
"reinstall": "pnpm clean:pnpm && pnpm i",
"test": "pnpm -r test",
"test-reset-and-update": "rimraf packages/themes/**/snapshots/** && pnpm test-update",
"test-update": "pnpm -r test-update",
- "update": "pnpm ncu:patch && pnpm ncu:minor && pnpm ncu:major"
- },
- "devDependencies": {
- "@commitlint/cli": "19.2.1",
- "@commitlint/config-conventional": "19.1.0",
- "@types/node": "ts5.4",
- "cross-env": "7.0.3",
- "husky": "9.0.11",
- "lerna": "8.1.2",
- "license-report": "6.5.0",
- "lint-staged": "15.2.2",
- "npm-check-updates": "16.14.18",
- "npm-run-all": "4.1.5",
- "pnpm": "8.15.6",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
- "ts-node": "10.9.2",
- "ts-prune": "0.10.3",
- "typescript": "5.4.5"
+ "update": "pnpm ncu:patch && pnpm ncu:minor && pnpm ncu:major",
+ "version": "node scripts/update-publiccode.mjs && git add publiccode.yml"
}
}
diff --git a/packages/adapters/angular/v11/README.md b/packages/adapters/angular/v11/README.md
deleted file mode 100644
index ad61a2c751..0000000000
--- a/packages/adapters/angular/v11/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Angular-Adapter
-
-Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
-
-Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
-
-Mehr zum **Projekt** kann in der [README](https://public-ui.github.io/docs) nachgelesen werden.
-
-## Referenzen
-
--
diff --git a/packages/adapters/angular/v11/ng-module.js b/packages/adapters/angular/v11/ng-module.js
deleted file mode 100644
index a2030c5dc8..0000000000
--- a/packages/adapters/angular/v11/ng-module.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const fs = require('fs');
-
-const componentFileContents = fs.readFileSync('./src/components.ts', 'utf-8');
-const componentList = [...componentFileContents.matchAll(/export class ([^ ]+)/g)].map((group) => group[1]);
-const componentListStr = componentList.join(', ');
-
-fs.writeFileSync(
- './src/index.ts',
- `
-/* AutoGen NgModule */
-
-import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
-import { ${componentListStr} } from './components';
-import { ReplaceTagDirective } from './angular-component-lib/ReplaceTagDirective';
-export { setTagNameTransformer } from './angular-component-lib/tagNameTransformer';
-
-
-@NgModule({
- declarations: [ReplaceTagDirective, ${componentListStr}],
- exports: [${componentListStr}],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
-})
-export class KoliBriModule {}
-export { ${componentListStr} }
-`,
- 'utf-8',
-);
diff --git a/packages/adapters/angular/v11/package.json b/packages/adapters/angular/v11/package.json
deleted file mode 100644
index 4b8f889494..0000000000
--- a/packages/adapters/angular/v11/package.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "name": "@public-ui/angular-v11",
- "version": "2.0.14",
- "license": "EUPL-1.2",
- "homepage": "https://public-ui.github.io",
- "repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
- "bugs": {
- "url": "https://github.com/public-ui/kolibri/issues",
- "email": "kolibri@itzbund.de"
- },
- "author": {
- "name": "Informationstechnikzentrum Bund",
- "email": "kolibri@itzbund.de"
- },
- "sideEffects": false,
- "description": "Angular (v11) framework adapter for KoliBri - The accessible HTML-Standard.",
- "keywords": [
- "accessibility",
- "accessible",
- "bitv",
- "framework",
- "library",
- "designsystem",
- "design",
- "system",
- "web components",
- "webcomponents",
- "aria",
- "wai",
- "axe",
- "custom elements",
- "styleguide",
- "style",
- "guide",
- "ui",
- "html",
- "css",
- "web",
- "a11y",
- "w3c",
- "webstandard",
- "wcag",
- "angular"
- ],
- "scripts": {
- "clean": "lerna exec --stream -- git clean -f -d -X && git clean -f -d -X",
- "build:cjs": "tsc -m commonjs --outDir cjs",
- "build:clean": "rimraf cjs esm types umd",
- "build:esm": "tsc -m esnext --outDir esm",
- "build:ngc": "node ng-module.js && ngc -p .",
- "build:tsc": "tsc -p .",
- "build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
- "build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
- },
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- "types": "./dist/index.d.ts",
- "require": "./dist/index.js",
- "import": "./dist/index.js"
- },
- "devDependencies": {
- "@angular/common": "11.2.14",
- "@angular/compiler": "11.2.14",
- "@angular/compiler-cli": "11.2.14",
- "@angular/core": "11.2.14",
- "@public-ui/components": "2.0.14",
- "@types/minimatch": "5.1.2",
- "@types/minimist": "1.2.5",
- "@types/node": "ts4.1",
- "@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
- "rxjs": "6.6.7",
- "tslib": "2.6.2",
- "typescript": "4.1.6",
- "zone.js": "0.11.8"
- },
- "peerDependencies": {
- "@angular/core": "11.2.14",
- "@public-ui/components": "2.0.14"
- },
- "files": [
- "dist"
- ]
-}
diff --git a/packages/adapters/angular/v12/LICENSE b/packages/adapters/angular/v12/LICENSE
deleted file mode 100644
index 4153cd3775..0000000000
--- a/packages/adapters/angular/v12/LICENSE
+++ /dev/null
@@ -1,287 +0,0 @@
- EUROPEAN UNION PUBLIC LICENCE v. 1.2
- EUPL © the European Union 2007, 2016
-
-This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
-below) which is provided under the terms of this Licence. Any use of the Work,
-other than as authorised under this Licence is prohibited (to the extent such
-use is covered by a right of the copyright holder of the Work).
-
-The Work is provided under the terms of this Licence when the Licensor (as
-defined below) has placed the following notice immediately following the
-copyright notice for the Work:
-
- Licensed under the EUPL
-
-or has expressed by any other means his willingness to license under the EUPL.
-
-1. Definitions
-
-In this Licence, the following terms have the following meaning:
-
-- ‘The Licence’: this Licence.
-
-- ‘The Original Work’: the work or software distributed or communicated by the
- Licensor under this Licence, available as Source Code and also as Executable
- Code as the case may be.
-
-- ‘Derivative Works’: the works or software that could be created by the
- Licensee, based upon the Original Work or modifications thereof. This Licence
- does not define the extent of modification or dependence on the Original Work
- required in order to classify a work as a Derivative Work; this extent is
- determined by copyright law applicable in the country mentioned in Article 15.
-
-- ‘The Work’: the Original Work or its Derivative Works.
-
-- ‘The Source Code’: the human-readable form of the Work which is the most
- convenient for people to study and modify.
-
-- ‘The Executable Code’: any code which has generally been compiled and which is
- meant to be interpreted by a computer as a program.
-
-- ‘The Licensor’: the natural or legal person that distributes or communicates
- the Work under the Licence.
-
-- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
- Licence, or otherwise contributes to the creation of a Derivative Work.
-
-- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
- the Work under the terms of the Licence.
-
-- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
- renting, distributing, communicating, transmitting, or otherwise making
- available, online or offline, copies of the Work or providing access to its
- essential functionalities at the disposal of any other natural or legal
- person.
-
-2. Scope of the rights granted by the Licence
-
-The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
-sublicensable licence to do the following, for the duration of copyright vested
-in the Original Work:
-
-- use the Work in any circumstance and for all usage,
-- reproduce the Work,
-- modify the Work, and make Derivative Works based upon the Work,
-- communicate to the public, including the right to make available or display
- the Work or copies thereof to the public and perform publicly, as the case may
- be, the Work,
-- distribute the Work or copies thereof,
-- lend and rent the Work or copies thereof,
-- sublicense rights in the Work or copies thereof.
-
-Those rights can be exercised on any media, supports and formats, whether now
-known or later invented, as far as the applicable law permits so.
-
-In the countries where moral rights apply, the Licensor waives his right to
-exercise his moral right to the extent allowed by law in order to make effective
-the licence of the economic rights here above listed.
-
-The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
-any patents held by the Licensor, to the extent necessary to make use of the
-rights granted on the Work under this Licence.
-
-3. Communication of the Source Code
-
-The Licensor may provide the Work either in its Source Code form, or as
-Executable Code. If the Work is provided as Executable Code, the Licensor
-provides in addition a machine-readable copy of the Source Code of the Work
-along with each copy of the Work that the Licensor distributes or indicates, in
-a notice following the copyright notice attached to the Work, a repository where
-the Source Code is easily and freely accessible for as long as the Licensor
-continues to distribute or communicate the Work.
-
-4. Limitations on copyright
-
-Nothing in this Licence is intended to deprive the Licensee of the benefits from
-any exception or limitation to the exclusive rights of the rights owners in the
-Work, of the exhaustion of those rights or of other applicable limitations
-thereto.
-
-5. Obligations of the Licensee
-
-The grant of the rights mentioned above is subject to some restrictions and
-obligations imposed on the Licensee. Those obligations are the following:
-
-Attribution right: The Licensee shall keep intact all copyright, patent or
-trademarks notices and all notices that refer to the Licence and to the
-disclaimer of warranties. The Licensee must include a copy of such notices and a
-copy of the Licence with every copy of the Work he/she distributes or
-communicates. The Licensee must cause any Derivative Work to carry prominent
-notices stating that the Work has been modified and the date of modification.
-
-Copyleft clause: If the Licensee distributes or communicates copies of the
-Original Works or Derivative Works, this Distribution or Communication will be
-done under the terms of this Licence or of a later version of this Licence
-unless the Original Work is expressly distributed only under this version of the
-Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
-(becoming Licensor) cannot offer or impose any additional terms or conditions on
-the Work or Derivative Work that alter or restrict the terms of the Licence.
-
-Compatibility clause: If the Licensee Distributes or Communicates Derivative
-Works or copies thereof based upon both the Work and another work licensed under
-a Compatible Licence, this Distribution or Communication can be done under the
-terms of this Compatible Licence. For the sake of this clause, ‘Compatible
-Licence’ refers to the licences listed in the appendix attached to this Licence.
-Should the Licensee's obligations under the Compatible Licence conflict with
-his/her obligations under this Licence, the obligations of the Compatible
-Licence shall prevail.
-
-Provision of Source Code: When distributing or communicating copies of the Work,
-the Licensee will provide a machine-readable copy of the Source Code or indicate
-a repository where this Source will be easily and freely available for as long
-as the Licensee continues to distribute or communicate the Work.
-
-Legal Protection: This Licence does not grant permission to use the trade names,
-trademarks, service marks, or 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 copyright notice.
-
-6. Chain of Authorship
-
-The original Licensor warrants that the copyright in the Original Work granted
-hereunder is owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each Contributor warrants that the copyright in the modifications he/she brings
-to the Work are owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each time You accept the Licence, the original Licensor and subsequent
-Contributors grant You a licence to their contributions to the Work, under the
-terms of this Licence.
-
-7. Disclaimer of Warranty
-
-The Work is a work in progress, which is continuously improved by numerous
-Contributors. It is not a finished work and may therefore contain defects or
-‘bugs’ inherent to this type of development.
-
-For the above reason, the Work is provided under the Licence on an ‘as is’ basis
-and without warranties of any kind concerning the Work, including without
-limitation merchantability, fitness for a particular purpose, absence of defects
-or errors, accuracy, non-infringement of intellectual property rights other than
-copyright as stated in Article 6 of this Licence.
-
-This disclaimer of warranty is an essential part of the Licence and a condition
-for the grant of any rights to the Work.
-
-8. Disclaimer of Liability
-
-Except in the cases of wilful misconduct or damages directly caused to natural
-persons, the Licensor will in no event be liable for any direct or indirect,
-material or moral, damages of any kind, arising out of the Licence or of the use
-of the Work, including without limitation, damages for loss of goodwill, work
-stoppage, computer failure or malfunction, loss of data or any commercial
-damage, even if the Licensor has been advised of the possibility of such damage.
-However, the Licensor will be liable under statutory product liability laws as
-far such laws apply to the Work.
-
-9. Additional agreements
-
-While distributing the Work, You may choose to conclude an additional agreement,
-defining obligations or services consistent with this Licence. However, if
-accepting obligations, You may act only on your own behalf and on your sole
-responsibility, not on behalf of the original Licensor or 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
-the fact You have accepted any warranty or additional liability.
-
-10. Acceptance of the Licence
-
-The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
-placed under the bottom of a window displaying the text of this Licence or by
-affirming consent in any other similar way, in accordance with the rules of
-applicable law. Clicking on that icon indicates your clear and irrevocable
-acceptance of this Licence and all of its terms and conditions.
-
-Similarly, you irrevocably accept this Licence and all of its terms and
-conditions by exercising any rights granted to You by Article 2 of this Licence,
-such as the use of the Work, the creation by You of a Derivative Work or the
-Distribution or Communication by You of the Work or copies thereof.
-
-11. Information to the public
-
-In case of any Distribution or Communication of the Work by means of electronic
-communication by You (for example, by offering to download the Work from a
-remote location) the distribution channel or media (for example, a website) must
-at least provide to the public the information requested by the applicable law
-regarding the Licensor, the Licence and the way it may be accessible, concluded,
-stored and reproduced by the Licensee.
-
-12. Termination of the Licence
-
-The Licence and the rights granted hereunder will terminate automatically upon
-any breach by the Licensee of the terms of the Licence.
-
-Such a termination will not terminate the licences of any person who has
-received the Work from the Licensee under the Licence, provided such persons
-remain in full compliance with the Licence.
-
-13. Miscellaneous
-
-Without prejudice of Article 9 above, the Licence represents the complete
-agreement between the Parties as to the Work.
-
-If any provision of the Licence is invalid or unenforceable under applicable
-law, this will not affect the validity or enforceability of the Licence as a
-whole. Such provision will be construed or reformed so as necessary to make it
-valid and enforceable.
-
-The European Commission may publish other linguistic versions or new versions of
-this Licence or updated versions of the Appendix, so far this is required and
-reasonable, without reducing the scope of the rights granted by the Licence. New
-versions of the Licence will be published with a unique version number.
-
-All linguistic versions of this Licence, approved by the European Commission,
-have identical value. Parties can take advantage of the linguistic version of
-their choice.
-
-14. Jurisdiction
-
-Without prejudice to specific agreement between parties,
-
-- any litigation resulting from the interpretation of this License, arising
- between the European Union institutions, bodies, offices or agencies, as a
- Licensor, and any Licensee, will be subject to the jurisdiction of the Court
- of Justice of the European Union, as laid down in article 272 of the Treaty on
- the Functioning of the European Union,
-
-- any litigation arising between other parties and resulting from the
- interpretation of this License, will be subject to the exclusive jurisdiction
- of the competent court where the Licensor resides or conducts its primary
- business.
-
-15. Applicable Law
-
-Without prejudice to specific agreement between parties,
-
-- this Licence shall be governed by the law of the European Union Member State
- where the Licensor has his seat, resides or has his registered office,
-
-- this licence shall be governed by Belgian law if the Licensor has no seat,
- residence or registered office inside a European Union Member State.
-
-Appendix
-
-‘Compatible Licences’ according to Article 5 EUPL are:
-
-- GNU General Public License (GPL) v. 2, v. 3
-- GNU Affero General Public License (AGPL) v. 3
-- Open Software License (OSL) v. 2.1, v. 3.0
-- Eclipse Public License (EPL) v. 1.0
-- CeCILL v. 2.0, v. 2.1
-- Mozilla Public Licence (MPL) v. 2
-- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
-- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
- works other than software
-- European Union Public Licence (EUPL) v. 1.1, v. 1.2
-- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
- Reciprocity (LiLiQ-R+).
-
-The European Commission may update this Appendix to later versions of the above
-licences without producing a new version of the EUPL, as long as they provide
-the rights granted in Article 2 of this Licence and protect the covered Source
-Code from exclusive appropriation.
-
-All other changes or additions to this Appendix require the production of a new
-EUPL version.
diff --git a/packages/adapters/angular/v12/README.md b/packages/adapters/angular/v12/README.md
deleted file mode 100644
index ad61a2c751..0000000000
--- a/packages/adapters/angular/v12/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Angular-Adapter
-
-Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
-
-Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
-
-Mehr zum **Projekt** kann in der [README](https://public-ui.github.io/docs) nachgelesen werden.
-
-## Referenzen
-
--
diff --git a/packages/adapters/angular/v12/ng-module.js b/packages/adapters/angular/v12/ng-module.js
deleted file mode 100644
index a2030c5dc8..0000000000
--- a/packages/adapters/angular/v12/ng-module.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const fs = require('fs');
-
-const componentFileContents = fs.readFileSync('./src/components.ts', 'utf-8');
-const componentList = [...componentFileContents.matchAll(/export class ([^ ]+)/g)].map((group) => group[1]);
-const componentListStr = componentList.join(', ');
-
-fs.writeFileSync(
- './src/index.ts',
- `
-/* AutoGen NgModule */
-
-import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
-import { ${componentListStr} } from './components';
-import { ReplaceTagDirective } from './angular-component-lib/ReplaceTagDirective';
-export { setTagNameTransformer } from './angular-component-lib/tagNameTransformer';
-
-
-@NgModule({
- declarations: [ReplaceTagDirective, ${componentListStr}],
- exports: [${componentListStr}],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
-})
-export class KoliBriModule {}
-export { ${componentListStr} }
-`,
- 'utf-8',
-);
diff --git a/packages/adapters/angular/v12/package.json b/packages/adapters/angular/v12/package.json
deleted file mode 100644
index 050700302b..0000000000
--- a/packages/adapters/angular/v12/package.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "name": "@public-ui/angular-v12",
- "version": "2.0.14",
- "license": "EUPL-1.2",
- "homepage": "https://public-ui.github.io",
- "repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
- "bugs": {
- "url": "https://github.com/public-ui/kolibri/issues",
- "email": "kolibri@itzbund.de"
- },
- "author": {
- "name": "Informationstechnikzentrum Bund",
- "email": "kolibri@itzbund.de"
- },
- "sideEffects": false,
- "description": "Angular (v12) framework adapter for KoliBri - The accessible HTML-Standard.",
- "keywords": [
- "accessibility",
- "accessible",
- "bitv",
- "framework",
- "library",
- "designsystem",
- "design",
- "system",
- "web components",
- "webcomponents",
- "aria",
- "wai",
- "axe",
- "custom elements",
- "styleguide",
- "style",
- "guide",
- "ui",
- "html",
- "css",
- "web",
- "a11y",
- "w3c",
- "webstandard",
- "wcag",
- "angular"
- ],
- "scripts": {
- "clean": "lerna exec --stream -- git clean -f -d -X && git clean -f -d -X",
- "build:cjs": "tsc -m commonjs --outDir cjs",
- "build:clean": "rimraf cjs esm types umd",
- "build:esm": "tsc -m esnext --outDir esm",
- "build:ngc": "node ng-module.js && ngc -p .",
- "build:tsc": "tsc -p .",
- "build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
- "build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
- },
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- "types": "./dist/index.d.ts",
- "require": "./dist/index.js",
- "import": "./dist/index.js"
- },
- "devDependencies": {
- "@angular/common": "12.2.17",
- "@angular/compiler": "12.2.17",
- "@angular/compiler-cli": "12.2.17",
- "@angular/core": "12.2.17",
- "@public-ui/components": "2.0.14",
- "@types/minimatch": "5.1.2",
- "@types/minimist": "1.2.5",
- "@types/node": "ts4.3",
- "@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
- "rxjs": "7.8.1",
- "tslib": "2.6.2",
- "typescript": "4.3",
- "zone.js": "0.11.8"
- },
- "peerDependencies": {
- "@angular/core": "12.2.17",
- "@public-ui/components": "2.0.14"
- },
- "files": [
- "dist"
- ]
-}
diff --git a/packages/adapters/angular/v12/tsconfig.json b/packages/adapters/angular/v12/tsconfig.json
deleted file mode 100644
index 0904853eb9..0000000000
--- a/packages/adapters/angular/v12/tsconfig.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "angularCompilerOptions": {
- "annotateForClosureCompiler": false,
- "strictMetadataEmit": true,
- "flatModuleOutFile": "core.js",
- "flatModuleId": "@public-ui/angular",
- "skipTemplateCodegen": true,
- "fullTemplateTypeCheck": false,
- "enableIvy": true
- },
- "compilerOptions": {
- "alwaysStrict": true,
- "strict": true,
- "allowSyntheticDefaultImports": true,
- "allowUnreachableCode": false,
- "declaration": true,
- "declarationDir": "dist",
- "experimentalDecorators": true,
- "forceConsistentCasingInFileNames": true,
- "lib": ["dom", "es2017"],
- "module": "ESNext",
- "moduleResolution": "node",
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noUnusedLocals": false,
- "noUnusedParameters": true,
- "outDir": "dist",
- "pretty": true,
- "removeComments": false,
- "importHelpers": true,
- "rootDir": "src",
- "strictPropertyInitialization": false,
- "target": "es2015",
- "skipLibCheck": true
- },
- "files": ["src/index.ts"],
- "exclude": ["node_modules"]
-}
diff --git a/packages/adapters/angular/v13/.gitignore b/packages/adapters/angular/v13/.gitignore
deleted file mode 100644
index 4f00cd9a73..0000000000
--- a/packages/adapters/angular/v13/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/src/
diff --git a/packages/adapters/angular/v13/LICENSE b/packages/adapters/angular/v13/LICENSE
deleted file mode 100644
index 4153cd3775..0000000000
--- a/packages/adapters/angular/v13/LICENSE
+++ /dev/null
@@ -1,287 +0,0 @@
- EUROPEAN UNION PUBLIC LICENCE v. 1.2
- EUPL © the European Union 2007, 2016
-
-This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
-below) which is provided under the terms of this Licence. Any use of the Work,
-other than as authorised under this Licence is prohibited (to the extent such
-use is covered by a right of the copyright holder of the Work).
-
-The Work is provided under the terms of this Licence when the Licensor (as
-defined below) has placed the following notice immediately following the
-copyright notice for the Work:
-
- Licensed under the EUPL
-
-or has expressed by any other means his willingness to license under the EUPL.
-
-1. Definitions
-
-In this Licence, the following terms have the following meaning:
-
-- ‘The Licence’: this Licence.
-
-- ‘The Original Work’: the work or software distributed or communicated by the
- Licensor under this Licence, available as Source Code and also as Executable
- Code as the case may be.
-
-- ‘Derivative Works’: the works or software that could be created by the
- Licensee, based upon the Original Work or modifications thereof. This Licence
- does not define the extent of modification or dependence on the Original Work
- required in order to classify a work as a Derivative Work; this extent is
- determined by copyright law applicable in the country mentioned in Article 15.
-
-- ‘The Work’: the Original Work or its Derivative Works.
-
-- ‘The Source Code’: the human-readable form of the Work which is the most
- convenient for people to study and modify.
-
-- ‘The Executable Code’: any code which has generally been compiled and which is
- meant to be interpreted by a computer as a program.
-
-- ‘The Licensor’: the natural or legal person that distributes or communicates
- the Work under the Licence.
-
-- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
- Licence, or otherwise contributes to the creation of a Derivative Work.
-
-- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
- the Work under the terms of the Licence.
-
-- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
- renting, distributing, communicating, transmitting, or otherwise making
- available, online or offline, copies of the Work or providing access to its
- essential functionalities at the disposal of any other natural or legal
- person.
-
-2. Scope of the rights granted by the Licence
-
-The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
-sublicensable licence to do the following, for the duration of copyright vested
-in the Original Work:
-
-- use the Work in any circumstance and for all usage,
-- reproduce the Work,
-- modify the Work, and make Derivative Works based upon the Work,
-- communicate to the public, including the right to make available or display
- the Work or copies thereof to the public and perform publicly, as the case may
- be, the Work,
-- distribute the Work or copies thereof,
-- lend and rent the Work or copies thereof,
-- sublicense rights in the Work or copies thereof.
-
-Those rights can be exercised on any media, supports and formats, whether now
-known or later invented, as far as the applicable law permits so.
-
-In the countries where moral rights apply, the Licensor waives his right to
-exercise his moral right to the extent allowed by law in order to make effective
-the licence of the economic rights here above listed.
-
-The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
-any patents held by the Licensor, to the extent necessary to make use of the
-rights granted on the Work under this Licence.
-
-3. Communication of the Source Code
-
-The Licensor may provide the Work either in its Source Code form, or as
-Executable Code. If the Work is provided as Executable Code, the Licensor
-provides in addition a machine-readable copy of the Source Code of the Work
-along with each copy of the Work that the Licensor distributes or indicates, in
-a notice following the copyright notice attached to the Work, a repository where
-the Source Code is easily and freely accessible for as long as the Licensor
-continues to distribute or communicate the Work.
-
-4. Limitations on copyright
-
-Nothing in this Licence is intended to deprive the Licensee of the benefits from
-any exception or limitation to the exclusive rights of the rights owners in the
-Work, of the exhaustion of those rights or of other applicable limitations
-thereto.
-
-5. Obligations of the Licensee
-
-The grant of the rights mentioned above is subject to some restrictions and
-obligations imposed on the Licensee. Those obligations are the following:
-
-Attribution right: The Licensee shall keep intact all copyright, patent or
-trademarks notices and all notices that refer to the Licence and to the
-disclaimer of warranties. The Licensee must include a copy of such notices and a
-copy of the Licence with every copy of the Work he/she distributes or
-communicates. The Licensee must cause any Derivative Work to carry prominent
-notices stating that the Work has been modified and the date of modification.
-
-Copyleft clause: If the Licensee distributes or communicates copies of the
-Original Works or Derivative Works, this Distribution or Communication will be
-done under the terms of this Licence or of a later version of this Licence
-unless the Original Work is expressly distributed only under this version of the
-Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
-(becoming Licensor) cannot offer or impose any additional terms or conditions on
-the Work or Derivative Work that alter or restrict the terms of the Licence.
-
-Compatibility clause: If the Licensee Distributes or Communicates Derivative
-Works or copies thereof based upon both the Work and another work licensed under
-a Compatible Licence, this Distribution or Communication can be done under the
-terms of this Compatible Licence. For the sake of this clause, ‘Compatible
-Licence’ refers to the licences listed in the appendix attached to this Licence.
-Should the Licensee's obligations under the Compatible Licence conflict with
-his/her obligations under this Licence, the obligations of the Compatible
-Licence shall prevail.
-
-Provision of Source Code: When distributing or communicating copies of the Work,
-the Licensee will provide a machine-readable copy of the Source Code or indicate
-a repository where this Source will be easily and freely available for as long
-as the Licensee continues to distribute or communicate the Work.
-
-Legal Protection: This Licence does not grant permission to use the trade names,
-trademarks, service marks, or 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 copyright notice.
-
-6. Chain of Authorship
-
-The original Licensor warrants that the copyright in the Original Work granted
-hereunder is owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each Contributor warrants that the copyright in the modifications he/she brings
-to the Work are owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each time You accept the Licence, the original Licensor and subsequent
-Contributors grant You a licence to their contributions to the Work, under the
-terms of this Licence.
-
-7. Disclaimer of Warranty
-
-The Work is a work in progress, which is continuously improved by numerous
-Contributors. It is not a finished work and may therefore contain defects or
-‘bugs’ inherent to this type of development.
-
-For the above reason, the Work is provided under the Licence on an ‘as is’ basis
-and without warranties of any kind concerning the Work, including without
-limitation merchantability, fitness for a particular purpose, absence of defects
-or errors, accuracy, non-infringement of intellectual property rights other than
-copyright as stated in Article 6 of this Licence.
-
-This disclaimer of warranty is an essential part of the Licence and a condition
-for the grant of any rights to the Work.
-
-8. Disclaimer of Liability
-
-Except in the cases of wilful misconduct or damages directly caused to natural
-persons, the Licensor will in no event be liable for any direct or indirect,
-material or moral, damages of any kind, arising out of the Licence or of the use
-of the Work, including without limitation, damages for loss of goodwill, work
-stoppage, computer failure or malfunction, loss of data or any commercial
-damage, even if the Licensor has been advised of the possibility of such damage.
-However, the Licensor will be liable under statutory product liability laws as
-far such laws apply to the Work.
-
-9. Additional agreements
-
-While distributing the Work, You may choose to conclude an additional agreement,
-defining obligations or services consistent with this Licence. However, if
-accepting obligations, You may act only on your own behalf and on your sole
-responsibility, not on behalf of the original Licensor or 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
-the fact You have accepted any warranty or additional liability.
-
-10. Acceptance of the Licence
-
-The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
-placed under the bottom of a window displaying the text of this Licence or by
-affirming consent in any other similar way, in accordance with the rules of
-applicable law. Clicking on that icon indicates your clear and irrevocable
-acceptance of this Licence and all of its terms and conditions.
-
-Similarly, you irrevocably accept this Licence and all of its terms and
-conditions by exercising any rights granted to You by Article 2 of this Licence,
-such as the use of the Work, the creation by You of a Derivative Work or the
-Distribution or Communication by You of the Work or copies thereof.
-
-11. Information to the public
-
-In case of any Distribution or Communication of the Work by means of electronic
-communication by You (for example, by offering to download the Work from a
-remote location) the distribution channel or media (for example, a website) must
-at least provide to the public the information requested by the applicable law
-regarding the Licensor, the Licence and the way it may be accessible, concluded,
-stored and reproduced by the Licensee.
-
-12. Termination of the Licence
-
-The Licence and the rights granted hereunder will terminate automatically upon
-any breach by the Licensee of the terms of the Licence.
-
-Such a termination will not terminate the licences of any person who has
-received the Work from the Licensee under the Licence, provided such persons
-remain in full compliance with the Licence.
-
-13. Miscellaneous
-
-Without prejudice of Article 9 above, the Licence represents the complete
-agreement between the Parties as to the Work.
-
-If any provision of the Licence is invalid or unenforceable under applicable
-law, this will not affect the validity or enforceability of the Licence as a
-whole. Such provision will be construed or reformed so as necessary to make it
-valid and enforceable.
-
-The European Commission may publish other linguistic versions or new versions of
-this Licence or updated versions of the Appendix, so far this is required and
-reasonable, without reducing the scope of the rights granted by the Licence. New
-versions of the Licence will be published with a unique version number.
-
-All linguistic versions of this Licence, approved by the European Commission,
-have identical value. Parties can take advantage of the linguistic version of
-their choice.
-
-14. Jurisdiction
-
-Without prejudice to specific agreement between parties,
-
-- any litigation resulting from the interpretation of this License, arising
- between the European Union institutions, bodies, offices or agencies, as a
- Licensor, and any Licensee, will be subject to the jurisdiction of the Court
- of Justice of the European Union, as laid down in article 272 of the Treaty on
- the Functioning of the European Union,
-
-- any litigation arising between other parties and resulting from the
- interpretation of this License, will be subject to the exclusive jurisdiction
- of the competent court where the Licensor resides or conducts its primary
- business.
-
-15. Applicable Law
-
-Without prejudice to specific agreement between parties,
-
-- this Licence shall be governed by the law of the European Union Member State
- where the Licensor has his seat, resides or has his registered office,
-
-- this licence shall be governed by Belgian law if the Licensor has no seat,
- residence or registered office inside a European Union Member State.
-
-Appendix
-
-‘Compatible Licences’ according to Article 5 EUPL are:
-
-- GNU General Public License (GPL) v. 2, v. 3
-- GNU Affero General Public License (AGPL) v. 3
-- Open Software License (OSL) v. 2.1, v. 3.0
-- Eclipse Public License (EPL) v. 1.0
-- CeCILL v. 2.0, v. 2.1
-- Mozilla Public Licence (MPL) v. 2
-- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
-- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
- works other than software
-- European Union Public Licence (EUPL) v. 1.1, v. 1.2
-- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
- Reciprocity (LiLiQ-R+).
-
-The European Commission may update this Appendix to later versions of the above
-licences without producing a new version of the EUPL, as long as they provide
-the rights granted in Article 2 of this Licence and protect the covered Source
-Code from exclusive appropriation.
-
-All other changes or additions to this Appendix require the production of a new
-EUPL version.
diff --git a/packages/adapters/angular/v13/README.md b/packages/adapters/angular/v13/README.md
deleted file mode 100644
index ad61a2c751..0000000000
--- a/packages/adapters/angular/v13/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Angular-Adapter
-
-Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
-
-Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
-
-Mehr zum **Projekt** kann in der [README](https://public-ui.github.io/docs) nachgelesen werden.
-
-## Referenzen
-
--
diff --git a/packages/adapters/angular/v13/package.json b/packages/adapters/angular/v13/package.json
deleted file mode 100644
index 1e6344feea..0000000000
--- a/packages/adapters/angular/v13/package.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "name": "@public-ui/angular-v13",
- "version": "2.0.14",
- "license": "EUPL-1.2",
- "homepage": "https://public-ui.github.io",
- "repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
- "bugs": {
- "url": "https://github.com/public-ui/kolibri/issues",
- "email": "kolibri@itzbund.de"
- },
- "author": {
- "name": "Informationstechnikzentrum Bund",
- "email": "kolibri@itzbund.de"
- },
- "sideEffects": false,
- "description": "Angular (v13) framework adapter for KoliBri - The accessible HTML-Standard.",
- "keywords": [
- "accessibility",
- "accessible",
- "bitv",
- "framework",
- "library",
- "designsystem",
- "design",
- "system",
- "web components",
- "webcomponents",
- "aria",
- "wai",
- "axe",
- "custom elements",
- "styleguide",
- "style",
- "guide",
- "ui",
- "html",
- "css",
- "web",
- "a11y",
- "w3c",
- "webstandard",
- "wcag",
- "angular"
- ],
- "scripts": {
- "clean": "lerna exec --stream -- git clean -f -d -X && git clean -f -d -X",
- "build:cjs": "tsc -m commonjs --outDir cjs",
- "build:clean": "rimraf cjs esm types umd",
- "build:esm": "tsc -m esnext --outDir esm",
- "build:ngc": "node ng-module.js && ngc -p .",
- "build:tsc": "tsc -p .",
- "build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
- "build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
- },
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- "types": "./dist/index.d.ts",
- "require": "./dist/index.js",
- "import": "./dist/index.js"
- },
- "devDependencies": {
- "@angular/common": "13.4.0",
- "@angular/compiler": "13.4.0",
- "@angular/compiler-cli": "13.4.0",
- "@angular/core": "13.4.0",
- "@public-ui/components": "2.0.14",
- "@types/minimatch": "5.1.2",
- "@types/minimist": "1.2.5",
- "@types/node": "ts4.6",
- "@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
- "rxjs": "7.8.1",
- "tslib": "2.6.2",
- "typescript": "4.6",
- "zone.js": "0.11.8"
- },
- "peerDependencies": {
- "@angular/core": "13.4.0",
- "@public-ui/components": "2.0.14"
- },
- "files": [
- "dist"
- ]
-}
diff --git a/packages/adapters/angular/v13/tsconfig.json b/packages/adapters/angular/v13/tsconfig.json
deleted file mode 100644
index 0904853eb9..0000000000
--- a/packages/adapters/angular/v13/tsconfig.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "angularCompilerOptions": {
- "annotateForClosureCompiler": false,
- "strictMetadataEmit": true,
- "flatModuleOutFile": "core.js",
- "flatModuleId": "@public-ui/angular",
- "skipTemplateCodegen": true,
- "fullTemplateTypeCheck": false,
- "enableIvy": true
- },
- "compilerOptions": {
- "alwaysStrict": true,
- "strict": true,
- "allowSyntheticDefaultImports": true,
- "allowUnreachableCode": false,
- "declaration": true,
- "declarationDir": "dist",
- "experimentalDecorators": true,
- "forceConsistentCasingInFileNames": true,
- "lib": ["dom", "es2017"],
- "module": "ESNext",
- "moduleResolution": "node",
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noUnusedLocals": false,
- "noUnusedParameters": true,
- "outDir": "dist",
- "pretty": true,
- "removeComments": false,
- "importHelpers": true,
- "rootDir": "src",
- "strictPropertyInitialization": false,
- "target": "es2015",
- "skipLibCheck": true
- },
- "files": ["src/index.ts"],
- "exclude": ["node_modules"]
-}
diff --git a/packages/adapters/angular/v14/.gitignore b/packages/adapters/angular/v14/.gitignore
deleted file mode 100644
index 4f00cd9a73..0000000000
--- a/packages/adapters/angular/v14/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/src/
diff --git a/packages/adapters/angular/v14/LICENSE b/packages/adapters/angular/v14/LICENSE
deleted file mode 100644
index 4153cd3775..0000000000
--- a/packages/adapters/angular/v14/LICENSE
+++ /dev/null
@@ -1,287 +0,0 @@
- EUROPEAN UNION PUBLIC LICENCE v. 1.2
- EUPL © the European Union 2007, 2016
-
-This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
-below) which is provided under the terms of this Licence. Any use of the Work,
-other than as authorised under this Licence is prohibited (to the extent such
-use is covered by a right of the copyright holder of the Work).
-
-The Work is provided under the terms of this Licence when the Licensor (as
-defined below) has placed the following notice immediately following the
-copyright notice for the Work:
-
- Licensed under the EUPL
-
-or has expressed by any other means his willingness to license under the EUPL.
-
-1. Definitions
-
-In this Licence, the following terms have the following meaning:
-
-- ‘The Licence’: this Licence.
-
-- ‘The Original Work’: the work or software distributed or communicated by the
- Licensor under this Licence, available as Source Code and also as Executable
- Code as the case may be.
-
-- ‘Derivative Works’: the works or software that could be created by the
- Licensee, based upon the Original Work or modifications thereof. This Licence
- does not define the extent of modification or dependence on the Original Work
- required in order to classify a work as a Derivative Work; this extent is
- determined by copyright law applicable in the country mentioned in Article 15.
-
-- ‘The Work’: the Original Work or its Derivative Works.
-
-- ‘The Source Code’: the human-readable form of the Work which is the most
- convenient for people to study and modify.
-
-- ‘The Executable Code’: any code which has generally been compiled and which is
- meant to be interpreted by a computer as a program.
-
-- ‘The Licensor’: the natural or legal person that distributes or communicates
- the Work under the Licence.
-
-- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
- Licence, or otherwise contributes to the creation of a Derivative Work.
-
-- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
- the Work under the terms of the Licence.
-
-- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
- renting, distributing, communicating, transmitting, or otherwise making
- available, online or offline, copies of the Work or providing access to its
- essential functionalities at the disposal of any other natural or legal
- person.
-
-2. Scope of the rights granted by the Licence
-
-The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
-sublicensable licence to do the following, for the duration of copyright vested
-in the Original Work:
-
-- use the Work in any circumstance and for all usage,
-- reproduce the Work,
-- modify the Work, and make Derivative Works based upon the Work,
-- communicate to the public, including the right to make available or display
- the Work or copies thereof to the public and perform publicly, as the case may
- be, the Work,
-- distribute the Work or copies thereof,
-- lend and rent the Work or copies thereof,
-- sublicense rights in the Work or copies thereof.
-
-Those rights can be exercised on any media, supports and formats, whether now
-known or later invented, as far as the applicable law permits so.
-
-In the countries where moral rights apply, the Licensor waives his right to
-exercise his moral right to the extent allowed by law in order to make effective
-the licence of the economic rights here above listed.
-
-The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
-any patents held by the Licensor, to the extent necessary to make use of the
-rights granted on the Work under this Licence.
-
-3. Communication of the Source Code
-
-The Licensor may provide the Work either in its Source Code form, or as
-Executable Code. If the Work is provided as Executable Code, the Licensor
-provides in addition a machine-readable copy of the Source Code of the Work
-along with each copy of the Work that the Licensor distributes or indicates, in
-a notice following the copyright notice attached to the Work, a repository where
-the Source Code is easily and freely accessible for as long as the Licensor
-continues to distribute or communicate the Work.
-
-4. Limitations on copyright
-
-Nothing in this Licence is intended to deprive the Licensee of the benefits from
-any exception or limitation to the exclusive rights of the rights owners in the
-Work, of the exhaustion of those rights or of other applicable limitations
-thereto.
-
-5. Obligations of the Licensee
-
-The grant of the rights mentioned above is subject to some restrictions and
-obligations imposed on the Licensee. Those obligations are the following:
-
-Attribution right: The Licensee shall keep intact all copyright, patent or
-trademarks notices and all notices that refer to the Licence and to the
-disclaimer of warranties. The Licensee must include a copy of such notices and a
-copy of the Licence with every copy of the Work he/she distributes or
-communicates. The Licensee must cause any Derivative Work to carry prominent
-notices stating that the Work has been modified and the date of modification.
-
-Copyleft clause: If the Licensee distributes or communicates copies of the
-Original Works or Derivative Works, this Distribution or Communication will be
-done under the terms of this Licence or of a later version of this Licence
-unless the Original Work is expressly distributed only under this version of the
-Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
-(becoming Licensor) cannot offer or impose any additional terms or conditions on
-the Work or Derivative Work that alter or restrict the terms of the Licence.
-
-Compatibility clause: If the Licensee Distributes or Communicates Derivative
-Works or copies thereof based upon both the Work and another work licensed under
-a Compatible Licence, this Distribution or Communication can be done under the
-terms of this Compatible Licence. For the sake of this clause, ‘Compatible
-Licence’ refers to the licences listed in the appendix attached to this Licence.
-Should the Licensee's obligations under the Compatible Licence conflict with
-his/her obligations under this Licence, the obligations of the Compatible
-Licence shall prevail.
-
-Provision of Source Code: When distributing or communicating copies of the Work,
-the Licensee will provide a machine-readable copy of the Source Code or indicate
-a repository where this Source will be easily and freely available for as long
-as the Licensee continues to distribute or communicate the Work.
-
-Legal Protection: This Licence does not grant permission to use the trade names,
-trademarks, service marks, or 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 copyright notice.
-
-6. Chain of Authorship
-
-The original Licensor warrants that the copyright in the Original Work granted
-hereunder is owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each Contributor warrants that the copyright in the modifications he/she brings
-to the Work are owned by him/her or licensed to him/her and that he/she has the
-power and authority to grant the Licence.
-
-Each time You accept the Licence, the original Licensor and subsequent
-Contributors grant You a licence to their contributions to the Work, under the
-terms of this Licence.
-
-7. Disclaimer of Warranty
-
-The Work is a work in progress, which is continuously improved by numerous
-Contributors. It is not a finished work and may therefore contain defects or
-‘bugs’ inherent to this type of development.
-
-For the above reason, the Work is provided under the Licence on an ‘as is’ basis
-and without warranties of any kind concerning the Work, including without
-limitation merchantability, fitness for a particular purpose, absence of defects
-or errors, accuracy, non-infringement of intellectual property rights other than
-copyright as stated in Article 6 of this Licence.
-
-This disclaimer of warranty is an essential part of the Licence and a condition
-for the grant of any rights to the Work.
-
-8. Disclaimer of Liability
-
-Except in the cases of wilful misconduct or damages directly caused to natural
-persons, the Licensor will in no event be liable for any direct or indirect,
-material or moral, damages of any kind, arising out of the Licence or of the use
-of the Work, including without limitation, damages for loss of goodwill, work
-stoppage, computer failure or malfunction, loss of data or any commercial
-damage, even if the Licensor has been advised of the possibility of such damage.
-However, the Licensor will be liable under statutory product liability laws as
-far such laws apply to the Work.
-
-9. Additional agreements
-
-While distributing the Work, You may choose to conclude an additional agreement,
-defining obligations or services consistent with this Licence. However, if
-accepting obligations, You may act only on your own behalf and on your sole
-responsibility, not on behalf of the original Licensor or 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
-the fact You have accepted any warranty or additional liability.
-
-10. Acceptance of the Licence
-
-The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
-placed under the bottom of a window displaying the text of this Licence or by
-affirming consent in any other similar way, in accordance with the rules of
-applicable law. Clicking on that icon indicates your clear and irrevocable
-acceptance of this Licence and all of its terms and conditions.
-
-Similarly, you irrevocably accept this Licence and all of its terms and
-conditions by exercising any rights granted to You by Article 2 of this Licence,
-such as the use of the Work, the creation by You of a Derivative Work or the
-Distribution or Communication by You of the Work or copies thereof.
-
-11. Information to the public
-
-In case of any Distribution or Communication of the Work by means of electronic
-communication by You (for example, by offering to download the Work from a
-remote location) the distribution channel or media (for example, a website) must
-at least provide to the public the information requested by the applicable law
-regarding the Licensor, the Licence and the way it may be accessible, concluded,
-stored and reproduced by the Licensee.
-
-12. Termination of the Licence
-
-The Licence and the rights granted hereunder will terminate automatically upon
-any breach by the Licensee of the terms of the Licence.
-
-Such a termination will not terminate the licences of any person who has
-received the Work from the Licensee under the Licence, provided such persons
-remain in full compliance with the Licence.
-
-13. Miscellaneous
-
-Without prejudice of Article 9 above, the Licence represents the complete
-agreement between the Parties as to the Work.
-
-If any provision of the Licence is invalid or unenforceable under applicable
-law, this will not affect the validity or enforceability of the Licence as a
-whole. Such provision will be construed or reformed so as necessary to make it
-valid and enforceable.
-
-The European Commission may publish other linguistic versions or new versions of
-this Licence or updated versions of the Appendix, so far this is required and
-reasonable, without reducing the scope of the rights granted by the Licence. New
-versions of the Licence will be published with a unique version number.
-
-All linguistic versions of this Licence, approved by the European Commission,
-have identical value. Parties can take advantage of the linguistic version of
-their choice.
-
-14. Jurisdiction
-
-Without prejudice to specific agreement between parties,
-
-- any litigation resulting from the interpretation of this License, arising
- between the European Union institutions, bodies, offices or agencies, as a
- Licensor, and any Licensee, will be subject to the jurisdiction of the Court
- of Justice of the European Union, as laid down in article 272 of the Treaty on
- the Functioning of the European Union,
-
-- any litigation arising between other parties and resulting from the
- interpretation of this License, will be subject to the exclusive jurisdiction
- of the competent court where the Licensor resides or conducts its primary
- business.
-
-15. Applicable Law
-
-Without prejudice to specific agreement between parties,
-
-- this Licence shall be governed by the law of the European Union Member State
- where the Licensor has his seat, resides or has his registered office,
-
-- this licence shall be governed by Belgian law if the Licensor has no seat,
- residence or registered office inside a European Union Member State.
-
-Appendix
-
-‘Compatible Licences’ according to Article 5 EUPL are:
-
-- GNU General Public License (GPL) v. 2, v. 3
-- GNU Affero General Public License (AGPL) v. 3
-- Open Software License (OSL) v. 2.1, v. 3.0
-- Eclipse Public License (EPL) v. 1.0
-- CeCILL v. 2.0, v. 2.1
-- Mozilla Public Licence (MPL) v. 2
-- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
-- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
- works other than software
-- European Union Public Licence (EUPL) v. 1.1, v. 1.2
-- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
- Reciprocity (LiLiQ-R+).
-
-The European Commission may update this Appendix to later versions of the above
-licences without producing a new version of the EUPL, as long as they provide
-the rights granted in Article 2 of this Licence and protect the covered Source
-Code from exclusive appropriation.
-
-All other changes or additions to this Appendix require the production of a new
-EUPL version.
diff --git a/packages/adapters/angular/v14/README.md b/packages/adapters/angular/v14/README.md
deleted file mode 100644
index ad61a2c751..0000000000
--- a/packages/adapters/angular/v14/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Angular-Adapter
-
-Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
-
-Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
-
-Mehr zum **Projekt** kann in der [README](https://public-ui.github.io/docs) nachgelesen werden.
-
-## Referenzen
-
--
diff --git a/packages/adapters/angular/v14/ng-module.js b/packages/adapters/angular/v14/ng-module.js
deleted file mode 100644
index 4bff553cde..0000000000
--- a/packages/adapters/angular/v14/ng-module.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const fs = require('fs');
-
-const componentFileContents = fs.readFileSync('./src/components.ts', 'utf-8');
-const componentList = [...componentFileContents.matchAll(/export class ([^ ]+)/g)].map((group) => group[1]);
-const componentListStr = componentList.join(', ');
-
-fs.writeFileSync(
- './src/index.ts',
- `
-/* AutoGen NgModule */
-
-import { CommonModule } from '@angular/common';
-import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
-import { ${componentListStr} } from './components';
-import { ReplaceTagDirective } from './angular-component-lib/ReplaceTagDirective';
-export { setTagNameTransformer } from './angular-component-lib/tagNameTransformer';
-
-@NgModule({
- declarations: [ReplaceTagDirective, ${componentListStr}],
- exports: [${componentListStr}],
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
- imports: [CommonModule],
-})
-export class KoliBriModule {}
-export { ${componentListStr} }
-`,
- 'utf-8',
-);
diff --git a/packages/adapters/angular/v14/package.json b/packages/adapters/angular/v14/package.json
deleted file mode 100644
index c03f3089da..0000000000
--- a/packages/adapters/angular/v14/package.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "name": "@public-ui/angular-v14",
- "version": "2.0.14",
- "license": "EUPL-1.2",
- "homepage": "https://public-ui.github.io",
- "repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
- "bugs": {
- "url": "https://github.com/public-ui/kolibri/issues",
- "email": "kolibri@itzbund.de"
- },
- "author": {
- "name": "Informationstechnikzentrum Bund",
- "email": "kolibri@itzbund.de"
- },
- "sideEffects": false,
- "description": "Angular (v14) framework adapter for KoliBri - The accessible HTML-Standard.",
- "keywords": [
- "accessibility",
- "accessible",
- "bitv",
- "framework",
- "library",
- "designsystem",
- "design",
- "system",
- "web components",
- "webcomponents",
- "aria",
- "wai",
- "axe",
- "custom elements",
- "styleguide",
- "style",
- "guide",
- "ui",
- "html",
- "css",
- "web",
- "a11y",
- "w3c",
- "webstandard",
- "wcag",
- "angular"
- ],
- "scripts": {
- "clean": "lerna exec --stream -- git clean -f -d -X && git clean -f -d -X",
- "build:cjs": "tsc -m commonjs --outDir cjs",
- "build:clean": "rimraf cjs esm types umd",
- "build:esm": "tsc -m esnext --outDir esm",
- "build:ngc": "node ng-module.js && ngc -p .",
- "build:tsc": "tsc -p .",
- "build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
- "build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
- },
- "main": "./dist/index.js",
- "module": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- "types": "./dist/index.d.ts",
- "require": "./dist/index.js",
- "import": "./dist/index.js"
- },
- "devDependencies": {
- "@angular/common": "14.3.0",
- "@angular/compiler": "14.3.0",
- "@angular/compiler-cli": "14.3.0",
- "@angular/core": "14.3.0",
- "@public-ui/components": "2.0.14",
- "@types/minimatch": "5.1.2",
- "@types/minimist": "1.2.5",
- "@types/node": "ts4.8",
- "@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
- "rxjs": "7.8.1",
- "tslib": "2.6.2",
- "typescript": "4.8.4",
- "zone.js": "0.12.0"
- },
- "peerDependencies": {
- "@angular/core": "14.3.0",
- "@public-ui/components": "2.0.14"
- },
- "files": [
- "dist"
- ]
-}
diff --git a/packages/adapters/angular/v14/tsconfig.json b/packages/adapters/angular/v14/tsconfig.json
deleted file mode 100644
index 0904853eb9..0000000000
--- a/packages/adapters/angular/v14/tsconfig.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "angularCompilerOptions": {
- "annotateForClosureCompiler": false,
- "strictMetadataEmit": true,
- "flatModuleOutFile": "core.js",
- "flatModuleId": "@public-ui/angular",
- "skipTemplateCodegen": true,
- "fullTemplateTypeCheck": false,
- "enableIvy": true
- },
- "compilerOptions": {
- "alwaysStrict": true,
- "strict": true,
- "allowSyntheticDefaultImports": true,
- "allowUnreachableCode": false,
- "declaration": true,
- "declarationDir": "dist",
- "experimentalDecorators": true,
- "forceConsistentCasingInFileNames": true,
- "lib": ["dom", "es2017"],
- "module": "ESNext",
- "moduleResolution": "node",
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noUnusedLocals": false,
- "noUnusedParameters": true,
- "outDir": "dist",
- "pretty": true,
- "removeComments": false,
- "importHelpers": true,
- "rootDir": "src",
- "strictPropertyInitialization": false,
- "target": "es2015",
- "skipLibCheck": true
- },
- "files": ["src/index.ts"],
- "exclude": ["node_modules"]
-}
diff --git a/packages/adapters/angular/v15/README.md b/packages/adapters/angular/v15/README.md
index ad61a2c751..409ea793dc 100644
--- a/packages/adapters/angular/v15/README.md
+++ b/packages/adapters/angular/v15/README.md
@@ -1,5 +1,13 @@
# Angular-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/angular-v15)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/angular-v15)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/angular-v15)](https://www.npmjs.com/package/@public-ui/angular-v15)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/angular-v15)](https://bundlephobia.com/result?p=@public-ui/angular-v15)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
diff --git a/packages/adapters/angular/v15/package.json b/packages/adapters/angular/v15/package.json
index 091f15c98f..5c65c2fe1c 100644
--- a/packages/adapters/angular/v15/package.json
+++ b/packages/adapters/angular/v15/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/angular-v15",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -54,8 +54,7 @@
"build:tsc": "tsc -p .",
"build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
"build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
+ "build": "npm run build:clean && npm run build:ngc"
},
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -70,21 +69,19 @@
"@angular/compiler": "15.2.10",
"@angular/compiler-cli": "15.2.10",
"@angular/core": "15.2.10",
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts4.9",
"@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
+ "prettier": "3.4.2",
+ "rimraf": "6.0.1",
"rxjs": "7.8.1",
- "tslib": "2.6.2",
"typescript": "4.9.5",
"zone.js": "0.13.3"
},
"peerDependencies": {
"@angular/core": "15.2.10",
- "@public-ui/components": "2.0.14"
+ "@public-ui/components": "workspace:*"
},
"files": [
"dist"
diff --git a/packages/adapters/angular/v16/README.md b/packages/adapters/angular/v16/README.md
index ad61a2c751..498a73d914 100644
--- a/packages/adapters/angular/v16/README.md
+++ b/packages/adapters/angular/v16/README.md
@@ -1,5 +1,13 @@
# Angular-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/angular-v16)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/angular-v16)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/angular-v16)](https://www.npmjs.com/package/@public-ui/angular-v16)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/angular-v16)](https://bundlephobia.com/result?p=@public-ui/angular-v16)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
diff --git a/packages/adapters/angular/v16/package.json b/packages/adapters/angular/v16/package.json
index 7a4ce8442e..b61fa05425 100644
--- a/packages/adapters/angular/v16/package.json
+++ b/packages/adapters/angular/v16/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/angular-v16",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -54,8 +54,7 @@
"build:tsc": "tsc -p .",
"build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
"build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
+ "build": "npm run build:clean && npm run build:ngc"
},
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -70,21 +69,19 @@
"@angular/compiler": "16.2.12",
"@angular/compiler-cli": "16.2.12",
"@angular/core": "16.2.12",
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts5.1",
"@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
+ "prettier": "3.4.2",
+ "rimraf": "6.0.1",
"rxjs": "7.8.1",
- "tslib": "2.6.2",
"typescript": "5.1.6",
"zone.js": "0.13.3"
},
"peerDependencies": {
"@angular/core": "16.2.12",
- "@public-ui/components": "2.0.14"
+ "@public-ui/components": "workspace:*"
},
"files": [
"dist"
diff --git a/packages/adapters/angular/v17/README.md b/packages/adapters/angular/v17/README.md
index ad61a2c751..585226b41c 100644
--- a/packages/adapters/angular/v17/README.md
+++ b/packages/adapters/angular/v17/README.md
@@ -1,5 +1,13 @@
# Angular-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/angular-v17)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/angular-v17)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/angular-v17)](https://www.npmjs.com/package/@public-ui/angular-v17)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/angular-v17)](https://bundlephobia.com/result?p=@public-ui/angular-v17)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
diff --git a/packages/adapters/angular/v17/package.json b/packages/adapters/angular/v17/package.json
index 38628256e5..b86f1ef76d 100644
--- a/packages/adapters/angular/v17/package.json
+++ b/packages/adapters/angular/v17/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/angular-v17",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -54,8 +54,7 @@
"build:tsc": "tsc -p .",
"build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
"build:umd": "tsc -m umd --outDir umd",
- "build": "npm run build:clean && npm run build:ngc",
- "prepack": "npm run build"
+ "build": "npm run build:clean && npm run build:ngc"
},
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -66,25 +65,23 @@
"import": "./dist/index.js"
},
"devDependencies": {
- "@angular/common": "17.3.4",
- "@angular/compiler": "17.3.4",
- "@angular/compiler-cli": "17.3.4",
- "@angular/core": "17.3.4",
- "@public-ui/components": "2.0.14",
+ "@angular/common": "17.3.12",
+ "@angular/compiler": "17.3.12",
+ "@angular/compiler-cli": "17.3.12",
+ "@angular/core": "17.3.12",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts5.3",
"@types/normalize-package-data": "2.4.4",
- "prettier": "3.2.5",
- "rimraf": "5.0.5",
+ "prettier": "3.4.2",
+ "rimraf": "6.0.1",
"rxjs": "7.8.1",
- "tslib": "2.6.2",
"typescript": "5.4.5",
- "zone.js": "0.14.4"
+ "zone.js": "0.14.10"
},
"peerDependencies": {
- "@angular/core": "17.3.4",
- "@public-ui/components": "2.0.14"
+ "@angular/core": "17.3.12",
+ "@public-ui/components": "workspace:*"
},
"files": [
"dist"
diff --git a/packages/adapters/angular/v11/.gitignore b/packages/adapters/angular/v18/.gitignore
similarity index 100%
rename from packages/adapters/angular/v11/.gitignore
rename to packages/adapters/angular/v18/.gitignore
diff --git a/packages/adapters/angular/v12/.gitignore b/packages/adapters/angular/v18/.npmignore
similarity index 100%
rename from packages/adapters/angular/v12/.gitignore
rename to packages/adapters/angular/v18/.npmignore
diff --git a/packages/adapters/angular/v11/LICENSE b/packages/adapters/angular/v18/LICENSE
similarity index 100%
rename from packages/adapters/angular/v11/LICENSE
rename to packages/adapters/angular/v18/LICENSE
diff --git a/packages/adapters/angular/v18/README.md b/packages/adapters/angular/v18/README.md
new file mode 100644
index 0000000000..9ac10e78a2
--- /dev/null
+++ b/packages/adapters/angular/v18/README.md
@@ -0,0 +1,19 @@
+# Angular-Adapter
+
+[![npm](https://img.shields.io/npm/v/@public-ui/angular-v18)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/angular-v18)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/angular-v18)](https://www.npmjs.com/package/@public-ui/angular-v18)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/angular-v18)](https://bundlephobia.com/result?p=@public-ui/angular-v18)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
+Das [**Angular**](https://angular.io)-Modul ist der Framework-Adapter für die Komponenten-Bibliothek.
+
+Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
+
+Mehr zum **Projekt** kann in der [README](https://public-ui.github.io/docs) nachgelesen werden.
+
+## Referenzen
+
+-
diff --git a/packages/adapters/angular/v13/ng-module.js b/packages/adapters/angular/v18/ng-module.js
similarity index 100%
rename from packages/adapters/angular/v13/ng-module.js
rename to packages/adapters/angular/v18/ng-module.js
diff --git a/packages/adapters/angular/v18/package.json b/packages/adapters/angular/v18/package.json
new file mode 100644
index 0000000000..8d28dfcfad
--- /dev/null
+++ b/packages/adapters/angular/v18/package.json
@@ -0,0 +1,89 @@
+{
+ "name": "@public-ui/angular-v18",
+ "version": "3.0.0-rc.2",
+ "license": "EUPL-1.2",
+ "homepage": "https://public-ui.github.io",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
+ "bugs": {
+ "url": "https://github.com/public-ui/kolibri/issues",
+ "email": "kolibri@itzbund.de"
+ },
+ "author": {
+ "name": "Informationstechnikzentrum Bund",
+ "email": "kolibri@itzbund.de"
+ },
+ "sideEffects": false,
+ "description": "Angular (v18) framework adapter for KoliBri - The accessible HTML-Standard.",
+ "keywords": [
+ "accessibility",
+ "accessible",
+ "bitv",
+ "framework",
+ "library",
+ "designsystem",
+ "design",
+ "system",
+ "web components",
+ "webcomponents",
+ "aria",
+ "wai",
+ "axe",
+ "custom elements",
+ "styleguide",
+ "style",
+ "guide",
+ "ui",
+ "html",
+ "css",
+ "web",
+ "a11y",
+ "w3c",
+ "webstandard",
+ "wcag",
+ "angular"
+ ],
+ "scripts": {
+ "clean": "lerna exec --stream -- git clean -f -d -X && git clean -f -d -X",
+ "build:cjs": "tsc -m commonjs --outDir cjs",
+ "build:clean": "rimraf cjs esm types umd",
+ "build:esm": "tsc -m esnext --outDir esm",
+ "build:ngc": "node ng-module.js && ngc -p .",
+ "build:tsc": "tsc -p .",
+ "build:types": "tsc -d --outDir types && rimraf types/*.js types/*.map types/**/*.js types/**/*.map",
+ "build:umd": "tsc -m umd --outDir umd",
+ "build": "npm run build:clean && npm run build:ngc"
+ },
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "require": "./dist/index.js",
+ "import": "./dist/index.js"
+ },
+ "devDependencies": {
+ "@angular/common": "18.2.13",
+ "@angular/compiler": "18.2.13",
+ "@angular/compiler-cli": "18.2.13",
+ "@angular/core": "18.2.13",
+ "@public-ui/components": "workspace:*",
+ "@types/minimatch": "5.1.2",
+ "@types/minimist": "1.2.5",
+ "@types/normalize-package-data": "2.4.4",
+ "prettier": "3.4.2",
+ "rimraf": "6.0.1",
+ "rxjs": "7.8.1",
+ "typescript": "5.5.4",
+ "zone.js": "0.14.10"
+ },
+ "peerDependencies": {
+ "@angular/core": "18.2.13",
+ "@public-ui/components": "workspace:*"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/packages/adapters/angular/v11/tsconfig.json b/packages/adapters/angular/v18/tsconfig.json
similarity index 100%
rename from packages/adapters/angular/v11/tsconfig.json
rename to packages/adapters/angular/v18/tsconfig.json
diff --git a/packages/adapters/hydrate/README.md b/packages/adapters/hydrate/README.md
index 22c6f6b1fa..2b4e940566 100644
--- a/packages/adapters/hydrate/README.md
+++ b/packages/adapters/hydrate/README.md
@@ -1,5 +1,13 @@
# KoliBri - Hydrate-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/hydrate)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/hydrate)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/hydrate)](https://www.npmjs.com/package/@public-ui/hydrate)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/hydrate)](https://bundlephobia.com/result?p=@public-ui/hydrate)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Motivation
Provide an adapter for Server Side Rendering of KoliBri components.
diff --git a/packages/adapters/hydrate/package.json b/packages/adapters/hydrate/package.json
index 23c95bce9d..b2e15ad3c1 100644
--- a/packages/adapters/hydrate/package.json
+++ b/packages/adapters/hydrate/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/hydrate",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,15 +45,14 @@
"hydrate"
],
"scripts": {
- "build": "rimraf dist/package.json",
- "prepack": "npm run build"
+ "build": "rimraf dist/package.json"
},
"devDependencies": {
- "@public-ui/components": "2.0.14",
- "rimraf": "5.0.5"
+ "@public-ui/components": "workspace:*",
+ "rimraf": "6.0.1"
},
"peerDependencies": {
- "@public-ui/components": "2.0.14"
+ "@public-ui/components": "workspace:*"
},
"sideEffects": false,
"type": "commonjs",
diff --git a/packages/adapters/preact/README.md b/packages/adapters/preact/README.md
index 1ed8d41e19..6108fbf1b7 100644
--- a/packages/adapters/preact/README.md
+++ b/packages/adapters/preact/README.md
@@ -1,5 +1,13 @@
# KoliBri - Preact-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/react)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/react)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/react)](https://www.npmjs.com/package/@public-ui/react)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/react)](https://bundlephobia.com/result?p=@public-ui/themes)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
The [Preact](https://github.com/preactjs/preact) adapter is a wrapper around the React adapter. Please refer to the [React adapter documentation](../react/README.md) for more information.
⚠️ Preact support is currently considered experimental.
diff --git a/packages/adapters/preact/package.json b/packages/adapters/preact/package.json
index 725d39c853..f38f4d3636 100644
--- a/packages/adapters/preact/package.json
+++ b/packages/adapters/preact/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/preact",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,21 +45,20 @@
"preact"
],
"scripts": {
- "build": "unbuild",
- "prepack": "unbuild"
+ "build": "unbuild"
},
"dependencies": {
- "@public-ui/react": "2.0.14"
+ "@public-ui/react": "workspace:*"
},
"devDependencies": {
- "@public-ui/components": "2.0.14",
- "react": "18.2.0",
- "react-dom": "18.2.0",
- "typescript": "5.4.5",
+ "@public-ui/components": "workspace:*",
+ "react": "18.3.1",
+ "react-dom": "18.3.1",
+ "typescript": "5.7.3",
"unbuild": "1.2.1"
},
"peerDependencies": {
- "preact": ">=10.20.2"
+ "preact": ">=10.25.4"
},
"sideEffects": false,
"type": "module",
diff --git a/packages/adapters/react-standalone/.gitignore b/packages/adapters/react-standalone/.gitignore
deleted file mode 100644
index 4f00cd9a73..0000000000
--- a/packages/adapters/react-standalone/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/src/
diff --git a/packages/adapters/react-standalone/README.md b/packages/adapters/react-standalone/README.md
index b2d006fee2..45fc236646 100644
--- a/packages/adapters/react-standalone/README.md
+++ b/packages/adapters/react-standalone/README.md
@@ -1,5 +1,13 @@
# KoliBri - Standalone React-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/react-standalone)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/react-standalone)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/react-standalone)](https://www.npmjs.com/package/@public-ui/react-standalone)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/react-standalone)](https://bundlephobia.com/result?p=@public-ui/react-standalone)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Motivation
Provide an adapter for [React](https://reactjs.org) to use the KoliBri components, without the need for a build/bundle process.
diff --git a/packages/adapters/react-standalone/kolibri-rock's.html b/packages/adapters/react-standalone/kolibri-rock's.html
deleted file mode 100644
index 0bd0208712..0000000000
--- a/packages/adapters/react-standalone/kolibri-rock's.html
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
- Home
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Home
-
-
-
-
-
-
- Thanks for watching! ;-)
-
-
diff --git a/packages/adapters/react-standalone/package.json b/packages/adapters/react-standalone/package.json
index 8adc267c8f..fb73ee13e8 100644
--- a/packages/adapters/react-standalone/package.json
+++ b/packages/adapters/react-standalone/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/react-standalone",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,17 +45,17 @@
"react"
],
"scripts": {
- "build": "pnpm prepare && node scripts/make-standalone.js",
- "prepack": "pnpm build",
- "prepare": "rimraf dist && cpy \"node_modules/@public-ui/react/dist/*.mjs\" dist --dot"
+ "build": "webpack"
},
"devDependencies": {
- "@public-ui/react": "2.0.14",
+ "@public-ui/react": "workspace:*",
"cpy-cli": "5.0.0",
- "rimraf": "5.0.5"
+ "rimraf": "6.0.1",
+ "webpack": "5.97.1",
+ "webpack-cli": "5.1.4"
},
"peerDependencies": {
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
},
diff --git a/packages/adapters/react-standalone/scripts/make-standalone.js b/packages/adapters/react-standalone/scripts/make-standalone.js
deleted file mode 100644
index fff0ea6006..0000000000
--- a/packages/adapters/react-standalone/scripts/make-standalone.js
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env node
-
-const fs = require('fs');
-const path = require('path');
-const rimraf = require('rimraf');
-
-let code = fs
- .readFileSync('dist/index.mjs', 'utf-8')
- .replace(/import React, \{ createElement \} from 'react';\n+/, '')
- .replace(/return createElement\(/g, 'return React.createElement(');
-
-const pattern = /export \{ (Kol[^,]+),/g;
-while (pattern.test(code)) {
- code = code.replace(/export \{ (Kol[^,]+),/g, 'window.$1 = $1;\nexport {');
-}
-
-code = code.replace(/export \{ (Kol[^ ]+) }/g, 'window.$1 = $1');
-
-fs.writeFileSync('dist/index.mjs', code, 'utf-8');
diff --git a/packages/adapters/react-standalone/scripts/package.json b/packages/adapters/react-standalone/scripts/package.json
deleted file mode 100644
index a0df0c8677..0000000000
--- a/packages/adapters/react-standalone/scripts/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "type": "commonjs"
-}
diff --git a/packages/adapters/react-standalone/src/index.js b/packages/adapters/react-standalone/src/index.js
new file mode 100644
index 0000000000..71efcc6ab8
--- /dev/null
+++ b/packages/adapters/react-standalone/src/index.js
@@ -0,0 +1,5 @@
+import * as components from '@public-ui/react';
+
+Object.entries(components).forEach(([name, component]) => {
+ window[name] = component;
+});
diff --git a/packages/adapters/react-standalone/webpack.config.js b/packages/adapters/react-standalone/webpack.config.js
new file mode 100644
index 0000000000..6c50440a2a
--- /dev/null
+++ b/packages/adapters/react-standalone/webpack.config.js
@@ -0,0 +1,7 @@
+export default {
+ mode: 'production',
+ output: {
+ clean: true,
+ filename: 'index.mjs',
+ },
+};
diff --git a/packages/adapters/react/README.md b/packages/adapters/react/README.md
index 2f783cd844..65eca5b384 100644
--- a/packages/adapters/react/README.md
+++ b/packages/adapters/react/README.md
@@ -1,5 +1,13 @@
# KoliBri - React-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/react)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/react)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/react)](https://www.npmjs.com/package/@public-ui/react)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/react)](https://bundlephobia.com/result?p=@public-ui/react)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Motivation
Provide an adapter for [React](https://reactjs.org) to use the KoliBri components.
diff --git a/packages/adapters/react/package.json b/packages/adapters/react/package.json
index ab11f28c87..6efa67b6ea 100644
--- a/packages/adapters/react/package.json
+++ b/packages/adapters/react/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/react",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,24 +45,22 @@
"react"
],
"scripts": {
- "build": "unbuild",
- "prepack": "unbuild"
+ "build": "unbuild"
},
"devDependencies": {
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts5.4",
"@types/normalize-package-data": "2.4.4",
- "@types/react": "18.2.77",
- "@types/react-dom": "18.2.25",
+ "@types/react": "18.3.4",
+ "@types/react-dom": "18.3.5",
"react": "18.2.0",
"react-dom": "18.2.0",
- "typescript": "5.4.5",
+ "typescript": "5.7.3",
"unbuild": "1.2.1"
},
"peerDependencies": {
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
},
diff --git a/packages/adapters/solid/README.md b/packages/adapters/solid/README.md
index b3e2289867..b7c975c4fe 100644
--- a/packages/adapters/solid/README.md
+++ b/packages/adapters/solid/README.md
@@ -1,5 +1,13 @@
# KoliBri - Solid-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/solid)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/solid)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/solid)](https://www.npmjs.com/package/@public-ui/solid)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/solid)](https://bundlephobia.com/result?p=@public-ui/solid)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Motivation
Provide an adapter for [SolidJS](https://www.solidjs.com/) to use the KoliBri components.
@@ -16,12 +24,12 @@ yarn add -g @public-ui/solid
## Usage
-First, initialize KoliBri with a [theme](https://github.com/public-ui/kolibri/tree/develop/packages/themes) and create a Solid root:
+First, initialize KoliBri with a [theme](https://github.com/public-ui/kolibri/tree/develop/packages/solid) and create a Solid root:
```ts
import { defineCustomElements } from '@public-ui/components/dist/loader';
import { register } from '@public-ui/components';
-import { DEFAULT } from '@public-ui/themes';
+import { DEFAULT } from '@public-ui/solid';
register(DEFAULT, defineCustomElements)
.then(() => {
diff --git a/packages/adapters/solid/package.json b/packages/adapters/solid/package.json
index 513d041d65..59d2a23a3f 100644
--- a/packages/adapters/solid/package.json
+++ b/packages/adapters/solid/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/solid",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,22 +45,20 @@
"solidjs"
],
"scripts": {
- "build": "unbuild",
- "prepack": "unbuild"
+ "build": "unbuild"
},
"devDependencies": {
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts5.4",
"@types/normalize-package-data": "2.4.4",
- "solid-js": "1.8.16",
- "typescript": "5.4.5",
+ "solid-js": "1.9.4",
+ "typescript": "5.7.3",
"unbuild": "1.2.1"
},
"peerDependencies": {
- "@public-ui/components": "2.0.14",
- "solid-js": ">=1.8.16"
+ "@public-ui/components": "workspace:*",
+ "solid-js": ">=1.9.4"
},
"sideEffects": false,
"type": "module",
diff --git a/packages/adapters/vaadin/README.md b/packages/adapters/vaadin/README.md
index f5701e04c3..f103afcd2a 100644
--- a/packages/adapters/vaadin/README.md
+++ b/packages/adapters/vaadin/README.md
@@ -1,5 +1,13 @@
# Vaadin-Adapter for KoliBri
+[![npm](https://img.shields.io/npm/v/@public-ui/vaadin)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/vaadin)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/vaadin)](https://www.npmjs.com/package/@public-ui/vaadin)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/vaadin)](https://bundlephobia.com/result?p=@public-ui/vaadin)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Open points
| Feature | Status |
diff --git a/packages/adapters/vue/README.md b/packages/adapters/vue/README.md
index 4ade14b124..8f47ecc114 100644
--- a/packages/adapters/vue/README.md
+++ b/packages/adapters/vue/README.md
@@ -1,5 +1,13 @@
# KoliBri - Vue-Adapter
+[![npm](https://img.shields.io/npm/v/@public-ui/vue)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/vue)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/vue)](https://www.npmjs.com/package/@public-ui/vue)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/vue)](https://bundlephobia.com/result?p=@public-ui/vue)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
## Motivation
Provide an adapter for [Vue](https://vuejs.org/) to use the KoliBri components.
@@ -16,7 +24,7 @@ yarn add -g @public-ui/vue
## Usage
-First, initialize KoliBri with a [theme](https://github.com/public-ui/kolibri/tree/develop/packages/themes) and create a Vue app:
+First, initialize KoliBri with a [theme](https://github.com/public-ui/kolibri/tree/develop/packages/vue) and create a Vue app:
```ts
import { createApp } from 'vue';
diff --git a/packages/adapters/vue/package.json b/packages/adapters/vue/package.json
index 2adfd766d2..98ba2fe05f 100644
--- a/packages/adapters/vue/package.json
+++ b/packages/adapters/vue/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/vue",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -45,22 +45,20 @@
"vue"
],
"scripts": {
- "build": "unbuild",
- "prepack": "unbuild"
+ "build": "unbuild"
},
"devDependencies": {
- "@babel/types": "7.24.0",
- "@public-ui/components": "2.0.14",
+ "@babel/types": "7.26.7",
+ "@public-ui/components": "workspace:*",
"@types/minimatch": "5.1.2",
"@types/minimist": "1.2.5",
- "@types/node": "ts5.4",
"@types/normalize-package-data": "2.4.4",
- "typescript": "5.4.5",
+ "typescript": "5.7.3",
"unbuild": "1.2.1",
"vue": "3.4.21"
},
"peerDependencies": {
- "@public-ui/components": "2.0.14",
+ "@public-ui/components": "workspace:*",
"vue": ">=3"
},
"sideEffects": false,
diff --git a/packages/components/.eslintignore b/packages/components/.eslintignore
index e12bd37bb3..3aed2a8ac0 100644
--- a/packages/components/.eslintignore
+++ b/packages/components/.eslintignore
@@ -1,3 +1,4 @@
-**/assets/**
-src/**/*.js
-src/**/*.html
\ No newline at end of file
+**/assets/**
+scripts/*.js
+src/**/*.js
+src/**/*.html
diff --git a/packages/components/.eslintrc.js b/packages/components/.eslintrc.js
index e5660aa022..52ee563e6b 100644
--- a/packages/components/.eslintrc.js
+++ b/packages/components/.eslintrc.js
@@ -1,13 +1,15 @@
+/* eslint-disable */
+
const config = {
root: true,
parserOptions: {
- project: './tsconfig.json',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
extends: [
'eslint:recommended',
// 'plugin:@stencil/recommended',
- // 'plugin:@stencil-community/recommended',
+ 'plugin:@stencil-community/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
@@ -36,6 +38,43 @@ const config = {
*/
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
+
+ '@stencil-community/async-methods': 'error',
+ '@stencil-community/ban-prefix': ['off', ['stencil', 'stnl', 'st']],
+ '@stencil-community/decorators-context': 'off',
+ '@stencil-community/decorators-style': [
+ 'off',
+ {
+ prop: 'inline',
+ state: 'inline',
+ element: 'inline',
+ event: 'inline',
+ method: 'multiline',
+ watch: 'multiline',
+ listen: 'multiline',
+ },
+ ],
+ '@stencil-community/element-type': 'off',
+ '@stencil-community/host-data-deprecated': 'off',
+ '@stencil-community/methods-must-be-public': 'off',
+ '@stencil-community/no-unused-watch': 'off',
+ '@stencil-community/own-methods-must-be-private': 'off',
+ '@stencil-community/own-props-must-be-private': 'off',
+ '@stencil-community/prefer-vdom-listener': 'off',
+ '@stencil-community/props-must-be-public': 'off',
+ '@stencil-community/props-must-be-readonly': 'off',
+ '@stencil-community/render-returns-host': 'off',
+ '@stencil-community/required-jsdoc': 'off',
+ '@stencil-community/reserved-member-names': 'off',
+ '@stencil-community/single-export': 'off',
+ '@stencil-community/strict-mutable': 'off',
+ '@stencil-community/ban-exported-const-enums': 'off',
+ '@stencil-community/strict-boolean-conditions': 'off',
+ '@stencil-community/ban-default-true': 'off',
+
+ 'react/jsx-no-bind': 'off',
+
+ 'no-console': 'error',
},
settings: {
react: {
@@ -81,7 +120,6 @@ config.overrides.push({
config.plugins = config.plugins || [];
// config.plugins.push('react');
config.plugins.push('jsx-a11y');
-config.plugins.push('no-loops');
config.settings = {
react: {
diff --git a/packages/components/.gitignore b/packages/components/.gitignore
index ecb6909886..7ace70dc01 100644
--- a/packages/components/.gitignore
+++ b/packages/components/.gitignore
@@ -1,4 +1,5 @@
/dist/
+/dist-e2e/
/doc/**
/loader/
/public/
@@ -43,3 +44,7 @@ UserInterfaceState.xcuserstate
# Allow
!/node_martin/*.tgz
+/test-results/
+/playwright-report/
+/blob-report/
+/playwright/.cache/
diff --git a/packages/components/.knip.json b/packages/components/.knip.json
index db2beb2ddd..1900e1a758 100644
--- a/packages/components/.knip.json
+++ b/packages/components/.knip.json
@@ -10,7 +10,6 @@
"@stencil/vue-output-target",
"eslint-plugin-html",
"eslint-plugin-jsdoc",
- "eslint-plugin-json",
"eslint-plugin-react"
],
"project": ["src/**/*.ts"]
diff --git a/packages/components/.lintstagedrc b/packages/components/.lintstagedrc
new file mode 100644
index 0000000000..7693413eba
--- /dev/null
+++ b/packages/components/.lintstagedrc
@@ -0,0 +1,4 @@
+{
+ "**/*.{ts,tsx,js,jsx}": ["prettier --list-different", "eslint"],
+ "**/*.{md,css,scss}": "prettier --list-different"
+}
diff --git a/packages/components/README.md b/packages/components/README.md
index 576438ed1f..5750d0bbb6 100644
--- a/packages/components/README.md
+++ b/packages/components/README.md
@@ -1,5 +1,13 @@
# Components (Library)
+[![npm](https://img.shields.io/npm/v/@public-ui/components)](https://www.npmjs.com/package/@public-ui/components)
+[![license](https://img.shields.io/npm/l/@public-ui/components)](https://github.com/public-ui/kolibri/blob/main/LICENSE)
+[![downloads](https://img.shields.io/npm/dt/@public-ui/components)](https://www.npmjs.com/package/@public-ui/components)
+[![issues](https://img.shields.io/github/issues/public-ui/kolibri)](https://github.com/public-ui/kolibri/issues)
+[![pull requests](https://img.shields.io/github/issues-pr/public-ui/kolibri)](https://github.com/public-ui/kolibri/pulls)
+[![size](https://img.shields.io/bundlephobia/min/@public-ui/components)](https://bundlephobia.com/result?p=@public-ui/components)
+![contributors](https://img.shields.io/github/contributors/public-ui/kolibri)
+
Das **Components**-Modul beinhaltet **alle** zur Komponenten-Bibliothek gehörenden **Web Components**.
Mehr zur **Modularisierung** kann im [Architekturkonzept](https://public-ui.github.io/docs/concepts/architecture) nachgelesen werden.
diff --git a/packages/components/assets/codicons/codicon.css b/packages/components/assets/codicons/codicon.css
index 7a161449ab..739be06ee4 100644
--- a/packages/components/assets/codicons/codicon.css
+++ b/packages/components/assets/codicons/codicon.css
@@ -6,7 +6,7 @@
@font-face {
font-family: "codicon";
font-display: block;
- src: url("./codicon.ttf?2ab61cbaefbdf4c7c5589068100bee0c") format("truetype");
+ src: url("./codicon.ttf?be64b7213e352cd7f91ef58198e71237") format("truetype");
}
.codicon[class*='codicon-'] {
@@ -72,6 +72,7 @@
.codicon-record-keys:before { content: "\ea65" }
.codicon-keyboard:before { content: "\ea65" }
.codicon-tag:before { content: "\ea66" }
+.codicon-git-pull-request-label:before { content: "\ea66" }
.codicon-tag-add:before { content: "\ea66" }
.codicon-tag-remove:before { content: "\ea66" }
.codicon-person:before { content: "\ea67" }
@@ -264,6 +265,7 @@
.codicon-diff-removed:before { content: "\eadf" }
.codicon-diff-renamed:before { content: "\eae0" }
.codicon-diff:before { content: "\eae1" }
+.codicon-diff-sidebyside:before { content: "\eae1" }
.codicon-discard:before { content: "\eae2" }
.codicon-editor-layout:before { content: "\eae3" }
.codicon-empty-window:before { content: "\eae4" }
@@ -327,6 +329,7 @@
.codicon-megaphone:before { content: "\eb1e" }
.codicon-mention:before { content: "\eb1f" }
.codicon-milestone:before { content: "\eb20" }
+.codicon-git-pull-request-milestone:before { content: "\eb20" }
.codicon-mortar-board:before { content: "\eb21" }
.codicon-move:before { content: "\eb22" }
.codicon-multiple-windows:before { content: "\eb23" }
@@ -452,9 +455,11 @@
.codicon-menu:before { content: "\eb94" }
.codicon-expand-all:before { content: "\eb95" }
.codicon-feedback:before { content: "\eb96" }
+.codicon-git-pull-request-reviewer:before { content: "\eb96" }
.codicon-group-by-ref-type:before { content: "\eb97" }
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
.codicon-account:before { content: "\eb99" }
+.codicon-git-pull-request-assignee:before { content: "\eb99" }
.codicon-bell-dot:before { content: "\eb9a" }
.codicon-debug-console:before { content: "\eb9b" }
.codicon-library:before { content: "\eb9c" }
@@ -568,7 +573,11 @@
.codicon-blank:before { content: "\ec03" }
.codicon-heart-filled:before { content: "\ec04" }
.codicon-map:before { content: "\ec05" }
+.codicon-map-horizontal:before { content: "\ec05" }
+.codicon-fold-horizontal:before { content: "\ec05" }
.codicon-map-filled:before { content: "\ec06" }
+.codicon-map-horizontal-filled:before { content: "\ec06" }
+.codicon-fold-horizontal-filled:before { content: "\ec06" }
.codicon-circle-small:before { content: "\ec07" }
.codicon-bell-slash:before { content: "\ec08" }
.codicon-bell-slash-dot:before { content: "\ec09" }
@@ -580,3 +589,47 @@
.codicon-send:before { content: "\ec0f" }
.codicon-sparkle:before { content: "\ec10" }
.codicon-insert:before { content: "\ec11" }
+.codicon-mic:before { content: "\ec12" }
+.codicon-thumbsdown-filled:before { content: "\ec13" }
+.codicon-thumbsup-filled:before { content: "\ec14" }
+.codicon-coffee:before { content: "\ec15" }
+.codicon-snake:before { content: "\ec16" }
+.codicon-game:before { content: "\ec17" }
+.codicon-vr:before { content: "\ec18" }
+.codicon-chip:before { content: "\ec19" }
+.codicon-piano:before { content: "\ec1a" }
+.codicon-music:before { content: "\ec1b" }
+.codicon-mic-filled:before { content: "\ec1c" }
+.codicon-repo-fetch:before { content: "\ec1d" }
+.codicon-copilot:before { content: "\ec1e" }
+.codicon-lightbulb-sparkle:before { content: "\ec1f" }
+.codicon-robot:before { content: "\ec20" }
+.codicon-sparkle-filled:before { content: "\ec21" }
+.codicon-diff-single:before { content: "\ec22" }
+.codicon-diff-multiple:before { content: "\ec23" }
+.codicon-surround-with:before { content: "\ec24" }
+.codicon-share:before { content: "\ec25" }
+.codicon-git-stash:before { content: "\ec26" }
+.codicon-git-stash-apply:before { content: "\ec27" }
+.codicon-git-stash-pop:before { content: "\ec28" }
+.codicon-vscode:before { content: "\ec29" }
+.codicon-vscode-insiders:before { content: "\ec2a" }
+.codicon-code-oss:before { content: "\ec2b" }
+.codicon-run-coverage:before { content: "\ec2c" }
+.codicon-run-all-coverage:before { content: "\ec2d" }
+.codicon-coverage:before { content: "\ec2e" }
+.codicon-github-project:before { content: "\ec2f" }
+.codicon-map-vertical:before { content: "\ec30" }
+.codicon-fold-vertical:before { content: "\ec30" }
+.codicon-map-vertical-filled:before { content: "\ec31" }
+.codicon-fold-vertical-filled:before { content: "\ec31" }
+.codicon-go-to-search:before { content: "\ec32" }
+.codicon-percentage:before { content: "\ec33" }
+.codicon-sort-percentage:before { content: "\ec33" }
+.codicon-attach:before { content: "\ec34" }
+.codicon-go-to-editing-session:before { content: "\ec35" }
+.codicon-edit-session:before { content: "\ec36" }
+.codicon-code-review:before { content: "\ec37" }
+.codicon-copilot-warning:before { content: "\ec38" }
+.codicon-python:before { content: "\ec39" }
+.codicon-git-fetch:before { content: "\f101" }
diff --git a/packages/components/assets/codicons/codicon.csv b/packages/components/assets/codicons/codicon.csv
index 1c8600cc0c..9ff6867799 100644
--- a/packages/components/assets/codicons/codicon.csv
+++ b/packages/components/assets/codicons/codicon.csv
@@ -17,6 +17,7 @@ arrow-small-right,,EA9F
arrow-small-up,,EAA0
arrow-swap,,EBCB
arrow-up,,EAA1
+attach,,EC34
azure-devops,,EBE8
azure,,EBD8
beaker-stop,,EBE1
@@ -46,6 +47,7 @@ chevron-down,,EAB4
chevron-left,,EAB5
chevron-right,,EAB6
chevron-up,,EAB7
+chip,,EC19
chrome-close,,EAB8
chrome-maximize,,EAB9
chrome-minimize,,EABA
@@ -65,7 +67,10 @@ close,,EA76
cloud-download,,EAC2
cloud-upload,,EAC3
cloud,,EBAA
+code-oss,,EC2B
+code-review,,EC37
code,,EAC4
+coffee,,EC15
collapse-all,,EAC5
color-mode,,EAC6
combine,,EBB6
@@ -76,7 +81,10 @@ comment,,EA6B
compass-active,,EBD7
compass-dot,,EBD6
compass,,EBD5
+copilot-warning,,EC38
+copilot,,EC1E
copy,,EBCC
+coverage,,EC2E
credit-card,,EAC9
dash,,EACC
dashboard,,EACD
@@ -120,10 +128,13 @@ device-mobile,,EADB
diff-added,,EADC
diff-ignored,,EADD
diff-modified,,EADE
+diff-multiple,,EC23
diff-removed,,EADF
diff-renamed,,EAE0
+diff-single,,EC22
diff,,EAE1
discard,,EAE2
+edit-session,,EC36
edit,,EA73
editor-layout,,EAE3
ellipsis,,EA7C
@@ -157,11 +168,13 @@ folder-active,,EAF6
folder-library,,EBDF
folder-opened,,EAF7
folder,,EA83
+game,,EC17
gear,,EAF8
gift,,EAF9
gist-secret,,EAFA
git-commit,,EAFC
git-compare,,EAFD
+git-fetch,,F101
git-merge,,EAFE
git-pull-request-closed,,EBDA
git-pull-request-create,,EBBC
@@ -169,12 +182,18 @@ git-pull-request-draft,,EBDB
git-pull-request-go-to-changes,,EC0B
git-pull-request-new-changes,,EC0C
git-pull-request,,EA64
+git-stash-apply,,EC27
+git-stash-pop,,EC28
+git-stash,,EC26
github-action,,EAFF
github-alt,,EB00
github-inverted,,EBA1
+github-project,,EC2F
github,,EA84
globe,,EB01
+go-to-editing-session,,EC35
go-to-file,,EA94
+go-to-search,,EC32
grabber,,EB02
graph-left,,EBAD
graph-line,,EBE2
@@ -223,6 +242,7 @@ layout-statusbar,,EBF5
layout,,EBEB
library,,EB9C
lightbulb-autofix,,EB13
+lightbulb-sparkle,,EC1F
lightbulb,,EA61
link-external,,EB14
link,,EB15
@@ -241,17 +261,22 @@ magnet,,EBAE
mail-read,,EB1B
mail,,EB1C
map-filled,,EC06
+map-vertical-filled,,EC31
+map-vertical,,EC30
map,,EC05
markdown,,EB1D
megaphone,,EB1E
mention,,EB1F
menu,,EB94
merge,,EBAB
+mic-filled,,EC1C
+mic,,EC12
milestone,,EB20
mirror,,EA69
mortar-board,,EB21
move,,EB22
multiple-windows,,EB23
+music,,EC1B
mute,,EB24
new-file,,EA7F
new-folder,,EA80
@@ -268,8 +293,10 @@ package,,EB29
paintcan,,EB2A
pass-filled,,EBB3
pass,,EBA4
+percentage,,EC33
person-add,,EBCD
person,,EA67
+piano,,EC1A
pie-chart,,EBE4
pin,,EB2B
pinned-dirty,,EBB2
@@ -282,6 +309,7 @@ preview,,EB2F
primitive-square,,EA72
project,,EB30
pulse,,EB31
+python,,EC39
question,,EB32
quote,,EB33
radio-tower,,EB34
@@ -300,6 +328,7 @@ replace-all,,EB3C
replace,,EB3D
reply,,EA7D
repo-clone,,EB3E
+repo-fetch,,EC1D
repo-force-push,,EB3F
repo-forked,,EA63
repo-pull,,EB40
@@ -307,14 +336,17 @@ repo-push,,EB41
repo,,EA62
report,,EB42
request-changes,,EB43
+robot,,EC20
rocket,,EB44
root-folder-opened,,EB45
root-folder,,EB46
rss,,EB47
ruby,,EB48
run-above,,EBBD
+run-all-coverage,,EC2D
run-all,,EB9E
run-below,,EBBE
+run-coverage,,EC2C
run-errors,,EBDE
save-all,,EB49
save-as,,EB4A
@@ -330,12 +362,15 @@ server-process,,EBA2
server,,EB50
settings-gear,,EB51
settings,,EB52
+share,,EC25
shield,,EB53
sign-in,,EA6F
sign-out,,EA6E
smiley,,EB54
+snake,,EC16
sort-precedence,,EB55
source-control,,EA68
+sparkle-filled,,EC21
sparkle,,EC10
split-horizontal,,EB56
split-vertical,,EB57
@@ -344,6 +379,7 @@ star-empty,,EA6A
star-full,,EB59
star-half,,EB5A
stop-circle,,EBA5
+surround-with,,EC24
symbol-array,,EA8A
symbol-boolean,,EA8F
symbol-class,,EB5B
@@ -386,7 +422,9 @@ terminal-ubuntu,,EBC9
terminal,,EA85
text-size,,EB69
three-bars,,EB6A
+thumbsdown-filled,,EC13
thumbsdown,,EB6B
+thumbsup-filled,,EC14
thumbsup,,EB6C
tools,,EB6D
trash,,EA81
@@ -412,6 +450,9 @@ vm-connect,,EBA9
vm-outline,,EB7A
vm-running,,EB7B
vm,,EA7A
+vr,,EC18
+vscode-insiders,,EC2A
+vscode,,EC29
wand,,EBCF
warning,,EA6C
watch,,EB7C
diff --git a/packages/components/assets/codicons/codicon.html b/packages/components/assets/codicons/codicon.html
index 609529d134..d883dd2483 100644
--- a/packages/components/assets/codicons/codicon.html
+++ b/packages/components/assets/codicons/codicon.html
@@ -297,6 +297,14 @@ codicon
arrow-up
+
+
+
+
+
+ attach
+
+
@@ -529,6 +537,14 @@ codicon
chevron-up
+
+
+
+
+
+ chip
+
+
@@ -681,6 +697,22 @@ codicon
cloud
+
+
+
+
+
+ code-oss
+
+
+
+
+
+
+
+ code-review
+
+
@@ -689,6 +721,14 @@ codicon
code
+
+
+
+
+
+ coffee
+
+
@@ -769,6 +809,22 @@ codicon
compass
+
+
+
+
+
+ copilot-warning
+
+
+
+
+
+
+
+ copilot
+
+
@@ -777,6 +833,14 @@ codicon
copy
+
+
+
+
+
+ coverage
+
+
@@ -1121,6 +1185,14 @@ codicon
diff-modified
+
+
+
+
+
+ diff-multiple
+
+
@@ -1137,6 +1209,14 @@ codicon
diff-renamed
+
+
+
+
+
+ diff-single
+
+
@@ -1153,6 +1233,14 @@ codicon
discard
+
+
+
+
+
+ edit-session
+
+
@@ -1417,6 +1505,14 @@ codicon
folder
+
+
+
+
+
+ game
+
+
@@ -1465,6 +1561,14 @@ codicon
git-compare
+
+
+
+
+
+ git-fetch
+
+
@@ -1521,6 +1625,30 @@ codicon
git-pull-request
+
+
+
+
+
+ git-stash-apply
+
+
+
+
+
+
+
+ git-stash-pop
+
+
+
+
+
+
+
+ git-stash
+
+
@@ -1545,6 +1673,14 @@ codicon
github-inverted
+
+
+
+
+
+ github-project
+
+
@@ -1561,6 +1697,14 @@ codicon
globe
+
+
+
+
+
+ go-to-editing-session
+
+
@@ -1569,6 +1713,14 @@ codicon
go-to-file
+
+
+
+
+
+ go-to-search
+
+
@@ -1953,6 +2105,14 @@ codicon
lightbulb-autofix
+
+
+
+
+
+ lightbulb-sparkle
+
+
@@ -2097,6 +2257,22 @@ codicon
map-filled
+
+
+
+
+
+ map-vertical-filled
+
+
+
+
+
+
+
+ map-vertical
+
+
@@ -2145,6 +2321,22 @@ codicon
merge
+
+
+
+
+
+ mic-filled
+
+
+
+
+
+
+
+ mic
+
+
@@ -2185,6 +2377,14 @@ codicon
multiple-windows
+
+
+
+
+
+ music
+
+
@@ -2313,6 +2513,14 @@ codicon
pass
+
+
+
+
+
+ percentage
+
+
@@ -2329,6 +2537,14 @@ codicon
person
+
+
+
+
+
+ piano
+
+
@@ -2425,6 +2641,14 @@ codicon
pulse
+
+
+
+
+
+ python
+
+
@@ -2569,6 +2793,14 @@ codicon
repo-clone
+
+
+
+
+
+ repo-fetch
+
+
@@ -2625,6 +2857,14 @@ codicon
request-changes
+
+
+
+
+
+ robot
+
+
@@ -2673,6 +2913,14 @@ codicon
run-above
+
+
+
+
+
+ run-all-coverage
+
+
@@ -2689,6 +2937,14 @@ codicon
run-below
+
+
+
+
+
+ run-coverage
+
+
@@ -2809,6 +3065,14 @@ codicon
settings
+
+
+
+
+
+ share
+
+
@@ -2841,6 +3105,14 @@ codicon
smiley
+
+
+
+
+
+ snake
+
+
@@ -2857,6 +3129,14 @@ codicon
source-control
+
+
+
+
+
+ sparkle-filled
+
+
@@ -2921,6 +3201,14 @@ codicon
stop-circle
+
+
+
+
+
+ surround-with
+
+
@@ -3257,6 +3545,14 @@ codicon
three-bars
+
+
+
+
+
+ thumbsdown-filled
+
+
@@ -3265,6 +3561,14 @@ codicon
thumbsdown
+
+
+
+
+
+ thumbsup-filled
+
+
@@ -3465,6 +3769,30 @@ codicon
vm
+
+
+
+
+
+ vr
+
+
+
+
+
+
+
+ vscode-insiders
+
+
+
+
+
+
+
+ vscode
+
+
diff --git a/packages/components/assets/codicons/codicon.svg b/packages/components/assets/codicons/codicon.svg
index 7f1b6ec25a..141bbdd3ae 100644
--- a/packages/components/assets/codicons/codicon.svg
+++ b/packages/components/assets/codicons/codicon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/packages/components/assets/codicons/codicon.ttf b/packages/components/assets/codicons/codicon.ttf
index ea2309d11d..4a4d15cc2d 100644
Binary files a/packages/components/assets/codicons/codicon.ttf and b/packages/components/assets/codicons/codicon.ttf differ
diff --git a/packages/components/declare.d.ts b/packages/components/declare.d.ts
deleted file mode 100644
index 7ab302dc87..0000000000
--- a/packages/components/declare.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-declare module 'color-rgba' {
- const rgba: (value: string) => [number, number, number, number];
- export = rgba;
-}
diff --git a/packages/components/package.json b/packages/components/package.json
index 8a7b43113e..218a3b813b 100644
--- a/packages/components/package.json
+++ b/packages/components/package.json
@@ -1,12 +1,12 @@
{
"name": "@public-ui/components",
- "version": "2.0.14",
+ "version": "3.0.0-rc.2",
"license": "EUPL-1.2",
"homepage": "https://public-ui.github.io",
"repository": {
- "type": "git",
- "url": "https://github.com/public-ui/kolibri"
- },
+ "type": "git",
+ "url": "https://github.com/public-ui/kolibri"
+ },
"bugs": {
"url": "https://github.com/public-ui/kolibri/issues",
"email": "kolibri@itzbund.de"
@@ -56,67 +56,79 @@
"scripts": {
"build": "npm run build:light",
"build:deps": "pnpm --filter @public-ui/components^... build",
- "build:light": "npm run clear && mkdir doc && cross-env NODE_ENV=production stencil build --docs --prod && node scripts/hashing.js && node scripts/autogen.doc.js && node scripts/vaadin.js && npm run format -- -w",
- "clear": "rimraf -g dist doc loader www ../adapters/angular/v11/src ../adapters/angular/v12/src ../adapters/angular/v13/src ../adapters/angular/v14/src ../adapters/angular/v15/src ../adapters/angular/v16/src ../adapters/angular/v17/src ../adapters/hydrate/dist ../adapters/react/src ../adapters/solid/src ../adapters/vaadin/*.java ../adapters/vue/src",
+ "build:light": "npm run clear && mkdir doc && cross-env NODE_ENV=production stencil build --docs --prod && node scripts/autogen.doc.js && node scripts/vaadin.js && npm run format -- -w",
+ "clear": "rimraf -g dist doc loader www ../adapters/angular/v15/src ../adapters/angular/v16/src ../adapters/angular/v17/src ../adapters/angular/v18/src ../adapters/hydrate/dist ../adapters/react/src ../adapters/solid/src ../adapters/vaadin/*.java ../adapters/vue/src",
"format": "prettier --check src",
"lighthouse": "lighthouse --chrome-flags=\"--headless\" --output-path lighthouse.report.html --preset=desktop --quiet",
"lint": "tsc --noemit && eslint src",
- "start": "cross-env NODE_ENV=development stencil build --dev --serve --watch --no-open",
"dev": "cross-env NODE_ENV=development stencil build --prod --watch",
- "test": "cross-env NODE_ENV=test stencil test --spec --json --outputFile dist/jest-test-results.json",
+ "test": "pnpm test:unit",
+ "test:unit": "cross-env NODE_ENV=test stencil test --spec --json --outputFile dist/jest-test-results.json",
"test:watch": "cross-env NODE_ENV=test stencil test --spec --watchAll",
+ "test:e2e": "cross-env E2E=1 playwright test",
+ "postinstall": "pnpm exec playwright install",
"postpack": "mv package.bak.json package.json",
"prepack": "npm run build && cp package.json package.bak.json && rimraf dist/collection dist/kolibri/assets/@leanup dist/types/assets/@leanup && node scripts/anonymous.js && node scripts/minify.js",
"xunused": "knip"
},
"dependencies": {
- "@floating-ui/dom": "1.6.3",
- "@public-ui/schema": "2.0.14",
- "adopted-style-sheets": "1.1.4",
- "markdown-it": "14.1.0"
+ "@floating-ui/dom": "1.6.13",
+ "adopted-style-sheets": "1.1.7",
+ "clsx": "2.1.1",
+ "color-convert": "2.0.1",
+ "color-rgba": "2.4.0",
+ "lodash-es": "4.17.21",
+ "markdown-it": "14.1.0",
+ "query-selector-all-shadow-root": "0.0.3",
+ "query-selector-shadow-root": "0.0.3",
+ "rgba-convert": "0.3.0",
+ "wcag-contrast": "3.0.0"
},
"devDependencies": {
+ "@playwright/test": "1.50.0",
"@public-ui/stencil-angular-output-target": "0.9.0",
"@public-ui/stencil-react-output-target": "0.6.0",
"@public-ui/stencil-solid-output-target": "0.2.0",
"@public-ui/stencil-vue-output-target": "0.9.0",
- "@stencil/core": "4.15.0",
- "@stencil/postcss": "2.1.0",
- "@stencil/sass": "3.0.11",
+ "@stencil-community/eslint-plugin": "0.9.0",
+ "@stencil-community/postcss": "2.2.0",
+ "@stencil/core": "4.20.0",
+ "@stencil/playwright": "0.2.1",
+ "@stencil/sass": "3.0.12",
+ "@types/color-convert": "2.0.4",
"@types/jest": "26.0.24",
- "@types/markdown-it": "13.0.7",
+ "@types/lodash-es": "4.17.12",
+ "@types/markdown-it": "14.1.2",
"@types/mustache": "4.2.5",
- "@types/node": "ts5.4",
"@types/pug": "2.0.10",
"@types/twig": "1.12.16",
- "@typescript-eslint/eslint-plugin": "7.6.0",
- "@typescript-eslint/parser": "7.6.0",
- "autoprefixer": "10.4.19",
- "clsx": "2.1.0",
- "color-rgba": "2.4.0",
+ "@types/wcag-contrast": "3.0.3",
+ "@typescript-eslint/eslint-plugin": "7.18.0",
+ "@typescript-eslint/parser": "7.18.0",
+ "autoprefixer": "10.4.20",
"cross-env": "7.0.3",
- "cssnano": "6.1.2",
- "eslint": "8.57.0",
- "eslint-plugin-html": "8.1.0",
- "eslint-plugin-jsdoc": "48.2.3",
- "eslint-plugin-json": "3.1.0",
- "eslint-plugin-jsx-a11y": "6.8.0",
- "eslint-plugin-no-loops": "0.3.0",
- "eslint-plugin-react": "7.34.1",
+ "cssnano": "7.0.6",
+ "eslint": "8.57.1",
+ "eslint-plugin-html": "8.1.2",
+ "eslint-plugin-jsdoc": "50.6.3",
+ "eslint-plugin-jsx-a11y": "6.10.2",
+ "eslint-plugin-react": "7.37.4",
"jest": "26.6.3",
- "knip": "5.9.4",
- "lighthouse": "11.7.1",
+ "knip": "5.43.6",
+ "lighthouse": "12.3.0",
"mustache": "4.2.0",
- "postcss": "8.4.38",
- "postcss-sorting": "8.0.2",
- "prettier": "3.2.5",
- "pug": "3.0.2",
- "rimraf": "5.0.5",
+ "postcss": "8.5.1",
+ "postcss-sorting": "9.1.0",
+ "prettier": "3.4.2",
+ "pug": "3.0.3",
+ "rimraf": "6.0.1",
"stencil-awesome-test": "1.0.6",
- "terser": "5.30.3",
- "tslib": "2.6.2",
+ "terser": "5.37.0",
"twig": "1.17.1",
- "typescript": "5.4.5"
+ "typescript": "5.7.3"
+ },
+ "peerDependencies": {
+ "adopted-style-sheets": "1.1.7"
},
"files": [
"assets",
diff --git a/packages/components/playwright.config.ts b/packages/components/playwright.config.ts
new file mode 100644
index 0000000000..84debd5bc0
--- /dev/null
+++ b/packages/components/playwright.config.ts
@@ -0,0 +1,43 @@
+import { devices, expect } from '@playwright/test';
+import { createConfig, matchers } from '@stencil/playwright';
+
+expect.extend(matchers);
+
+const TEST_PORT = '3333';
+const TEST_URL = `http://localhost:${TEST_PORT}`;
+
+/* See https://playwright.dev/docs/test-configuration */
+export default createConfig({
+ testMatch: /.*\.e2e\.ts$/,
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: [['html', { open: 'never' }]],
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+ ],
+ use: {
+ baseURL: TEST_URL,
+ timezoneId: 'Europe/Berlin',
+ screenshot: 'only-on-failure',
+ trace: 'retain-on-failure',
+ },
+ webServer: {
+ url: TEST_URL,
+ reuseExistingServer: false,
+ /* The builtin Stencil server sometimes fails to serve some assets which leads to intermittent test failures. Use a more stable server (without watcher) for CI: */
+ ...(process.env.CI ? { command: `stencil build --dev && mv dist-e2e/kolibri dist-e2e/build && npx serve dist-e2e -p ${TEST_PORT} -L` } : {}),
+ },
+});
diff --git a/packages/components/scripts/anonymous.js b/packages/components/scripts/anonymous.js
index c5194acada..a7ebc39d13 100644
--- a/packages/components/scripts/anonymous.js
+++ b/packages/components/scripts/anonymous.js
@@ -4,14 +4,15 @@ const prettier = require('prettier');
packageJson = JSON.parse(packageJson);
-delete packageJson.dependencies;
+// delete packageJson.dependencies;
delete packageJson.devDependencies;
+// delete packageJson.peerDependencies;
delete packageJson.scripts;
delete packageJson.husky;
delete packageJson['lint-staged'];
delete packageJson.collection;
delete packageJson['collection:main'];
-delete packageJson.repository;
+// delete packageJson.repository;
// delete packageJson.publishConfig;
delete packageJson.unpkg;
// packageJson.files.push('docs/.vitepress/dist/');
diff --git a/packages/components/scripts/vaadin.js b/packages/components/scripts/vaadin.js
index ace2d5663a..16edd3ffaa 100644
--- a/packages/components/scripts/vaadin.js
+++ b/packages/components/scripts/vaadin.js
@@ -54,8 +54,6 @@ const javaType = (type, required) => {
const BLACKLIST = [
'kol-alert-wc',
'kol-avatar-wc',
- 'kol-button-group',
- 'kol-button-group-wc',
'kol-color',
'kol-counter',
'kol-heading-wc',
@@ -63,7 +61,6 @@ const BLACKLIST = [
'kol-icon-icofont',
'kol-input-adapter-leanup',
'kol-input-radio-group',
- 'kol-link-group',
'kol-span',
'kol-span-wc',
];
diff --git a/packages/components/src/assets/@leanup/forms/bundle.js b/packages/components/src/assets/@leanup/forms/bundle.js
deleted file mode 100644
index 75f3c4eae4..0000000000
--- a/packages/components/src/assets/@leanup/forms/bundle.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(n,w){typeof exports=="object"&&typeof module!="undefined"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(n=typeof globalThis!="undefined"?globalThis:n||self,w(n.LeanUpForm={}))})(this,function(n){"use strict";var w=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},f={exports:{}};(function(r){(function(e,t){r.exports?r.exports=t():e.log=t()})(w,function(){var e=function(){},t="undefined",s=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),o=["trace","debug","info","warn","error"];function E(a,d){var h=a[d];if(typeof h.bind=="function")return h.bind(a);try{return Function.prototype.bind.call(h,a)}catch(l){return function(){return Function.prototype.apply.apply(h,[a,arguments])}}}function te(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function re(a){return a==="debug"&&(a="log"),typeof console===t?!1:a==="trace"&&s?te:console[a]!==void 0?E(console,a):console.log!==void 0?E(console,"log"):e}function k(a,d){for(var h=0;h=0&&i<=l.levels.SILENT){if(B=i,m!==!1&&oe(i),k.call(l,i,a),typeof console===t&&i=t}static isObject(e){return typeof e=="object"&&e!==null&&this.isArray(e)===!1}static isString(e,t=0){return typeof e=="string"&&e.length>=t}}const O=[];function W(){return"$$NODE_ENV$$"}class g{constructor(){}static log(e,t){switch(y.isObject(t.refObject)&&typeof t.refObject.constructor=="function"&&y.isString(t.refObject.constructor.name)&&(t.className=`[${t.refObject.constructor.name}]:`),O.push({date:new Date().toUTCString(),level:e,message:t}),e){case"trace":f.exports.trace(t);break;case"debug":f.exports.debug(t);break;case"info":f.exports.info(t);break;case"warn":f.exports.warn(t);break;case"error":f.exports.error(t)}}static trace(e,t){return this.log("trace",{messageText:e,refObject:t}),this}static debug(e,t){return this.log("debug",{messageText:e,refObject:t}),this}static info(e,t){return this.log("info",{messageText:e,refObject:t}),this}static warn(e,t){return this.log("warn",{messageText:e,refObject:t}),this}static error(e,t){return this.log("error",{messageText:e,refObject:t}),this}static get cache(){return[].concat(O)}}switch(g._instance=null,W()){case"development":f.exports.setDefaultLevel("trace");break;case"test":f.exports.setDefaultLevel("warn");break;case"production":f.exports.setDefaultLevel("error")}function Z(r,e){return y.isArray(r)?r.find(t=>e instanceof t)!==void 0:!1}function R(r){return r instanceof b?r.get():Array.isArray(r)?r:[r]}class b{constructor(e){this._instancesOf=[],this._items=[],this._protectedItems=[],this._instancesOf=Array.isArray(e)?e:[e]}get empty(){return this._items.length===0}get first(){return this._items.length>0?this._items[0]:null}forEach(e){this._items.forEach(e)}filter(e){return this._items.filter(e)}find(e){return this._items.find(e)}get last(){return this._items.length>0?this._items[this._items.length-1]:null}get length(){return this._items.length}add(e,t=!1){return R(e).filter(s=>{let o=!1;return this.contains(s)===!1?Z(this._instancesOf,s)?(t&&this._protectedItems.push(s),this._items.push(s),o=!0):g.debug("The item does not have a valid instance type.",this):g.debug("The item is already in the list.",this),o}).length>0}remove(e){return R(e).filter(t=>{let s=!1,o=this._protectedItems.indexOf(t);return o===-1?(o=this._items.indexOf(t),o>=0?(this._items.splice(o,1),s=!0):g.debug("The item is not in the list.",this)):g.debug("The item is protected and cannot be removed.",this),s}).length>0}set(e,t=!1){const s=this.clear(),o=this.add(e,t);return s||o}get(e){return isNaN(e)===!1&&typeof e=="number"?this._items.slice(0,e):this._items}clear(){const e=this._items.length;return this._items=this._items.filter(t=>this._protectedItems.indexOf(t)>=0),e!==this._items.length}contains(e){return this._items.indexOf(e)>-1}}class V{}class N{constructor(){this.formatters=new b(V)}format(e){return this.formatters.forEach(t=>{e=t.format(e)}),e}parse(e){return this.formatters.forEach(t=>{e=t.parse(e)}),e}}class v{constructor(e){this.state={message:"Ein unbekannter Fehler ist aufgetreten."},this.message=e}set message(e){y.isString(e,1)?this.state.message=e:g.debug("")}get message(){return this.state.message}}class S{constructor(){this.validators=new b(v)}validate(e,t=!1){const s=[];try{this.validators.forEach(o=>{if(o.isValid(e)===!1&&(s.push(o.message),t===!0))throw new Error("Only one error is enough. Be quick and stop the execution of other validation functions.")})}catch(o){}return s}}class F{constructor(e){this.changeListeners=new b(Function),this._errors=new Set,this._parentForms=[],this._name="unnamed",this._validationHandler=new S,this._notifyTimeout=setTimeout(()=>{},0),this.name=e}get name(){return this._name}set name(e){if(typeof e=="string")if(e.length>0)this._name=e;else throw new Error("The name of a control must have a min-length of 1.");else throw new Error("The name of a control must be a string.")}get error(){return this._errors.size>0?this._errors.values().next().value:null}getErrors(){return this._errors}get id(){let e=this.name;return this._parentForms.length>0&&(e=`${this._parentForms[0].id}_${e}`),e}get valid(){return this._errors.size===0}es5isValid(){return this._errors.size===0}findMeInParentForm(e){if(this===e)return!0;if(e instanceof p){const t=[];return this._parentForms.forEach(s=>{s.findMeInParentForm(e)===!0&&t.push(s)}),t.length>0}else return!1}addParentForm(e){if(this._parentForms.includes(e)===!1)if(e.findMeInParentForm(this)===!1)this._parentForms.push(e);else throw new Error(`The same form control (${e.name}) leads to a form control loop.`);else throw new Error(`An form control with the name '${e.name}' already exists.`)}removeParentForm(e){const t=this._parentForms.indexOf(e);if(t>=0)this._parentForms.splice(t,1);else throw new Error(`An form control with the name '${e.name}' does not exists.`)}setValidationHandler(e,t=null){this._validationHandler=e,this.validate(t)}validate(e){this._errors.clear(),this._validationHandler.validate(e).forEach(s=>{this._errors.add(s)}),this._parentForms.forEach(s=>{s.validate(e)})}notify(){this._notifyTimeout&&clearTimeout(this._notifyTimeout),this._notifyTimeout=setTimeout(()=>{this.changeListeners.forEach(e=>{e()})},0)}}n.InputControlTypes=void 0,function(r){r.checkbox="checkbox",r.date="date",r.email="email",r.number="number",r.password="password",r.radio="radio",r.select="select",r.slider="slider",r.text="text"}(n.InputControlTypes||(n.InputControlTypes={}));class T extends F{constructor(e,t){super(e);this._disabled=!1,this._info="",this._label="",this._mandatory=!1,this._placeholder="",this._readonly=!1,this._type="text",this._value=null,this._oldValue=null,this._valueTimeout=setTimeout(()=>{},0),this._formatHandler=new N,t&&(this.info=t.info?t.info:"",this.label=t.label?t.label:"",this.disabled=t.disabled?t.disabled:!1,this.mandatory=t.mandatory?t.mandatory:!1,this.readonly=t.readonly?t.readonly:!1,this.placeholder=t.placeholder?t.placeholder:"",this.type=t.type?t.type:"text",this.value=t.value?t.value:null)}get info(){return this._info}set info(e){if(typeof e=="string")this._info=e,this.notify();else throw new Error("The info of a input control must be a string.")}get disabled(){return this._disabled}set disabled(e){if(typeof e=="boolean")this._disabled=e,this.notify();else throw new Error("The disabled flag of a input control must be a string.")}get mandatory(){return this._mandatory}set mandatory(e){if(typeof e=="boolean")this._mandatory=e,this.notify();else throw new Error("The mandatory flag of a input control must be a string.")}get readonly(){return this._readonly}set readonly(e){if(typeof e=="boolean")this._readonly=e,this.notify();else throw new Error("The readonly flag of a input control must be a string.")}get label(){return this._label}set label(e){if(typeof e=="string")this._label=e,this.notify();else throw new Error("The label of a input control must be a string.")}get placeholder(){return this._placeholder}set placeholder(e){if(typeof e=="string")this._placeholder=e,this.notify();else throw new Error("The placeholder of a input control must be a string.")}get type(){return this._type.toString()}set type(e){if(typeof e=="string")switch(e){case"checkbox":case"date":case"email":case"number":case"password":case"radio":case"select":case"slider":case"text":this._type=e,this.notify();break;default:throw new Error("The type of a input control must be a of the following types: ???.")}else throw new Error("The type of a input control must be a string.")}get oldValue(){return this._oldValue}get value(){return this._value}set value(e){this._valueTimeout&&clearTimeout(this._valueTimeout),this._valueTimeout=setTimeout(()=>{this.validate(e),this._oldValue=this._value,this._value=e,this.notify()},0)}get modelValue(){return this.value}set modelValue(e){this.value=e}get viewValue(){return this._formatHandler.format(this.modelValue)}set viewValue(e){this.modelValue=this._formatHandler.parse(e)}setValidationHandler(e){super.setValidationHandler(e,this.value)}setFormatHandler(e){this._formatHandler=e}}class p extends F{constructor(){super(...arguments);this.controls=new b([p,T])}get disabled(){return this.controls.filter(e=>e.disabled===!1).length===0}set disabled(e){this.controls.forEach(t=>{t.disabled=e})}get readonly(){return this.controls.filter(e=>e.readonly===!1).length===0}set readonly(e){this.controls.forEach(t=>{t.readonly=e})}get valid(){return this.es5isValid()&&this.controls.filter(e=>e.valid===!1).length===0}addConrol(e){if(this.controls.contains(e)===!1)e.addParentForm(this),this.controls.add(e);else throw new Error(`A control with the same name '${e.name}' already exists.`)}removeControl(e){if(this.controls.contains(e)===!0)e instanceof F&&(e.removeParentForm(this),this.controls.remove(e));else throw new Error(`A control with the name '${e.name}' does not exists.`)}getControls(){return this.controls.get()}getControl(e){return this.controls.find(t=>t.name===e)}setData(e){console.log("FormControl.setData is currently not implemented.")}getData(){const e={};return this.controls.forEach(t=>{if(t instanceof p)e[t.name]=t.getData();else if(t instanceof T)e[t.name]=t.value;else throw new Error("The control is neither an instance of FormControl or InputControl.")}),e}setValidationHandler(e){super.setValidationHandler(e)}}class I{static createForm(e,t){const s=new p(e);for(const o in t)if(t.hasOwnProperty(o))if(typeof t[o]=="object"&&t[o]!==null)s.addConrol(I.createForm(o,t[o]));else{const E=new T(o);E.value=t[o],s.addConrol(E)}return s}}class C extends V{constructor(){super(...arguments);this.regExp=/([A-Z0-9]{1,4})/gi}format(e){if(typeof e=="string"){const t=e.match(this.regExp);if(Array.isArray(t))return t==null?void 0:t.join(" ")}return e}parse(e){return typeof e=="string"?e.replace(/ /g,""):e}}const q=new C;class M extends v{constructor(e="Bitte tragen Sie einen Wert ein."){super(e)}isValid(e){return e!=null&&e.toString().length>0}}const P=new M;class _ extends v{isValid(e){return P.isValid(e)===!1||this.validate(e)}}class A extends _{constructor(e,t="Bitte tragen Sie einen g\xFCltigen Wert ein."){super(t);this._regExp=/^/g,this.regExp=e}set regExp(e){e instanceof RegExp?this._regExp=e:g.debug("The regExp of the pattern validator should be type of RegExp.")}get regExp(){return this._regExp}validate(e){return this.regExp.test(e)}}class j extends A{validate(e){return super.validate(e)===!1}}const H=/^\d+$/;class U extends A{constructor(e="Der Wert ist keine Zahl."){super(H,e)}}const X=new U,$=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;class Q extends A{constructor(e="Die E-Mail-Adresse hat nicht das richtige Format."){super($,e)}}class K extends _{constructor(e="Bitte best\xE4tigen Sie."){super(e)}validate(e){return e===!0}}class Y extends _{constructor(e,t=`Die Eingabe darf nicht l\xE4nger als ${e} Zeichen sein.`){super(t);this.maxLength=e}validate(e){return y.isString(e)&&e.length<=this.maxLength}}class J extends _{constructor(e,t=`Die Eingabe darf nicht k\xFCrzer als ${e} Zeichen sein.`){super(t);this.minLength=e}validate(e){return y.isString(e)&&e.length>=this.minLength}}class ee extends _{constructor(e,t){super(t);this.validator=e}validate(e){return this.validator.isValid(e)===!1}}n.AbstractFormatter=V,n.AbstractValidator=v,n.DEFAULT_DIGITS_VALIDATOR=X,n.DEFAULT_IBAN_FORMATTER=q,n.DEFAULT_REQUIRED_VALIDATOR=P,n.DIGITS_VALIDATION_REGEXP=H,n.DigitsValidator=U,n.EMAIL_VALIDATION_REGEXP=$,n.EmailValidator=Q,n.FormControl=p,n.FormFactory=I,n.FormatHandler=N,n.IbanFormatter=C,n.InputControl=T,n.IsTrueValidator=K,n.MaxLengthValidator=Y,n.MinLengthValidator=J,n.NonRequiredValidator=_,n.NotPatternValidator=j,n.NotValidator=ee,n.PatternValidator=A,n.RequiredValidator=M,n.ValidationHandler=S,Object.defineProperty(n,"__esModule",{value:!0})});
-//# sourceMappingURL=bundle.js.map
diff --git a/packages/components/src/assets/@leanup/forms/bundle.js.map b/packages/components/src/assets/@leanup/forms/bundle.js.map
deleted file mode 100644
index 019524a029..0000000000
--- a/packages/components/src/assets/@leanup/forms/bundle.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"bundle.js","sources":["../node_modules/loglevel/lib/loglevel.js","../node_modules/@leanup/lib/helpers/validator.js","../node_modules/@leanup/lib/helpers/log.js","../node_modules/@leanup/lib/pattern/list-of.js","../src/handlers/formatters/abstract.formatter.ts","../src/handlers/format.handler.ts","../src/handlers/validators/abstract.validator.ts","../src/handlers/validation.handler.ts","../src/controls/controls.ts","../src/handlers/formatters/iban.formatter.ts","../src/handlers/validators/required.validator.ts","../src/handlers/validators/non-required.validator.ts","../src/handlers/validators/pattern.validator.ts","../src/handlers/validators/digits.validator.ts","../src/handlers/validators/email.validator.ts","../src/handlers/validators/is-true.validator.ts","../src/handlers/validators/max-length.validator.ts","../src/handlers/validators/min-length.validator.ts","../src/handlers/validators/not.validator.ts"],"sourcesContent":["/*\n* loglevel - https://github.com/pimterry/loglevel\n*\n* Copyright (c) 2013 Tim Perry\n* Licensed under the MIT license.\n*/\n(function (root, definition) {\n \"use strict\";\n if (typeof define === 'function' && define.amd) {\n define(definition);\n } else if (typeof module === 'object' && module.exports) {\n module.exports = definition();\n } else {\n root.log = definition();\n }\n}(this, function () {\n \"use strict\";\n\n // Slightly dubious tricks to cut down minimized file size\n var noop = function() {};\n var undefinedType = \"undefined\";\n var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (\n /Trident\\/|MSIE /.test(window.navigator.userAgent)\n );\n\n var logMethods = [\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\"\n ];\n\n // Cross-browser bind equivalent that works at least back to IE6\n function bindMethod(obj, methodName) {\n var method = obj[methodName];\n if (typeof method.bind === 'function') {\n return method.bind(obj);\n } else {\n try {\n return Function.prototype.bind.call(method, obj);\n } catch (e) {\n // Missing bind shim or IE8 + Modernizr, fallback to wrapping\n return function() {\n return Function.prototype.apply.apply(method, [obj, arguments]);\n };\n }\n }\n }\n\n // Trace() doesn't print the message in IE, so for that case we need to wrap it\n function traceForIE() {\n if (console.log) {\n if (console.log.apply) {\n console.log.apply(console, arguments);\n } else {\n // In old IE, native console methods themselves don't have apply().\n Function.prototype.apply.apply(console.log, [console, arguments]);\n }\n }\n if (console.trace) console.trace();\n }\n\n // Build the best logging method possible for this env\n // Wherever possible we want to bind, not wrap, to preserve stack traces\n function realMethod(methodName) {\n if (methodName === 'debug') {\n methodName = 'log';\n }\n\n if (typeof console === undefinedType) {\n return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives\n } else if (methodName === 'trace' && isIE) {\n return traceForIE;\n } else if (console[methodName] !== undefined) {\n return bindMethod(console, methodName);\n } else if (console.log !== undefined) {\n return bindMethod(console, 'log');\n } else {\n return noop;\n }\n }\n\n // These private functions always need `this` to be set properly\n\n function replaceLoggingMethods(level, loggerName) {\n /*jshint validthis:true */\n for (var i = 0; i < logMethods.length; i++) {\n var methodName = logMethods[i];\n this[methodName] = (i < level) ?\n noop :\n this.methodFactory(methodName, level, loggerName);\n }\n\n // Define log.log as an alias for log.debug\n this.log = this.debug;\n }\n\n // In old IE versions, the console isn't present until you first open it.\n // We build realMethod() replacements here that regenerate logging methods\n function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {\n return function () {\n if (typeof console !== undefinedType) {\n replaceLoggingMethods.call(this, level, loggerName);\n this[methodName].apply(this, arguments);\n }\n };\n }\n\n // By default, we use closely bound real methods wherever possible, and\n // otherwise we wait for a console to appear, and then try again.\n function defaultMethodFactory(methodName, level, loggerName) {\n /*jshint validthis:true */\n return realMethod(methodName) ||\n enableLoggingWhenConsoleArrives.apply(this, arguments);\n }\n\n function Logger(name, defaultLevel, factory) {\n var self = this;\n var currentLevel;\n\n var storageKey = \"loglevel\";\n if (typeof name === \"string\") {\n storageKey += \":\" + name;\n } else if (typeof name === \"symbol\") {\n storageKey = undefined;\n }\n\n function persistLevelIfPossible(levelNum) {\n var levelName = (logMethods[levelNum] || 'silent').toUpperCase();\n\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage[storageKey] = levelName;\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=\" + levelName + \";\";\n } catch (ignore) {}\n }\n\n function getPersistedLevel() {\n var storedLevel;\n\n if (typeof window === undefinedType || !storageKey) return;\n\n try {\n storedLevel = window.localStorage[storageKey];\n } catch (ignore) {}\n\n // Fallback to cookies if local storage gives us nothing\n if (typeof storedLevel === undefinedType) {\n try {\n var cookie = window.document.cookie;\n var location = cookie.indexOf(\n encodeURIComponent(storageKey) + \"=\");\n if (location !== -1) {\n storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];\n }\n } catch (ignore) {}\n }\n\n // If the stored level is not valid, treat it as if nothing was stored.\n if (self.levels[storedLevel] === undefined) {\n storedLevel = undefined;\n }\n\n return storedLevel;\n }\n\n /*\n *\n * Public logger API - see https://github.com/pimterry/loglevel for details\n *\n */\n\n self.name = name;\n\n self.levels = { \"TRACE\": 0, \"DEBUG\": 1, \"INFO\": 2, \"WARN\": 3,\n \"ERROR\": 4, \"SILENT\": 5};\n\n self.methodFactory = factory || defaultMethodFactory;\n\n self.getLevel = function () {\n return currentLevel;\n };\n\n self.setLevel = function (level, persist) {\n if (typeof level === \"string\" && self.levels[level.toUpperCase()] !== undefined) {\n level = self.levels[level.toUpperCase()];\n }\n if (typeof level === \"number\" && level >= 0 && level <= self.levels.SILENT) {\n currentLevel = level;\n if (persist !== false) { // defaults to true\n persistLevelIfPossible(level);\n }\n replaceLoggingMethods.call(self, level, name);\n if (typeof console === undefinedType && level < self.levels.SILENT) {\n return \"No console available for logging\";\n }\n } else {\n throw \"log.setLevel() called with invalid level: \" + level;\n }\n };\n\n self.setDefaultLevel = function (level) {\n if (!getPersistedLevel()) {\n self.setLevel(level, false);\n }\n };\n\n self.enableAll = function(persist) {\n self.setLevel(self.levels.TRACE, persist);\n };\n\n self.disableAll = function(persist) {\n self.setLevel(self.levels.SILENT, persist);\n };\n\n // Initialize with the right level\n var initialLevel = getPersistedLevel();\n if (initialLevel == null) {\n initialLevel = defaultLevel == null ? \"WARN\" : defaultLevel;\n }\n self.setLevel(initialLevel, false);\n }\n\n /*\n *\n * Top-level API\n *\n */\n\n var defaultLogger = new Logger();\n\n var _loggersByName = {};\n defaultLogger.getLogger = function getLogger(name) {\n if ((typeof name !== \"symbol\" && typeof name !== \"string\") || name === \"\") {\n throw new TypeError(\"You must supply a name when creating a logger.\");\n }\n\n var logger = _loggersByName[name];\n if (!logger) {\n logger = _loggersByName[name] = new Logger(\n name, defaultLogger.getLevel(), defaultLogger.methodFactory);\n }\n return logger;\n };\n\n // Grab the current global log variable in case of overwrite\n var _log = (typeof window !== undefinedType) ? window.log : undefined;\n defaultLogger.noConflict = function() {\n if (typeof window !== undefinedType &&\n window.log === defaultLogger) {\n window.log = _log;\n }\n\n return defaultLogger;\n };\n\n defaultLogger.getLoggers = function getLoggers() {\n return _loggersByName;\n };\n\n // ES6 default export, for compatibility\n defaultLogger['default'] = defaultLogger;\n\n return defaultLogger;\n}));\n","export class Validator {\n constructor() { }\n static isNumber(any) {\n return isNaN(any) === false && typeof any === 'number';\n }\n static isArray(any, minLength = 0) {\n return Array.isArray(any) && any.length >= minLength;\n }\n static isObject(any) {\n return typeof any === 'object' && any !== null && this.isArray(any) === false;\n }\n static isString(any, minLength = 0) {\n return typeof any === 'string' && any.length >= minLength;\n }\n}\n//# sourceMappingURL=validator.js.map","import * as log from 'loglevel';\nimport { Validator } from './validator';\nconst LOG_CACHE = [];\nfunction getEnvironment() {\n return '$$NODE_ENV$$';\n}\nexport class Log {\n constructor() { }\n static log(level, message) {\n if (Validator.isObject(message.refObject) &&\n typeof message.refObject.constructor === 'function' &&\n Validator.isString(message.refObject.constructor.name)) {\n message.className = `[${message.refObject.constructor.name}]:`;\n }\n LOG_CACHE.push({\n date: new Date().toUTCString(),\n level,\n message,\n });\n switch (level) {\n case 'trace':\n log.trace(message);\n break;\n case 'debug':\n log.debug(message);\n break;\n case 'info':\n log.info(message);\n break;\n case 'warn':\n log.warn(message);\n break;\n case 'error':\n log.error(message);\n }\n if (getEnvironment() === 'development' && level === 'error') {\n throw new Error(`Execution in development mode was canceled. See the error log above.`);\n }\n }\n static trace(messageText, refObject) {\n this.log('trace', { messageText, refObject });\n return this;\n }\n static debug(messageText, refObject) {\n this.log('debug', { messageText, refObject });\n return this;\n }\n static info(messageText, refObject) {\n this.log('info', { messageText, refObject });\n return this;\n }\n static warn(messageText, refObject) {\n this.log('warn', { messageText, refObject });\n return this;\n }\n static error(messageText, refObject) {\n this.log('error', { messageText, refObject });\n return this;\n }\n static get cache() {\n return [].concat(LOG_CACHE);\n }\n}\nLog._instance = null;\nswitch (getEnvironment()) {\n case 'development':\n log.setDefaultLevel('trace');\n break;\n case 'test':\n log.setDefaultLevel('warn');\n break;\n case 'production':\n log.setDefaultLevel('error');\n}\n//# sourceMappingURL=log.js.map","import { Log } from '../helpers/log';\nimport { Validator } from '../helpers/validator';\nfunction isInstanceOf(instancesOf, item) {\n if (Validator.isArray(instancesOf)) {\n return (instancesOf.find((instanceOf) => {\n return item instanceof instanceOf;\n }) !== undefined);\n }\n return false;\n}\nfunction normalizeListOfItems(items) {\n return (items instanceof ListOf ? items.get() : Array.isArray(items) ? items : [items]);\n}\nexport class ListOf {\n constructor(instancesOf) {\n this._instancesOf = [];\n this._items = [];\n this._protectedItems = [];\n this._instancesOf = (Array.isArray(instancesOf) ? instancesOf : [instancesOf]);\n }\n get empty() {\n return this._items.length === 0;\n }\n get first() {\n if (this._items.length > 0) {\n return this._items[0];\n }\n else {\n return null;\n }\n }\n forEach(action) {\n this._items.forEach(action);\n }\n filter(action) {\n return this._items.filter(action);\n }\n find(action) {\n return this._items.find(action);\n }\n get last() {\n if (this._items.length > 0) {\n return this._items[this._items.length - 1];\n }\n else {\n return null;\n }\n }\n get length() {\n return this._items.length;\n }\n add(items, protect = false) {\n return (normalizeListOfItems(items).filter((item) => {\n let changed = false;\n if (this.contains(item) === false) {\n if (isInstanceOf(this._instancesOf, item)) {\n if (protect) {\n this._protectedItems.push(item);\n }\n this._items.push(item);\n changed = true;\n }\n else {\n Log.debug(`The item does not have a valid instance type.`, this);\n }\n }\n else {\n Log.debug(`The item is already in the list.`, this);\n }\n return changed;\n }).length > 0);\n }\n remove(items) {\n return (normalizeListOfItems(items).filter((item) => {\n let changed = false;\n let index = this._protectedItems.indexOf(item);\n if (index === -1) {\n index = this._items.indexOf(item);\n if (index >= 0) {\n this._items.splice(index, 1);\n changed = true;\n }\n else {\n Log.debug(`The item is not in the list.`, this);\n }\n }\n else {\n Log.debug(`The item is protected and cannot be removed.`, this);\n }\n return changed;\n }).length > 0);\n }\n set(items, protect = false) {\n const cleared = this.clear();\n const added = this.add(items, protect);\n return cleared || added;\n }\n get(length) {\n return isNaN(length) === false && typeof length === 'number' ? this._items.slice(0, length) : this._items;\n }\n clear() {\n const length = this._items.length;\n this._items = this._items.filter((item) => {\n return this._protectedItems.indexOf(item) >= 0;\n });\n return length !== this._items.length;\n }\n contains(item) {\n return this._items.indexOf(item) > -1;\n }\n}\n//# sourceMappingURL=list-of.js.map","export abstract class AbstractFormatter {\r\n abstract format(value: unknown): unknown;\r\n abstract parse(value: unknown): unknown;\r\n}\r\n","import { ListOf } from '@leanup/lib/pattern/list-of';\n\nimport { AbstractFormatter } from './formatters/abstract.formatter';\n\nexport class FormatHandler {\n public readonly formatters: ListOf = new ListOf(AbstractFormatter);\n\n public format(value: unknown): unknown {\n this.formatters.forEach((formatter: AbstractFormatter) => {\n value = formatter.format(value);\n });\n return value;\n }\n public parse(value: unknown): unknown {\n this.formatters.forEach((formatter: AbstractFormatter) => {\n value = formatter.parse(value);\n });\n return value;\n }\n}\n","import { Log } from '@leanup/lib/helpers/log';\r\nimport { Validator } from '@leanup/lib/helpers/validator';\r\n\r\nexport abstract class AbstractValidator {\r\n private readonly state = {\r\n message: `Ein unbekannter Fehler ist aufgetreten.`,\r\n };\r\n\r\n constructor(message: string) {\r\n this.message = message;\r\n }\r\n\r\n set message(message: string) {\r\n if (Validator.isString(message, 1)) {\r\n this.state.message = message;\r\n } else {\r\n Log.debug(``);\r\n }\r\n }\r\n get message(): string {\r\n return this.state.message;\r\n }\r\n\r\n abstract isValid(value: any): boolean;\r\n}\r\n","import { ListOf } from '@leanup/lib/pattern/list-of';\n\nimport { AbstractValidator } from './validators/abstract.validator';\n\nexport class ValidationHandler {\n public readonly validators: ListOf = new ListOf(AbstractValidator);\n\n public validate(value: unknown, fast = false): string[] {\n const errors: string[] = [];\n try {\n this.validators.forEach((validator: AbstractValidator) => {\n if (validator.isValid(value) === false) {\n errors.push(validator.message);\n if (fast === true) {\n throw new Error(`Only one error is enough. Be quick and stop the execution of other validation functions.`);\n }\n }\n });\n } catch (error) {\n // be fast\n }\n return errors;\n }\n}\n","import { ListOf } from '@leanup/lib/pattern/list-of';\n\nimport { FormatHandler } from '../handlers/format.handler';\nimport { ValidationHandler } from '../handlers/validation.handler';\n\nabstract class AbstractControl {\n public readonly changeListeners: ListOf = new ListOf(Function);\n\n private readonly _errors: Set = new Set();\n private readonly _parentForms: FormControl[] = [];\n private _name = 'unnamed';\n private _validationHandler: ValidationHandler = new ValidationHandler();\n private _notifyTimeout: NodeJS.Timeout = setTimeout(() => {}, 0);\n\n constructor(name: string) {\n this.name = name;\n }\n\n get name(): string {\n return this._name;\n }\n set name(value: string) {\n if (typeof value === 'string') {\n if (value.length > 0) {\n this._name = value;\n } else {\n throw new Error('The name of a control must have a min-length of 1.');\n }\n } else {\n throw new Error('The name of a control must be a string.');\n }\n }\n\n get error(): string | null {\n if (this._errors.size > 0) {\n return this._errors.values().next().value;\n } else {\n return null;\n }\n }\n\n protected getErrors() {\n return this._errors;\n }\n\n get id(): string {\n let id = this.name;\n if (this._parentForms.length > 0) {\n id = `${this._parentForms[0].id}_${id}`;\n }\n return id;\n }\n\n get valid(): boolean {\n return this._errors.size === 0;\n }\n\n // ES5\n protected es5isValid(): boolean {\n return this._errors.size === 0;\n }\n\n public findMeInParentForm(control: AbstractControl): boolean {\n if (this === control) {\n return true;\n }\n if (control instanceof FormControl) {\n const findings: FormControl[] = [];\n this._parentForms.forEach((formControl: FormControl) => {\n if (formControl.findMeInParentForm(control) === true) {\n findings.push(formControl);\n }\n });\n return findings.length > 0;\n } else {\n return false;\n }\n }\n\n public addParentForm(form: FormControl) {\n if (this._parentForms.includes(form) === false) {\n if (form.findMeInParentForm(this) === false) {\n this._parentForms.push(form);\n } else {\n throw new Error(`The same form control (${form.name}) leads to a form control loop.`);\n }\n } else {\n throw new Error(`An form control with the name '${form.name}' already exists.`);\n }\n }\n\n public removeParentForm(form: FormControl) {\n const index = this._parentForms.indexOf(form);\n if (index >= 0) {\n this._parentForms.splice(index, 1);\n } else {\n throw new Error(`An form control with the name '${form.name}' does not exists.`);\n }\n }\n\n protected setValidationHandler(validationHandler: ValidationHandler, value: unknown = null) {\n this._validationHandler = validationHandler;\n this.validate(value);\n // this.notify(); redundant?!\n }\n\n protected validate(value: unknown) {\n this._errors.clear();\n const errors = this._validationHandler.validate(value);\n errors.forEach((error: string) => {\n this._errors.add(error);\n });\n this._parentForms.forEach((formControl: FormControl) => {\n formControl.validate(value);\n });\n }\n\n protected notify() {\n if (this._notifyTimeout) {\n clearTimeout(this._notifyTimeout);\n }\n this._notifyTimeout = setTimeout(() => {\n this.changeListeners.forEach((changeListener: Function) => {\n changeListener();\n });\n }, 0);\n }\n}\n\nexport enum InputControlTypes {\n checkbox = 'checkbox',\n date = 'date',\n email = 'email',\n number = 'number',\n password = 'password',\n radio = 'radio',\n select = 'select',\n slider = 'slider',\n text = 'text',\n}\nexport interface InputControlProps {\n info?: string;\n label?: string;\n disabled?: boolean;\n mandatory?: boolean;\n readonly?: boolean;\n placeholder?: string;\n type?: string;\n value?: unknown;\n}\n\nexport class InputControl extends AbstractControl implements InputControlProps {\n private _disabled = false;\n private _info = '';\n private _label = '';\n private _mandatory = false;\n private _placeholder = '';\n private _readonly = false;\n private _type = 'text';\n private _value: unknown = null;\n private _oldValue: unknown = null;\n private _valueTimeout: NodeJS.Timeout = setTimeout(() => {}, 0);\n private _formatHandler: FormatHandler = new FormatHandler();\n\n constructor(name: string, properties?: InputControlProps) {\n super(name);\n if (properties) {\n this.info = properties.info ? properties.info : '';\n this.label = properties.label ? properties.label : '';\n this.disabled = properties.disabled ? properties.disabled : false;\n this.mandatory = properties.mandatory ? properties.mandatory : false;\n this.readonly = properties.readonly ? properties.readonly : false;\n this.placeholder = properties.placeholder ? properties.placeholder : '';\n this.type = properties.type ? properties.type : 'text';\n this.value = properties.value ? properties.value : null;\n }\n }\n\n get info(): string {\n return this._info;\n }\n set info(value: string) {\n if (typeof value === 'string') {\n this._info = value;\n this.notify();\n } else {\n throw new Error('The info of a input control must be a string.');\n }\n }\n\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value: boolean) {\n if (typeof value === 'boolean') {\n this._disabled = value;\n this.notify();\n } else {\n throw new Error('The disabled flag of a input control must be a string.');\n }\n }\n\n get mandatory(): boolean {\n return this._mandatory;\n }\n set mandatory(value: boolean) {\n if (typeof value === 'boolean') {\n this._mandatory = value;\n this.notify();\n } else {\n throw new Error('The mandatory flag of a input control must be a string.');\n }\n }\n\n get readonly(): boolean {\n return this._readonly;\n }\n set readonly(value: boolean) {\n if (typeof value === 'boolean') {\n this._readonly = value;\n this.notify();\n } else {\n throw new Error('The readonly flag of a input control must be a string.');\n }\n }\n\n get label(): string {\n return this._label;\n }\n set label(value: string) {\n if (typeof value === 'string') {\n this._label = value;\n this.notify();\n } else {\n throw new Error('The label of a input control must be a string.');\n }\n }\n\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n if (typeof value === 'string') {\n this._placeholder = value;\n this.notify();\n } else {\n throw new Error('The placeholder of a input control must be a string.');\n }\n }\n\n get type(): string {\n return this._type.toString();\n }\n set type(value: string) {\n if (typeof value === 'string') {\n // https://developer.mozilla.org/de/docs/Web/HTML/Element/Input#Arten_des_%3Cinput%3E-Elements\n switch (value) {\n case 'checkbox':\n case 'date':\n case 'email':\n case 'number':\n case 'password':\n case 'radio':\n case 'select':\n case 'slider':\n case 'text':\n this._type = value;\n this.notify();\n break;\n default:\n throw new Error('The type of a input control must be a of the following types: ???.');\n }\n } else {\n throw new Error('The type of a input control must be a string.');\n }\n }\n\n get oldValue(): unknown {\n return this._oldValue;\n }\n\n get value(): unknown {\n return this._value;\n }\n set value(value: unknown) {\n if (this._valueTimeout) {\n clearTimeout(this._valueTimeout);\n }\n this._valueTimeout = setTimeout(() => {\n this.validate(value); // execution?!\n this._oldValue = this._value;\n this._value = value;\n this.notify();\n }, 0);\n }\n\n get modelValue(): unknown {\n return this.value;\n }\n set modelValue(value: unknown) {\n this.value = value;\n }\n\n get viewValue(): unknown {\n return this._formatHandler.format(this.modelValue);\n }\n set viewValue(value: unknown) {\n this.modelValue = this._formatHandler.parse(value);\n }\n\n public setValidationHandler(validationHandler: ValidationHandler) {\n super.setValidationHandler(validationHandler, this.value);\n }\n\n public setFormatHandler(formatHandler: FormatHandler) {\n this._formatHandler = formatHandler;\n }\n}\n\nexport class FormControl extends AbstractControl {\n private readonly controls: ListOf = new ListOf([FormControl, InputControl]);\n\n get disabled(): boolean {\n return (\n this.controls.filter((control: FormControl | InputControl) => {\n return control.disabled === false;\n }).length === 0\n );\n }\n set disabled(value: boolean) {\n this.controls.forEach((control: FormControl | InputControl) => {\n control.disabled = value;\n });\n }\n\n get readonly(): boolean {\n return (\n this.controls.filter((control: FormControl | InputControl) => {\n return control.readonly === false;\n }).length === 0\n );\n }\n set readonly(value: boolean) {\n this.controls.forEach((control: FormControl | InputControl) => {\n control.readonly = value;\n });\n }\n\n get valid(): boolean {\n return (\n this.es5isValid() && // ES5\n this.controls.filter((control: FormControl | InputControl) => {\n return control.valid === false;\n }).length === 0\n );\n }\n\n public addConrol(control: FormControl | InputControl): void {\n if (this.controls.contains(control) === false) {\n control.addParentForm(this);\n this.controls.add(control);\n } else {\n throw new Error(`A control with the same name '${control.name}' already exists.`);\n }\n }\n\n public removeControl(control: FormControl | InputControl): void {\n if (this.controls.contains(control) === true) {\n if (control instanceof AbstractControl) {\n control.removeParentForm(this);\n this.controls.remove(control);\n }\n } else {\n throw new Error(`A control with the name '${control.name}' does not exists.`);\n }\n }\n\n public getControls(): Array {\n return >this.controls.get();\n }\n\n public getControl(name: string): FormControl | InputControl {\n return this.controls.find((control: FormControl | InputControl) => {\n return control.name === name;\n });\n }\n\n public setData(_data: Object) {\n console.log('FormControl.setData is currently not implemented.');\n }\n\n public getData(): Object {\n const data: Record = {};\n this.controls.forEach((control: FormControl | InputControl) => {\n if (control instanceof FormControl) {\n data[control.name] = control.getData();\n } else if (control instanceof InputControl) {\n data[control.name] = control.value;\n } else {\n throw new Error(`The control is neither an instance of FormControl or InputControl.`);\n }\n });\n return data;\n }\n\n public setValidationHandler(validationHandler: ValidationHandler) {\n super.setValidationHandler(validationHandler);\n }\n}\n\nexport class FormFactory {\n static createForm(name: string, json: Record): FormControl {\n const form = new FormControl(name);\n for (const name in json) {\n if (json.hasOwnProperty(name)) {\n if (typeof json[name] === 'object' && json[name] !== null) {\n form.addConrol(FormFactory.createForm(name, json[name]));\n } else {\n const input = new InputControl(name);\n input.value = json[name];\n form.addConrol(input);\n }\n }\n }\n return form;\n }\n}\n","import { AbstractFormatter } from './abstract.formatter';\r\n\r\nexport class IbanFormatter extends AbstractFormatter {\r\n private regExp: RegExp = /([A-Z0-9]{1,4})/gi;\r\n\r\n public format(value: unknown): unknown {\r\n if (typeof value === 'string') {\r\n const matches: string[] | null = value.match(this.regExp);\r\n if (Array.isArray(matches)) {\r\n return matches?.join(' ');\r\n }\r\n }\r\n return value;\r\n }\r\n\r\n public parse(value: unknown): unknown {\r\n if (typeof value === 'string') {\r\n return value.replace(/ /g, '');\r\n }\r\n return value;\r\n }\r\n}\r\n\r\nexport const DEFAULT_IBAN_FORMATTER = new IbanFormatter();\r\n","import { AbstractValidator } from './abstract.validator';\r\n\r\nexport class RequiredValidator extends AbstractValidator {\r\n constructor(message: string = 'Bitte tragen Sie einen Wert ein.') {\r\n super(message);\r\n }\r\n\r\n public isValid(value: any): boolean {\r\n return value !== undefined && value !== null && value.toString().length > 0;\r\n }\r\n}\r\n\r\nexport const DEFAULT_REQUIRED_VALIDATOR: RequiredValidator = new RequiredValidator();\r\n","import { AbstractValidator } from './abstract.validator';\r\nimport { DEFAULT_REQUIRED_VALIDATOR } from './required.validator';\r\n\r\nexport abstract class NonRequiredValidator extends AbstractValidator {\r\n public isValid(value: any): boolean {\r\n return DEFAULT_REQUIRED_VALIDATOR.isValid(value) === false || this.validate(value);\r\n }\r\n\r\n abstract validate(value: any): boolean;\r\n}\r\n","import { Log } from '@leanup/lib/helpers/log';\r\n\r\nimport { NonRequiredValidator } from './non-required.validator';\r\n\r\nexport class PatternValidator extends NonRequiredValidator {\r\n public _regExp: RegExp = /^/g;\r\n\r\n constructor(regExp: RegExp, message: string = 'Bitte tragen Sie einen gültigen Wert ein.') {\r\n super(message);\r\n this.regExp = regExp;\r\n }\r\n\r\n set regExp(regExp: RegExp) {\r\n if (regExp instanceof RegExp) {\r\n this._regExp = regExp;\r\n } else {\r\n Log.debug(`The regExp of the pattern validator should be type of RegExp.`);\r\n }\r\n }\r\n\r\n get regExp(): RegExp {\r\n return this._regExp;\r\n }\r\n\r\n public validate(value: any): boolean {\r\n return this.regExp.test(value);\r\n }\r\n}\r\n\r\nexport class NotPatternValidator extends PatternValidator {\r\n public validate(value: any): boolean {\r\n return super.validate(value) === false;\r\n }\r\n}\r\n","import { PatternValidator } from './pattern.validator';\r\n\r\nexport const DIGITS_VALIDATION_REGEXP: RegExp = /^\\d+$/;\r\n\r\nexport class DigitsValidator extends PatternValidator {\r\n constructor(message: string = 'Der Wert ist keine Zahl.') {\r\n super(DIGITS_VALIDATION_REGEXP, message);\r\n }\r\n}\r\n\r\nexport const DEFAULT_DIGITS_VALIDATOR = new DigitsValidator();\r\n","import { PatternValidator } from './pattern.validator';\r\n\r\nexport const EMAIL_VALIDATION_REGEXP: RegExp =\r\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\r\n\r\nexport class EmailValidator extends PatternValidator {\r\n constructor(message: string = 'Die E-Mail-Adresse hat nicht das richtige Format.') {\r\n super(EMAIL_VALIDATION_REGEXP, message);\r\n }\r\n}\r\n","import { NonRequiredValidator } from './non-required.validator';\r\n\r\nexport class IsTrueValidator extends NonRequiredValidator {\r\n constructor(message: string = 'Bitte bestätigen Sie.') {\r\n super(message);\r\n }\r\n\r\n public validate(value: any): boolean {\r\n return value === true;\r\n }\r\n}\r\n","import { Validator } from '@leanup/lib/helpers/validator';\r\n\r\nimport { NonRequiredValidator } from './non-required.validator';\r\n\r\nexport class MaxLengthValidator extends NonRequiredValidator {\r\n // --- Properties ---\r\n public maxLength: number;\r\n\r\n constructor(maxLength: number, message: string = `Die Eingabe darf nicht länger als ${maxLength} Zeichen sein.`) {\r\n super(message);\r\n this.maxLength = maxLength;\r\n }\r\n\r\n public validate(value: any): boolean {\r\n return Validator.isString(value) && value.length <= this.maxLength;\r\n }\r\n}\r\n","import { Validator } from '@leanup/lib/helpers/validator';\r\n\r\nimport { NonRequiredValidator } from './non-required.validator';\r\n\r\nexport class MinLengthValidator extends NonRequiredValidator {\r\n // --- Properties ---\r\n public minLength: number;\r\n\r\n constructor(minLength: number, message: string = `Die Eingabe darf nicht kürzer als ${minLength} Zeichen sein.`) {\r\n super(message);\r\n this.minLength = minLength;\r\n }\r\n\r\n public validate(value: any): boolean {\r\n return Validator.isString(value) && value.length >= this.minLength;\r\n }\r\n}\r\n","import { AbstractValidator } from './abstract.validator';\r\nimport { NonRequiredValidator } from './non-required.validator';\r\n\r\nexport class NotValidator extends NonRequiredValidator {\r\n // --- Properties ---\r\n public validator: AbstractValidator;\r\n\r\n constructor(validator: AbstractValidator, message: string) {\r\n super(message);\r\n this.validator = validator;\r\n }\r\n\r\n public validate(value: any): boolean {\r\n return this.validator.isValid(value) === false;\r\n }\r\n}\r\n"],"names":["this","log.trace","log.debug","log.info","log.warn","log.error","log.setDefaultLevel","InputControlTypes"],"mappings":"qaAMA,AAAC,UAAU,EAAM,EAAY,CAIlB,AAAkC,EAAO,QAC5C,UAAiB,IAEjB,EAAK,IAAM,MAEjBA,EAAM,UAAY,CAIhB,GAAI,GAAO,UAAW,GAClB,EAAgB,YAChB,EAAQ,MAAO,UAAW,GAAmB,MAAO,QAAO,YAAc,GACzE,kBAAkB,KAAK,OAAO,UAAU,WAGxC,EAAa,CACb,QACA,QACA,OACA,OACA,SAIJ,WAAoB,EAAK,EAAY,CACjC,GAAI,GAAS,EAAI,GACjB,GAAI,MAAO,GAAO,MAAS,WACvB,MAAO,GAAO,KAAK,GAEnB,GAAI,CACA,MAAO,UAAS,UAAU,KAAK,KAAK,EAAQ,SACvC,EAAP,CAEE,MAAO,WAAW,CACd,MAAO,UAAS,UAAU,MAAM,MAAM,EAAQ,CAAC,EAAK,cAOpE,aAAsB,CAClB,AAAI,QAAQ,KACR,CAAI,QAAQ,IAAI,MACZ,QAAQ,IAAI,MAAM,QAAS,WAG3B,SAAS,UAAU,MAAM,MAAM,QAAQ,IAAK,CAAC,QAAS,aAG1D,QAAQ,OAAO,QAAQ,QAK/B,YAAoB,EAAY,CAK5B,MAJI,KAAe,SACf,GAAa,OAGb,MAAO,WAAY,EACZ,GACA,IAAe,SAAW,EAC1B,GACA,QAAQ,KAAgB,OACxB,EAAW,QAAS,GACpB,QAAQ,MAAQ,OAChB,EAAW,QAAS,OAEpB,EAMf,WAA+B,EAAO,EAAY,CAE9C,OAAS,GAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CACxC,GAAI,GAAa,EAAW,GAC5B,KAAK,GAAe,EAAI,EACpB,EACA,KAAK,cAAc,EAAY,EAAO,GAI9C,KAAK,IAAM,KAAK,MAKpB,YAAyC,EAAY,EAAO,EAAY,CACpE,MAAO,WAAY,CACf,AAAI,MAAO,WAAY,GACnB,GAAsB,KAAK,KAAM,EAAO,GACxC,KAAK,GAAY,MAAM,KAAM,aAOzC,YAA8B,EAAY,EAAO,EAAY,CAEzD,MAAO,IAAW,IACX,GAAgC,MAAM,KAAM,WAGvD,WAAgB,EAAM,EAAc,EAAS,CAC3C,GAAI,GAAO,KACP,EAEA,EAAa,WACjB,AAAI,MAAO,IAAS,SAClB,GAAc,IAAM,EACX,MAAO,IAAS,UACzB,GAAa,QAGf,YAAgC,EAAU,CACtC,GAAI,GAAa,GAAW,IAAa,UAAU,cAEnD,GAAI,QAAO,UAAW,GAAiB,CAAC,GAGxC,IAAI,CACA,OAAO,aAAa,GAAc,EAClC,aACK,EAAP,EAGF,GAAI,CACA,OAAO,SAAS,OACd,mBAAmB,GAAc,IAAM,EAAY,UAChD,EAAP,IAGN,YAA6B,CACzB,GAAI,GAEJ,GAAI,QAAO,UAAW,GAAiB,CAAC,GAExC,IAAI,CACA,EAAc,OAAO,aAAa,SAC7B,GAAP,EAGF,GAAI,MAAO,KAAgB,EACvB,GAAI,CACA,GAAI,GAAS,OAAO,SAAS,OACzB,EAAW,EAAO,QAClB,mBAAmB,GAAc,KACrC,AAAI,IAAa,IACb,GAAc,WAAW,KAAK,EAAO,MAAM,IAAW,UAErD,GAAP,EAIN,MAAI,GAAK,OAAO,KAAiB,QAC7B,GAAc,QAGX,GASX,EAAK,KAAO,EAEZ,EAAK,OAAS,CAAE,MAAS,EAAG,MAAS,EAAG,KAAQ,EAAG,KAAQ,EACvD,MAAS,EAAG,OAAU,GAE1B,EAAK,cAAgB,GAAW,GAEhC,EAAK,SAAW,UAAY,CACxB,MAAO,IAGX,EAAK,SAAW,SAAU,EAAO,EAAS,CAItC,GAHI,MAAO,IAAU,UAAY,EAAK,OAAO,EAAM,iBAAmB,QAClE,GAAQ,EAAK,OAAO,EAAM,gBAE1B,MAAO,IAAU,UAAY,GAAS,GAAK,GAAS,EAAK,OAAO,QAMhE,GALA,EAAe,EACX,IAAY,IACZ,GAAuB,GAE3B,EAAsB,KAAK,EAAM,EAAO,GACpC,MAAO,WAAY,GAAiB,EAAQ,EAAK,OAAO,OACxD,MAAO,uCAGX,MAAM,6CAA+C,GAI7D,EAAK,gBAAkB,SAAU,EAAO,CACpC,AAAK,KACD,EAAK,SAAS,EAAO,KAI7B,EAAK,UAAY,SAAS,EAAS,CAC/B,EAAK,SAAS,EAAK,OAAO,MAAO,IAGrC,EAAK,WAAa,SAAS,EAAS,CAChC,EAAK,SAAS,EAAK,OAAO,OAAQ,IAItC,GAAI,GAAe,IACnB,AAAI,GAAgB,MAChB,GAAe,GAAgB,KAAO,OAAS,GAEnD,EAAK,SAAS,EAAc,IAS9B,GAAI,GAAgB,GAAI,GAEpB,EAAiB,GACrB,EAAc,UAAY,SAAmB,EAAM,CAC/C,GAAK,MAAO,IAAS,UAAY,MAAO,IAAS,UAAa,IAAS,GACrE,KAAM,IAAI,WAAU,kDAGtB,GAAI,GAAS,EAAe,GAC5B,MAAK,IACH,GAAS,EAAe,GAAQ,GAAI,GAClC,EAAM,EAAc,WAAY,EAAc,gBAE3C,GAIX,GAAI,IAAQ,MAAO,UAAW,EAAiB,OAAO,IAAM,OAC5D,SAAc,WAAa,UAAW,CAClC,MAAI,OAAO,UAAW,GACf,OAAO,MAAQ,GAClB,QAAO,IAAM,IAGV,GAGX,EAAc,WAAa,UAAsB,CAC7C,MAAO,IAIX,EAAc,QAAa,EAEpB,SChRJ,OAAgB,CACnB,aAAc,QACP,UAAS,EAAK,CACjB,MAAO,OAAM,KAAS,IAAS,MAAO,IAAQ,eAE3C,SAAQ,EAAK,EAAY,EAAG,CAC/B,MAAO,OAAM,QAAQ,IAAQ,EAAI,QAAU,QAExC,UAAS,EAAK,CACjB,MAAO,OAAO,IAAQ,UAAY,IAAQ,MAAQ,KAAK,QAAQ,KAAS,SAErE,UAAS,EAAK,EAAY,EAAG,CAChC,MAAO,OAAO,IAAQ,UAAY,EAAI,QAAU,GCVxD,KAAM,GAAY,GAClB,YAA0B,CACtB,MAAO,eAEJ,OAAU,CACb,aAAc,QACP,KAAI,EAAO,EAAS,CAWvB,OAVI,EAAU,SAAS,EAAQ,YAC3B,MAAO,GAAQ,UAAU,aAAgB,YACzC,EAAU,SAAS,EAAQ,UAAU,YAAY,OACjD,GAAQ,UAAY,IAAI,EAAQ,UAAU,YAAY,UAE1D,EAAU,KAAK,CACX,KAAM,GAAI,QAAO,cACjB,QACA,YAEI,OACC,QACDC,gBAAU,GACV,UACC,QACDC,gBAAU,GACV,UACC,OACDC,eAAS,GACT,UACC,OACDC,eAAS,GACT,UACC,QACDC,gBAAU,UAMf,OAAM,EAAa,EAAW,CACjC,YAAK,IAAI,QAAS,CAAE,cAAa,cAC1B,WAEJ,OAAM,EAAa,EAAW,CACjC,YAAK,IAAI,QAAS,CAAE,cAAa,cAC1B,WAEJ,MAAK,EAAa,EAAW,CAChC,YAAK,IAAI,OAAQ,CAAE,cAAa,cACzB,WAEJ,MAAK,EAAa,EAAW,CAChC,YAAK,IAAI,OAAQ,CAAE,cAAa,cACzB,WAEJ,OAAM,EAAa,EAAW,CACjC,YAAK,IAAI,QAAS,CAAE,cAAa,cAC1B,eAEA,QAAQ,CACf,MAAO,GAAG,OAAO,IAIzB,OADA,EAAI,UAAY,KACR,SACC,cACDC,0BAAoB,SACpB,UACC,OACDA,0BAAoB,QACpB,UACC,aACDA,0BAAoB,SCtE5B,WAAsB,EAAa,EAAM,CACrC,MAAI,GAAU,QAAQ,GACV,EAAY,KAAK,AAAC,GACf,YAAgB,MACpB,OAEJ,GAEX,WAA8B,EAAO,CACjC,MAAQ,aAAiB,GAAS,EAAM,MAAQ,MAAM,QAAQ,GAAS,EAAQ,CAAC,GAE7E,OAAa,CAChB,YAAY,EAAa,CACrB,KAAK,aAAe,GACpB,KAAK,OAAS,GACd,KAAK,gBAAkB,GACvB,KAAK,aAAgB,MAAM,QAAQ,GAAe,EAAc,CAAC,MAEjE,QAAQ,CACR,MAAO,MAAK,OAAO,SAAW,KAE9B,QAAQ,CACR,MAAI,MAAK,OAAO,OAAS,EACd,KAAK,OAAO,GAGZ,KAGf,QAAQ,EAAQ,CACZ,KAAK,OAAO,QAAQ,GAExB,OAAO,EAAQ,CACX,MAAO,MAAK,OAAO,OAAO,GAE9B,KAAK,EAAQ,CACT,MAAO,MAAK,OAAO,KAAK,MAExB,OAAO,CACP,MAAI,MAAK,OAAO,OAAS,EACd,KAAK,OAAO,KAAK,OAAO,OAAS,GAGjC,QAGX,SAAS,CACT,MAAO,MAAK,OAAO,OAEvB,IAAI,EAAO,EAAU,GAAO,CACxB,MAAQ,GAAqB,GAAO,OAAO,AAAC,GAAS,CACjD,GAAI,GAAU,GACd,MAAI,MAAK,SAAS,KAAU,GACxB,AAAI,EAAa,KAAK,aAAc,GAC5B,IACA,KAAK,gBAAgB,KAAK,GAE9B,KAAK,OAAO,KAAK,GACjB,EAAU,IAGV,EAAI,MAAM,gDAAiD,MAI/D,EAAI,MAAM,mCAAoC,MAE3C,IACR,OAAS,EAEhB,OAAO,EAAO,CACV,MAAQ,GAAqB,GAAO,OAAO,AAAC,GAAS,CACjD,GAAI,GAAU,GACV,EAAQ,KAAK,gBAAgB,QAAQ,GACzC,MAAI,KAAU,GACV,GAAQ,KAAK,OAAO,QAAQ,GAC5B,AAAI,GAAS,EACT,MAAK,OAAO,OAAO,EAAO,GAC1B,EAAU,IAGV,EAAI,MAAM,+BAAgC,OAI9C,EAAI,MAAM,+CAAgD,MAEvD,IACR,OAAS,EAEhB,IAAI,EAAO,EAAU,GAAO,CACxB,KAAM,GAAU,KAAK,QACf,EAAQ,KAAK,IAAI,EAAO,GAC9B,MAAO,IAAW,EAEtB,IAAI,EAAQ,CACR,MAAO,OAAM,KAAY,IAAS,MAAO,IAAW,SAAW,KAAK,OAAO,MAAM,EAAG,GAAU,KAAK,OAEvG,OAAQ,CACJ,KAAM,GAAS,KAAK,OAAO,OAC3B,YAAK,OAAS,KAAK,OAAO,OAAO,AAAC,GACvB,KAAK,gBAAgB,QAAQ,IAAS,GAE1C,IAAW,KAAK,OAAO,OAElC,SAAS,EAAM,CACX,MAAO,MAAK,OAAO,QAAQ,GAAQ,WC5GH,SCIb,CAApB,aAJP,iBAK0D,GAAI,GAAO,GAE5D,OAAO,EAAyB,aAChC,WAAW,QAAQ,AAAC,GAAiC,GAChD,EAAU,OAAO,KAEpB,EAEF,MAAM,EAAyB,aAC/B,WAAW,QAAQ,AAAC,GAAiC,GAChD,EAAU,MAAM,KAEnB,UCd6B,CAKtC,YAAY,EAAiB,YAJJ,CACvB,QAAS,gDAIJ,QAAU,KAGb,SAAQ,EAAiB,CACvB,EAAU,SAAS,EAAS,QACzB,MAAM,QAAU,IAEjB,MAAM,OAGV,UAAkB,OACb,MAAK,MAAM,gBChBS,CAAxB,aAJP,iBAK0D,GAAI,GAAO,GAE5D,SAAS,EAAgB,EAAO,GAAiB,MAChD,GAAmB,MACrB,MACG,WAAW,QAAQ,AAAC,GAAiC,IACpD,EAAU,QAAQ,KAAW,OACxB,KAAK,EAAU,SAClB,IAAS,SACL,IAAI,OAAM,oGAIf,UAGF,IChBX,OAA+B,CAS7B,YAAY,EAAc,sBAR0B,GAAI,GAAO,uBAEvB,GAAI,uBACG,cAC/B,kCACgC,GAAI,uBACX,WAAW,IAAM,GAAI,QAGvD,KAAO,KAGV,OAAe,OACV,MAAK,SAEV,MAAK,EAAe,IAClB,MAAO,IAAU,YACf,EAAM,OAAS,OACZ,MAAQ,YAEP,IAAI,OAAM,gEAGZ,IAAI,OAAM,8CAIhB,QAAuB,OACrB,MAAK,QAAQ,KAAO,EACf,KAAK,QAAQ,SAAS,OAAO,MAE7B,KAID,WAAY,OACb,MAAK,WAGV,KAAa,IACX,GAAK,KAAK,WACV,MAAK,aAAa,OAAS,MACxB,GAAG,KAAK,aAAa,GAAG,MAAM,KAE9B,KAGL,QAAiB,OACZ,MAAK,QAAQ,OAAS,EAIrB,YAAsB,OACvB,MAAK,QAAQ,OAAS,EAGxB,mBAAmB,EAAmC,IACvD,OAAS,QACJ,MAEL,YAAmB,GAAa,MAC5B,GAA0B,eAC3B,aAAa,QAAQ,AAAC,GAA6B,CAClD,EAAY,mBAAmB,KAAa,MACrC,KAAK,KAGX,EAAS,OAAS,aAElB,GAIJ,cAAc,EAAmB,IAClC,KAAK,aAAa,SAAS,KAAU,MACnC,EAAK,mBAAmB,QAAU,QAC/B,aAAa,KAAK,aAEjB,IAAI,OAAM,0BAA0B,EAAK,iDAG3C,IAAI,OAAM,kCAAkC,EAAK,yBAIpD,iBAAiB,EAAmB,MACnC,GAAQ,KAAK,aAAa,QAAQ,MACpC,GAAS,OACN,aAAa,OAAO,EAAO,aAE1B,IAAI,OAAM,kCAAkC,EAAK,0BAIjD,qBAAqB,EAAsC,EAAiB,KAAM,MACrF,mBAAqB,OACrB,SAAS,GAIN,SAAS,EAAgB,MAC5B,QAAQ,QACE,KAAK,mBAAmB,SAAS,GACzC,QAAQ,AAAC,GAAkB,MAC3B,QAAQ,IAAI,UAEd,aAAa,QAAQ,AAAC,GAA6B,GAC1C,SAAS,KAIf,QAAS,CACb,KAAK,6BACM,KAAK,qBAEf,eAAiB,WAAW,IAAM,MAChC,gBAAgB,QAAQ,AAAC,GAA6B,QAG1D,wCAIK,EAAL,YACM,kBACJ,eACC,iBACC,oBACE,mBACH,iBACC,kBACA,gBACF,QATGC,8DAsBsB,EAA6C,CAa7E,YAAY,EAAc,EAAgC,OAClD,kBAbY,cACJ,eACC,mBACI,qBACE,kBACH,cACJ,mBACU,oBACG,wBACW,WAAW,IAAM,GAAI,uBACrB,GAAI,GAItC,SACG,KAAO,EAAW,KAAO,EAAW,KAAO,QAC3C,MAAQ,EAAW,MAAQ,EAAW,MAAQ,QAC9C,SAAW,EAAW,SAAW,EAAW,SAAW,QACvD,UAAY,EAAW,UAAY,EAAW,UAAY,QAC1D,SAAW,EAAW,SAAW,EAAW,SAAW,QACvD,YAAc,EAAW,YAAc,EAAW,YAAc,QAChE,KAAO,EAAW,KAAO,EAAW,KAAO,YAC3C,MAAQ,EAAW,MAAQ,EAAW,MAAQ,SAInD,OAAe,OACV,MAAK,SAEV,MAAK,EAAe,IAClB,MAAO,IAAU,cACd,MAAQ,OACR,mBAEC,IAAI,OAAM,oDAIhB,WAAoB,OACf,MAAK,aAEV,UAAS,EAAgB,IACvB,MAAO,IAAU,eACd,UAAY,OACZ,mBAEC,IAAI,OAAM,6DAIhB,YAAqB,OAChB,MAAK,cAEV,WAAU,EAAgB,IACxB,MAAO,IAAU,eACd,WAAa,OACb,mBAEC,IAAI,OAAM,8DAIhB,WAAoB,OACf,MAAK,aAEV,UAAS,EAAgB,IACvB,MAAO,IAAU,eACd,UAAY,OACZ,mBAEC,IAAI,OAAM,6DAIhB,QAAgB,OACX,MAAK,UAEV,OAAM,EAAe,IACnB,MAAO,IAAU,cACd,OAAS,OACT,mBAEC,IAAI,OAAM,qDAIhB,cAAsB,OACjB,MAAK,gBAEV,aAAY,EAAe,IACzB,MAAO,IAAU,cACd,aAAe,OACf,mBAEC,IAAI,OAAM,2DAIhB,OAAe,OACV,MAAK,MAAM,cAEhB,MAAK,EAAe,IAClB,MAAO,IAAU,gBAEX,OACD,eACA,WACA,YACA,aACA,eACA,YACA,aACA,aACA,YACE,MAAQ,OACR,4BAGC,IAAI,OAAM,gFAGd,IAAI,OAAM,oDAIhB,WAAoB,OACf,MAAK,aAGV,QAAiB,OACZ,MAAK,UAEV,OAAM,EAAgB,CACpB,KAAK,4BACM,KAAK,oBAEf,cAAgB,WAAW,IAAM,MAC/B,SAAS,QACT,UAAY,KAAK,YACjB,OAAS,OACT,UACJ,MAGD,aAAsB,OACjB,MAAK,SAEV,YAAW,EAAgB,MACxB,MAAQ,KAGX,YAAqB,OAChB,MAAK,eAAe,OAAO,KAAK,eAErC,WAAU,EAAgB,MACvB,WAAa,KAAK,eAAe,MAAM,GAGvC,qBAAqB,EAAsC,OAC1D,qBAAqB,EAAmB,KAAK,OAG9C,iBAAiB,EAA8B,MAC/C,eAAiB,kBAIO,EAAgB,CAA1C,aA/TP,mCAgUkE,GAAI,GAAO,CAAC,EAAa,OAErF,WAAoB,OAEpB,MAAK,SAAS,OAAO,AAAC,GACb,EAAQ,WAAa,IAC3B,SAAW,KAGd,UAAS,EAAgB,MACtB,SAAS,QAAQ,AAAC,GAAwC,GACrD,SAAW,OAInB,WAAoB,OAEpB,MAAK,SAAS,OAAO,AAAC,GACb,EAAQ,WAAa,IAC3B,SAAW,KAGd,UAAS,EAAgB,MACtB,SAAS,QAAQ,AAAC,GAAwC,GACrD,SAAW,OAInB,QAAiB,OAEjB,MAAK,cACL,KAAK,SAAS,OAAO,AAAC,GACb,EAAQ,QAAU,IACxB,SAAW,EAIX,UAAU,EAA2C,IACtD,KAAK,SAAS,SAAS,KAAa,KAC9B,cAAc,WACjB,SAAS,IAAI,aAEZ,IAAI,OAAM,iCAAiC,EAAQ,yBAItD,cAAc,EAA2C,IAC1D,KAAK,SAAS,SAAS,KAAa,GAClC,YAAmB,OACb,iBAAiB,WACpB,SAAS,OAAO,cAGjB,IAAI,OAAM,4BAA4B,EAAQ,0BAIjD,aAAiD,OACZ,MAAK,SAAS,MAGnD,WAAW,EAA0C,OACnD,MAAK,SAAS,KAAK,AAAC,GAClB,EAAQ,OAAS,GAIrB,QAAQ,EAAe,SACpB,IAAI,qDAGP,SAAkB,MACjB,GAA4B,eAC7B,SAAS,QAAQ,AAAC,GAAwC,IACzD,YAAmB,KAChB,EAAQ,MAAQ,EAAQ,kBACpB,YAAmB,KACvB,EAAQ,MAAQ,EAAQ,gBAEvB,IAAI,OAAM,wEAGb,EAGF,qBAAqB,EAAsC,OAC1D,qBAAqB,WAIN,OAChB,YAAW,EAAc,EAAwC,MAChE,GAAO,GAAI,GAAY,YAClB,KAAQ,MACb,EAAK,eAAe,MAClB,MAAO,GAAK,IAAU,UAAY,EAAK,KAAU,OAC9C,UAAU,EAAY,WAAW,EAAM,EAAK,SAC5C,MACC,GAAQ,GAAI,GAAa,KACzB,MAAiB,EAAK,KACvB,UAAU,SAId,mBCtawB,EAAkB,CAA9C,aAFP,iCAG2B,oBAElB,OAAO,EAAyB,IACjC,MAAO,IAAU,SAAU,MACvB,GAA2B,EAAM,MAAM,KAAK,WAC9C,MAAM,QAAQ,SACT,kBAAS,KAAK,WAGlB,GAGF,MAAM,EAAyB,OAChC,OAAO,IAAU,SACZ,EAAM,QAAQ,KAAM,IAEtB,QAIE,GAAyB,GAAI,kBCrBH,EAAkB,CACvD,YAAY,EAAkB,mCAAoC,OAC1D,GAGD,QAAQ,EAAqB,OAC3B,AAAuB,IAAU,MAAQ,EAAM,WAAW,OAAS,QAIjE,GAAgD,GAAI,kBCTd,EAAkB,CAC5D,QAAQ,EAAqB,OAC3B,GAA2B,QAAQ,KAAW,IAAS,KAAK,SAAS,mBCD1C,EAAqB,CAGzD,YAAY,EAAgB,EAAkB,+CAA6C,OACnF,gBAHiB,UAIlB,OAAS,KAGZ,QAAO,EAAgB,CACrB,YAAkB,aACf,QAAU,IAEX,MAAM,oEAIV,SAAiB,OACZ,MAAK,QAGP,SAAS,EAAqB,OAC5B,MAAK,OAAO,KAAK,mBAIa,EAAiB,CACjD,SAAS,EAAqB,OAC5B,OAAM,SAAS,KAAW,SC7BxB,GAAmC,uBAEX,EAAiB,CACpD,YAAY,EAAkB,2BAA4B,OAClD,EAA0B,SAIvB,GAA2B,GAAI,GCR/B,EACX,sKAEkC,EAAiB,CACnD,YAAY,EAAkB,oDAAqD,OAC3E,EAAyB,mBCLE,EAAqB,CACxD,YAAY,EAAkB,2BAAyB,OAC/C,GAGD,SAAS,EAAqB,OAC5B,KAAU,mBCJmB,EAAqB,CAI3D,YAAY,EAAmB,EAAkB,wCAAqC,kBAA2B,OACzG,QACD,UAAY,EAGZ,SAAS,EAAqB,OAC5B,GAAU,SAAS,IAAU,EAAM,QAAU,KAAK,0BCVrB,EAAqB,CAI3D,YAAY,EAAmB,EAAkB,wCAAqC,kBAA2B,OACzG,QACD,UAAY,EAGZ,SAAS,EAAqB,OAC5B,GAAU,SAAS,IAAU,EAAM,QAAU,KAAK,2BCX3B,EAAqB,CAIrD,YAAY,EAA8B,EAAiB,OACnD,QACD,UAAY,EAGZ,SAAS,EAAqB,OAC5B,MAAK,UAAU,QAAQ,KAAW"}
\ No newline at end of file
diff --git a/packages/components/src/assets/@leanup/forms/index.js b/packages/components/src/assets/@leanup/forms/index.js
deleted file mode 100644
index e72cd776c1..0000000000
--- a/packages/components/src/assets/@leanup/forms/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@leanup/lib")):"function"==typeof define&&define.amd?define(["exports","@leanup/lib"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).LeanUpForm={},t.LeanUpLib)}(this,(function(t,e){"use strict";class r{}class s extends e.SetOf{constructor(){super(r),this.formatters=this}format(t){return this.formatters.forEach((e=>{t=e.format(t)})),t}parse(t){return this.formatters.forEach((e=>{t=e.parse(t)})),t}}class a{constructor(t){this.state={message:"An unknown validation error occurred."},this.message=t}set message(t){"string"==typeof t&&t.length>0?this.state.message=t:e.Log.error("The message of the validator should be type of string with a min-length of 1.")}get message(){return this.state.message}}class o extends e.SetOf{constructor(){super(a),this.validators=this,this.validators=this}validate(t,e=!1){const r=[];try{this.validators.forEach((s=>{if(!1===s.valid(t)&&(r.push(s.message),!0===e))throw new Error("Only one error is enough. Be quick and stop the execution of other validation functions.")}))}catch(t){}return r}}class n{constructor(t){this.changeListeners=new e.SetOf(Function),this._errors=new Set,this._parentForms=new Set,this._name="unnamed",this._validationHandler=new o,this.name=t}get name(){return this._name}set name(t){if("string"!=typeof t)throw new Error("The name of a control must be a string.");if(!(t.length>0))throw new Error("The name of a control must have a min-length of 1.");this._name=t}get error(){return this._errors.size>0?this._errors.values().next().value:null}getErrors(){return this._errors}get id(){let t=this.name;return this._parentForms.size>0&&(t=`${this._parentForms.values().next().value.id}_${t}`),t}get valid(){return 0===this._errors.size}findMeInParentForm(t){if(this===t)return!0;if(t instanceof h){const e=[];return this._parentForms.forEach((r=>{!0===r.findMeInParentForm(t)&&e.push(r)})),e.length>0}return!1}addParentForm(t){if(!1!==this._parentForms.has(t))throw new Error(`An form control with the name '${t.name}' already exists.`);if(!1!==t.findMeInParentForm(this))throw new Error(`The same form control (${t.name}) leads to a form control loop.`);this._parentForms.add(t)}removeParentForm(t){if(!0!==this._parentForms.has(t))throw new Error(`An form control with the name '${t.name}' does not exists.`);this._parentForms.delete(t)}setValidationHandler(t,e=null){this._validationHandler=t,this.validate(e),this.notify()}validate(t){this._errors.clear();this._validationHandler.validate(t).forEach((t=>{this._errors.add(t)})),this._parentForms.forEach((t=>{t.validate(t.getData())}))}notify(...t){this.changeListeners.forEach((e=>{e(...t)})),this._parentForms.forEach((t=>{t.notify(t.getData())}))}}var i;t.InputControlTypes=void 0,(i=t.InputControlTypes||(t.InputControlTypes={})).checkbox="checkbox",i.date="date",i.email="email",i.number="number",i.password="password",i.radio="radio",i.select="select",i.slider="slider",i.text="text";class l extends n{constructor(t,e){super(t),this._disabled=!1,this._label="",this._mandatory=!1,this._placeholder="",this._readonly=!1,this._type="text",this._value=null,this._oldValue=null,this._formatHandler=new s,"object"==typeof e&&null!==e&&(this.disabled=!0===e.disabled,this.label="string"==typeof e.label?e.label:"",this.mandatory=!0===e.mandatory,this.placeholder="string"==typeof e.placeholder?e.placeholder:"",this.readonly=!0===e.disabled,this.type="string"==typeof e.type?e.type:"text",this.value=void 0!==e.value?e.value:null)}get disabled(){return this._disabled}set disabled(t){if("boolean"!=typeof t)throw new Error("The disabled flag of a input control must be a string.");this._disabled=t,this.notify()}get mandatory(){return this._mandatory}set mandatory(t){if("boolean"!=typeof t)throw new Error("The mandatory flag of a input control must be a string.");this._mandatory=t,this.notify()}get readonly(){return this._readonly}set readonly(t){if("boolean"!=typeof t)throw new Error("The readonly flag of a input control must be a string.");this._readonly=t,this.notify()}get label(){return this._label}set label(t){if("string"!=typeof t)throw new Error("The label of a input control must be a string.");this._label=t,this.notify()}get placeholder(){return this._placeholder}set placeholder(t){if("string"!=typeof t)throw new Error("The placeholder of a input control must be a string.");this._placeholder=t,this.notify()}get type(){return this._type.toString()}set type(t){if("string"!=typeof t)throw new Error("The type of a input control must be a string.");switch(t){case"checkbox":case"date":case"email":case"number":case"password":case"radio":case"select":case"slider":case"text":this._type=t,this.notify();break;default:throw new Error("The type of a input control must be a of the following types: ???.")}}get oldValue(){return this._oldValue}get value(){return this._value}set value(t){this._oldValue=this._value,this._value=t,this.validate(t),this.notify()}get modelValue(){return this.value}set modelValue(t){this.value=t}get viewValue(){return this._formatHandler.format(this.modelValue)}set viewValue(t){this.modelValue=this._formatHandler.parse(t)}notify(){super.notify(this._value,this._oldValue)}setValidationHandler(t){super.setValidationHandler(t,this.value)}setFormatHandler(t){this._formatHandler=t}}class h extends n{constructor(){super(...arguments),this.controls=new Set}get disabled(){return 0===Array.from(this.controls).filter((t=>!1===t.disabled)).length}set disabled(t){this.controls.forEach((e=>{e.disabled=t}))}get readonly(){return 0===Array.from(this.controls).filter((t=>!1===t.readonly)).length}set readonly(t){this.controls.forEach((e=>{e.readonly=t}))}get valid(){return super.valid&&0===Array.from(this.controls).filter((t=>!1===t.valid)).length}addControl(t){if(!1!==this.controls.has(t))throw new Error(`A control with the same name '${t.name}' already exists.`);t.addParentForm(this),this.controls.add(t)}removeControl(t){if(!0!==this.controls.has(t))throw new Error(`A control with the name '${t.name}' does not exists.`);t instanceof n&&(t.removeParentForm(this),this.controls.delete(t))}getControls(){return Array.from(this.controls)}getControl(t){return Array.from(this.controls).find((e=>e.name===t))}getForms(){return Array.from(this.controls).filter((t=>t instanceof h))}getForm(t){return Array.from(this.getForms()).find((e=>e.name===t))}getInputs(){return Array.from(this.controls).filter((t=>t instanceof l))}getInput(t){return Array.from(this.getInputs()).find((e=>e.name===t))}setData(t){this.controls.forEach((e=>{if(void 0!==t[e.name])if(e instanceof h)e.setData(t[e.name]);else{if(!(e instanceof l))throw new Error("The control is neither an instance of FormControl or InputControl.");e.value=t[e.name]}}))}getData(){const t={};return this.controls.forEach((e=>{if(e instanceof h)t[e.name]=e.getData();else{if(!(e instanceof l))throw new Error("The control is neither an instance of FormControl or InputControl.");t[e.name]=e.value}})),t}setValidationHandler(t){super.setValidationHandler(t)}}class d{static createForm(t,e){const r=new h(t);for(const t in e)if(e.hasOwnProperty(t))if("object"==typeof e[t]&&null!==e[t])r.addControl(d.createForm(t,e[t]));else{const s=new l(t,{value:e[t]});r.addControl(s)}return r}}class u extends r{constructor(){super(...arguments),this.regExp=/([A-Z0-9]{1,4})/gi}format(t){if("string"==typeof t){const e=t.match(this.regExp);if(Array.isArray(e))return null==e?void 0:e.join(" ")}return t}parse(t){return"string"==typeof t?t.replace(/ /g,""):t}}const c=new u;class f extends a{constructor(t="Please enter a value."){super(t)}valid(t){return null!=t&&t.toString().length>0}}const m=new f;class p extends a{valid(t){return!1===m.valid(t)||this.validate(t)}}class g extends p{constructor(t,e="Please enter a valid value."){super(e),this._regExp=/^/g,this.regExp=t}set regExp(t){t instanceof RegExp?this._regExp=t:e.Log.debug("The regExp of the pattern validator should be type of RegExp.")}get regExp(){return this._regExp}validate(t){return this.regExp.test(t)}}const y=/^\d+$/;class v extends g{constructor(t="Please enter a number."){super(y,t)}}const _=new v,w=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;t.AbstractFormatter=r,t.AbstractValidator=a,t.DEFAULT_DIGITS_VALIDATOR=_,t.DEFAULT_IBAN_FORMATTER=c,t.DEFAULT_REQUIRED_VALIDATOR=m,t.DIGITS_VALIDATION_REGEXP=y,t.DigitsValidator=v,t.EMAIL_VALIDATION_REGEXP=w,t.EmailValidator=class extends g{constructor(t="The email address has not the correct format."){super(w,t)}},t.FormControl=h,t.FormFactory=d,t.FormatHandler=s,t.IbanFormatter=u,t.InputControl=l,t.IsTrueValidator=class extends p{constructor(t="Please confirm the note."){super(t)}validate(t){return!0===t}},t.MaxLengthValidator=class extends p{constructor(t,e=`The entry must not be longer than ${t} characters.`){super(e),this.maxLength=t}validate(t){return"string"==typeof t&&t.length<=this.maxLength}},t.MinLengthValidator=class extends p{constructor(t,e=`The entry must not be shorter than ${t} characters.`){super(e),this.minLength=t}validate(t){return"string"==typeof t&&t.length>=this.minLength}},t.NonRequiredValidator=p,t.NotPatternValidator=class extends g{validate(t){return!1===super.validate(t)}},t.NotValidator=class extends p{constructor(t,e){super(e),this.validator=t}validate(t){return!1===this.validator.valid(t)}},t.PatternValidator=g,t.RequiredValidator=f,t.ValidationHandler=o,Object.defineProperty(t,"__esModule",{value:!0})}));
-//# sourceMappingURL=index.js.map
diff --git a/packages/components/src/assets/@leanup/forms/index.js.map b/packages/components/src/assets/@leanup/forms/index.js.map
deleted file mode 100644
index 425f6be95c..0000000000
--- a/packages/components/src/assets/@leanup/forms/index.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"index.js","sources":["../src/handlers/formatters/abstract.formatter.ts","../src/handlers/format.handler.ts","../src/handlers/validators/abstract.validator.ts","../src/handlers/validation.handler.ts","../src/controls/controls.ts","../src/handlers/formatters/iban.formatter.ts","../src/handlers/validators/required.validator.ts","../src/handlers/validators/non-required.validator.ts","../src/handlers/validators/pattern.validator.ts","../src/handlers/validators/digits.validator.ts","../src/handlers/validators/email.validator.ts","../src/handlers/validators/is-true.validator.ts","../src/handlers/validators/max-length.validator.ts","../src/handlers/validators/min-length.validator.ts","../src/handlers/validators/not.validator.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":["AbstractFormatter","FormatHandler","SetOf","constructor","super","this","formatters","format","value","forEach","formatter","parse","AbstractValidator","message","state","length","Log","error","ValidationHandler","validators","validate","fast","errors","validator","valid","push","Error","AbstractControl","name","changeListeners","Function","_errors","Set","_parentForms","_name","_validationHandler","size","values","next","getErrors","id","findMeInParentForm","control","FormControl","findings","formControl","addParentForm","form","has","add","removeParentForm","delete","setValidationHandler","validationHandler","notify","clear","getData","args","changeListener","InputControlTypes","exports","InputControl","properties","_disabled","_label","_mandatory","_placeholder","_readonly","_type","_value","_oldValue","_formatHandler","disabled","label","mandatory","placeholder","readonly","type","undefined","toString","oldValue","modelValue","viewValue","setFormatHandler","formatHandler","controls","Array","from","filter","addControl","removeControl","getControls","getControl","find","getForms","getForm","getInputs","getInput","setData","data","FormFactory","static","json","hasOwnProperty","createForm","input","IbanFormatter","regExp","matches","match","isArray","join","replace","DEFAULT_IBAN_FORMATTER","RequiredValidator","DEFAULT_REQUIRED_VALIDATOR","NonRequiredValidator","PatternValidator","_regExp","RegExp","debug","test","DIGITS_VALIDATION_REGEXP","DigitsValidator","DEFAULT_DIGITS_VALIDATOR","EMAIL_VALIDATION_REGEXP","maxLength","minLength"],"mappings":"2SAAsBA,GCIhB,MAAOC,UAAsBC,EAAAA,MAGjCC,cACEC,MAAMJ,GACNK,KAAKC,WAAaD,KAGbE,OAAOC,GAIZ,OAHAH,KAAKC,WAAWG,SAASC,IACvBF,EAAQE,EAAUH,OAAOC,MAEpBA,EAEFG,MAAMH,GAIX,OAHAH,KAAKC,WAAWG,SAASC,IACvBF,EAAQE,EAAUC,MAAMH,MAEnBA,SCpBWI,EAKpBT,YAAYU,GAJKR,KAAAS,MAAQ,CACvBD,QAAS,yCAITR,KAAKQ,QAAUA,EAGbA,YAAQA,GACa,iBAAZA,GAAwBA,EAAQE,OAAS,EAClDV,KAAKS,MAAMD,QAAUA,EAErBG,EAAAA,IAAIC,MAAM,iFAGVJ,cACF,OAAOR,KAAKS,MAAMD,SCfhB,MAAOK,UAA0BhB,EAAAA,MAGrCC,cACEC,MAAMQ,GAHQP,KAAUc,WAA6Bd,KAIrDA,KAAKc,WAAad,KAGbe,SAASZ,EAAgBa,GAAO,GACrC,MAAMC,EAAmB,GACzB,IACEjB,KAAKc,WAAWV,SAASc,IACvB,IAA+B,IAA3BA,EAAUC,MAAMhB,KAClBc,EAAOG,KAAKF,EAAUV,UACT,IAATQ,GACF,MAAM,IAAIK,MAAM,+FAItB,MAAOT,IAGT,OAAOK,GCrBX,MAAeK,EAQbxB,YAAYyB,GAPIvB,KAAAwB,gBAAmC,IAAI3B,EAAKA,MAAC4B,UAE5CzB,KAAA0B,QAAuB,IAAIC,IAC3B3B,KAAA4B,aAAiC,IAAID,IAC9C3B,KAAK6B,MAAG,UACR7B,KAAA8B,mBAAwC,IAAIjB,EAGlDb,KAAKuB,KAAOA,EAGVA,WACF,OAAOvB,KAAK6B,MAEVN,SAAKpB,GACP,GAAqB,iBAAVA,EAOT,MAAM,IAAIkB,MAAM,2CANhB,KAAIlB,EAAMO,OAAS,GAGjB,MAAM,IAAIW,MAAM,sDAFhBrB,KAAK6B,MAAQ1B,EASfS,YACF,OAAIZ,KAAK0B,QAAQK,KAAO,EACf/B,KAAK0B,QAAQM,SAASC,OAAO9B,MAE7B,KAID+B,YACR,OAAOlC,KAAK0B,QAGVS,SACF,IAAIA,EAAKnC,KAAKuB,KAId,OAHIvB,KAAK4B,aAAaG,KAAO,IAC3BI,EAAK,GAAGnC,KAAK4B,aAAaI,SAASC,OAAO9B,MAAMgC,MAAMA,KAEjDA,EAGLhB,YACF,OAA6B,IAAtBnB,KAAK0B,QAAQK,KAGfK,mBAAmBC,GACxB,GAAIrC,OAASqC,EACX,OAAO,EAET,GAAIA,aAAmBC,EAAa,CAClC,MAAMC,EAA0B,GAMhC,OALAvC,KAAK4B,aAAaxB,SAASoC,KACuB,IAA5CA,EAAYJ,mBAAmBC,IACjCE,EAASnB,KAAKoB,MAGXD,EAAS7B,OAAS,EAEzB,OAAO,EAIJ+B,cAAcC,GACnB,IAAoC,IAAhC1C,KAAK4B,aAAae,IAAID,GAOxB,MAAM,IAAIrB,MAAM,kCAAkCqB,EAAKnB,yBANvD,IAAsC,IAAlCmB,EAAKN,mBAAmBpC,MAG1B,MAAM,IAAIqB,MAAM,0BAA0BqB,EAAKnB,uCAF/CvB,KAAK4B,aAAagB,IAAIF,GASrBG,iBAAiBH,GACtB,IAAoC,IAAhC1C,KAAK4B,aAAae,IAAID,GAGxB,MAAM,IAAIrB,MAAM,kCAAkCqB,EAAKnB,0BAFvDvB,KAAK4B,aAAakB,OAAOJ,GAMnBK,qBAAqBC,EAAsC7C,EAAiB,MACpFH,KAAK8B,mBAAqBkB,EAC1BhD,KAAKe,SAASZ,GACdH,KAAKiD,SAGGlC,SAASZ,GACjBH,KAAK0B,QAAQwB,QACElD,KAAK8B,mBAAmBf,SAASZ,GACzCC,SAASQ,IACdZ,KAAK0B,QAAQkB,IAAIhC,MAEnBZ,KAAK4B,aAAaxB,SAASoC,IACzBA,EAAYzB,SAASyB,EAAYW,cAI3BF,UAAUG,GAClBpD,KAAKwB,gBAAgBpB,SAASiD,IAC5BA,KAAkBD,MAEpBpD,KAAK4B,aAAaxB,SAASsC,IAKzBA,EAAKO,OAAOP,EAAKS,eAKvB,IAAYG,EAUXC,EAAAD,uBAAA,GAVWA,EAAAA,sBAAAA,EAAAA,kBAUX,KATC,SAAA,WACAA,EAAA,KAAA,OACAA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,SAAA,WACAA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,OAAA,SACAA,EAAA,KAAA,OAaI,MAAOE,UAAqBlC,EAWhCxB,YAAYyB,EAAckC,GACxB1D,MAAMwB,GAXAvB,KAAS0D,WAAG,EACZ1D,KAAM2D,OAAG,GACT3D,KAAU4D,YAAG,EACb5D,KAAY6D,aAAG,GACf7D,KAAS8D,WAAG,EACZ9D,KAAK+D,MAAG,OACR/D,KAAMgE,OAAY,KAClBhE,KAASiE,UAAY,KACrBjE,KAAAkE,eAAgC,IAAItE,EAIhB,iBAAf6D,GAA0C,OAAfA,IACpCzD,KAAKmE,UAAmC,IAAxBV,EAAWU,SAC3BnE,KAAKoE,MAAoC,iBAArBX,EAAWW,MAAqBX,EAAWW,MAAQ,GACvEpE,KAAKqE,WAAqC,IAAzBZ,EAAWY,UAC5BrE,KAAKsE,YAAgD,iBAA3Bb,EAAWa,YAA2Bb,EAAWa,YAAc,GACzFtE,KAAKuE,UAAmC,IAAxBd,EAAWU,SAC3BnE,KAAKwE,KAAkC,iBAApBf,EAAWe,KAAoBf,EAAWe,KAAO,OACpExE,KAAKG,WAA6BsE,IAArBhB,EAAWtD,MAAsBsD,EAAWtD,MAAQ,MAIjEgE,eACF,OAAOnE,KAAK0D,UAEVS,aAAShE,GACX,GAAqB,kBAAVA,EAIT,MAAM,IAAIkB,MAAM,0DAHhBrB,KAAK0D,UAAYvD,EACjBH,KAAKiD,SAMLoB,gBACF,OAAOrE,KAAK4D,WAEVS,cAAUlE,GACZ,GAAqB,kBAAVA,EAIT,MAAM,IAAIkB,MAAM,2DAHhBrB,KAAK4D,WAAazD,EAClBH,KAAKiD,SAMLsB,eACF,OAAOvE,KAAK8D,UAEVS,aAASpE,GACX,GAAqB,kBAAVA,EAIT,MAAM,IAAIkB,MAAM,0DAHhBrB,KAAK8D,UAAY3D,EACjBH,KAAKiD,SAMLmB,YACF,OAAOpE,KAAK2D,OAEVS,UAAMjE,GACR,GAAqB,iBAAVA,EAIT,MAAM,IAAIkB,MAAM,kDAHhBrB,KAAK2D,OAASxD,EACdH,KAAKiD,SAMLqB,kBACF,OAAOtE,KAAK6D,aAEVS,gBAAYnE,GACd,GAAqB,iBAAVA,EAIT,MAAM,IAAIkB,MAAM,wDAHhBrB,KAAK6D,aAAe1D,EACpBH,KAAKiD,SAMLuB,WACF,OAAOxE,KAAK+D,MAAMW,WAEhBF,SAAKrE,GACP,GAAqB,iBAAVA,EAmBT,MAAM,IAAIkB,MAAM,iDAjBhB,OAAQlB,GACN,IAAK,WACL,IAAK,OACL,IAAK,QACL,IAAK,SACL,IAAK,WACL,IAAK,QACL,IAAK,SACL,IAAK,SACL,IAAK,OACHH,KAAK+D,MAAQ5D,EACbH,KAAKiD,SACL,MACF,QACE,MAAM,IAAI5B,MAAM,uEAOpBsD,eACF,OAAO3E,KAAKiE,UAGV9D,YACF,OAAOH,KAAKgE,OAEV7D,UAAMA,GACRH,KAAKiE,UAAYjE,KAAKgE,OACtBhE,KAAKgE,OAAS7D,EACdH,KAAKe,SAASZ,GACdH,KAAKiD,SAGH2B,iBACF,OAAO5E,KAAKG,MAEVyE,eAAWzE,GACbH,KAAKG,MAAQA,EAGX0E,gBACF,OAAO7E,KAAKkE,eAAehE,OAAOF,KAAK4E,YAErCC,cAAU1E,GACZH,KAAK4E,WAAa5E,KAAKkE,eAAe5D,MAAMH,GAGvC8C,SACLlD,MAAMkD,OAAOjD,KAAKgE,OAAQhE,KAAKiE,WAG1BlB,qBAAqBC,GAC1BjD,MAAMgD,qBAAqBC,EAAmBhD,KAAKG,OAG9C2E,iBAAiBC,GACtB/E,KAAKkE,eAAiBa,GAIpB,MAAOzC,UAAoBhB,EAAjCxB,kCACmBE,KAAAgF,SAA4C,IAAIrD,IAE7DwC,eACF,OAGgB,IAFdc,MAAMC,KAAKlF,KAAKgF,UAAUG,QAAQ9C,IACJ,IAArBA,EAAQ8B,WACdzD,OAGHyD,aAAShE,GACXH,KAAKgF,SAAS5E,SAASiC,IACrBA,EAAQ8B,SAAWhE,KAInBoE,eACF,OAGgB,IAFdU,MAAMC,KAAKlF,KAAKgF,UAAUG,QAAQ9C,IACJ,IAArBA,EAAQkC,WACd7D,OAGH6D,aAASpE,GACXH,KAAKgF,SAAS5E,SAASiC,IACrBA,EAAQkC,SAAWpE,KAInBgB,YACF,OACEpB,MAAMoB,OAGQ,IAFd8D,MAAMC,KAAKlF,KAAKgF,UAAUG,QAAQ9C,IACP,IAAlBA,EAAQlB,QACdT,OAIA0E,WAAW/C,GAChB,IAAmC,IAA/BrC,KAAKgF,SAASrC,IAAIN,GAIpB,MAAM,IAAIhB,MAAM,iCAAiCgB,EAAQd,yBAHzDc,EAAQI,cAAczC,MACtBA,KAAKgF,SAASpC,IAAIP,GAMfgD,cAAchD,GACnB,IAAmC,IAA/BrC,KAAKgF,SAASrC,IAAIN,GAMpB,MAAM,IAAIhB,MAAM,4BAA4BgB,EAAQd,0BALhDc,aAAmBf,IACrBe,EAAQQ,iBAAiB7C,MACzBA,KAAKgF,SAASlC,OAAOT,IAOpBiD,cACL,OAAOL,MAAMC,KAAKlF,KAAKgF,UAGlBO,WAAsChE,GAC3C,OAAO0D,MAAMC,KAAKlF,KAAKgF,UAAUQ,MAAMnD,GAC9BA,EAAQd,OAASA,IAIpBkE,WACN,OAAOR,MAAMC,KAAKlF,KAAKgF,UAAUG,QAAQ9C,GAChCA,aAAmBC,IAIvBoD,QAAQnE,GACb,OAAO0D,MAAMC,KAAKlF,KAAKyF,YAAYD,MAAMnD,GAChCA,EAAQd,OAASA,IAIpBoE,YACN,OAAOV,MAAMC,KAAKlF,KAAKgF,UAAUG,QAAQ9C,GAChCA,aAAmBmB,IAIvBoC,SAASrE,GACd,OAAO0D,MAAMC,KAAKlF,KAAK2F,aAAaH,MAAMnD,GACjCA,EAAQd,OAASA,IAOrBsE,QAAuCC,GAC5C9F,KAAKgF,SAAS5E,SAASiC,IACrB,QAA2BoC,IAAvBqB,EAAKzD,EAAQd,MACf,GAAIc,aAAmBC,EACrBD,EAAQwD,QAAQC,EAAKzD,EAAQd,WACxB,CAAA,KAAIc,aAAmBmB,GAG5B,MAAM,IAAInC,MAAM,sEAFhBgB,EAAQlC,MAAQ2F,EAAKzD,EAAQd,UAQ9B4B,UACL,MAAM2C,EAA4B,GAUlC,OATA9F,KAAKgF,SAAS5E,SAASiC,IACrB,GAAIA,aAAmBC,EACrBwD,EAAKzD,EAAQd,MAAQc,EAAQc,cACxB,CAAA,KAAId,aAAmBmB,GAG5B,MAAM,IAAInC,MAAM,sEAFhByE,EAAKzD,EAAQd,MAAQc,EAAQlC,UAK1B2F,EAGF/C,qBAAqBC,GAC1BjD,MAAMgD,qBAAqBC,UAIlB+C,EACXC,kBAAkBzE,EAAc0E,GAC9B,MAAMvD,EAAO,IAAIJ,EAAYf,GAC7B,IAAK,MAAMA,KAAQ0E,EACjB,GAAIA,EAAKC,eAAe3E,GACtB,GAA0B,iBAAf0E,EAAK1E,IAAqC,OAAf0E,EAAK1E,GACzCmB,EAAK0C,WAAWW,EAAYI,WAAW5E,EAAM0E,EAAK1E,SAC7C,CACL,MAAM6E,EAAQ,IAAI5C,EAAajC,EAAM,CACnCpB,MAAgB8F,EAAK1E,KAEvBmB,EAAK0C,WAAWgB,GAItB,OAAO1D,GCvbL,MAAO2D,UAAsB1G,EAAnCG,kCACUE,KAAMsG,OAAW,oBAElBpG,OAAOC,GACZ,GAAqB,iBAAVA,EAAoB,CAC7B,MAAMoG,EAA2BpG,EAAMqG,MAAMxG,KAAKsG,QAClD,GAAIrB,MAAMwB,QAAQF,GAChB,OAAOA,MAAAA,OAAA,EAAAA,EAASG,KAAK,KAGzB,OAAOvG,EAGFG,MAAMH,GACX,MAAqB,iBAAVA,EACFA,EAAMwG,QAAQ,KAAM,IAEtBxG,GAIE,MAAAyG,EAAyB,IAAIP,ECrBpC,MAAOQ,UAA0BtG,EACrCT,YAAYU,EAAkB,yBAC5BT,MAAMS,GAGDW,MAAMhB,GACX,OAAOA,MAAAA,GAAyCA,EAAMuE,WAAWhE,OAAS,GAIjE,MAAAoG,EAAgD,IAAID,ECT3D,MAAgBE,UAA6BxG,EAC1CY,MAAMhB,GACX,OAAmD,IAA5C2G,EAA2B3F,MAAMhB,IAAoBH,KAAKe,SAASZ,ICDxE,MAAO6G,UAAyBD,EAGpCjH,YAAYwG,EAAgB9F,EAAkB,+BAC5CT,MAAMS,GAHDR,KAAOiH,QAAW,KAIvBjH,KAAKsG,OAASA,EAGZA,WAAOA,GACLA,aAAkBY,OACpBlH,KAAKiH,QAAUX,EAEf3F,EAAAA,IAAIwG,MAAM,iEAIVb,aACF,OAAOtG,KAAKiH,QAGPlG,SAASZ,GACd,OAAOH,KAAKsG,OAAOc,KAAKjH,ICvBf,MAAAkH,EAAmC,QAE1C,MAAOC,UAAwBN,EACnClH,YAAYU,EAAkB,0BAC5BT,MAAMsH,EAA0B7G,IAIvB,MAAA+G,EAA2B,IAAID,ECP/BE,EACX,wXAEI,cAA8BR,EAClClH,YAAYU,EAAkB,iDAC5BT,MAAMyH,EAAyBhH,4GCN7B,cAA+BuG,EACnCjH,YAAYU,EAAkB,4BAC5BT,MAAMS,GAGDO,SAASZ,GACd,OAAiB,IAAVA,yBCNL,cAAkC4G,EAItCjH,YAAY2H,EAAmBjH,EAAkB,qCAAqCiH,iBACpF1H,MAAMS,GACNR,KAAKyH,UAAYA,EAGZ1G,SAASZ,GACd,MAAwB,iBAAVA,GAAsBA,EAAMO,QAAUV,KAAKyH,iCCVvD,cAAkCV,EAItCjH,YAAY4H,EAAmBlH,EAAkB,sCAAsCkH,iBACrF3H,MAAMS,GACNR,KAAK0H,UAAYA,EAGZ3G,SAASZ,GACd,MAAwB,iBAAVA,GAAsBA,EAAMO,QAAUV,KAAK0H,2DLiBvD,cAAmCV,EAChCjG,SAASZ,GACd,OAAiC,IAA1BJ,MAAMgB,SAASZ,oBM5BpB,cAA4B4G,EAIhCjH,YAAYoB,EAA8BV,GACxCT,MAAMS,GACNR,KAAKkB,UAAYA,EAGZH,SAASZ,GACd,OAAuC,IAAhCH,KAAKkB,UAAUC,MAAMhB"}
\ No newline at end of file
diff --git a/packages/components/src/assets/@leanup/lib/bundle.js b/packages/components/src/assets/@leanup/lib/bundle.js
deleted file mode 100644
index 0033da6e20..0000000000
--- a/packages/components/src/assets/@leanup/lib/bundle.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(a,p){typeof exports=="object"&&typeof module!="undefined"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(a=typeof globalThis!="undefined"?globalThis:a||self,p(a.LeanUpLib={}))})(this,function(a){"use strict";class p{constructor(){this.services=new Map}register(e,t){if(typeof e=="string"&&this.services.has(e)===!1)return this.services.set(e,t),this;throw new Error(`The service '${e}' is allready registered!`)}get(e){if(typeof e=="string"&&this.services.has(e)===!0)return this.services.get(e);throw new Error(`The service '${e}' is not registered!`)}}const D=new p;var R=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},g={exports:{}};(function(s){(function(e,t){s.exports?s.exports=t():e.log=t()})(R,function(){var e=function(){},t="undefined",f=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),c=["trace","debug","info","warn","error"];function T(n,l){var o=n[l];if(typeof o.bind=="function")return o.bind(n);try{return Function.prototype.bind.call(o,n)}catch(i){return function(){return Function.prototype.apply.apply(o,[n,arguments])}}}function j(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function k(n){return n==="debug"&&(n="log"),typeof console===t?!1:n==="trace"&&f?j:console[n]!==void 0?T(console,n):console.log!==void 0?T(console,"log"):e}function I(n,l){for(var o=0;o=0&&r<=i.levels.SILENT){if(A=r,h!==!1&&V(r),I.call(i,r,n),typeof console===t&&r=t}static isObject(e){return typeof e=="object"&&e!==null&&this.isArray(e)===!1}static isString(e,t=0){return typeof e=="string"&&e.length>=t}}const _=[];function x(){return"$$NODE_ENV$$"}class y{constructor(){}static log(e,t){switch(w.isObject(t.refObject)&&typeof t.refObject.constructor=="function"&&w.isString(t.refObject.constructor.name)&&(t.className=`[${t.refObject.constructor.name}]:`),_.push({date:new Date().toUTCString(),level:e,message:t}),e){case"trace":g.exports.trace(t);break;case"debug":g.exports.debug(t);break;case"info":g.exports.info(t);break;case"warn":g.exports.warn(t);break;case"error":g.exports.error(t)}}static trace(e,t){return this.log("trace",{messageText:e,refObject:t}),this}static debug(e,t){return this.log("debug",{messageText:e,refObject:t}),this}static info(e,t){return this.log("info",{messageText:e,refObject:t}),this}static warn(e,t){return this.log("warn",{messageText:e,refObject:t}),this}static error(e,t){return this.log("error",{messageText:e,refObject:t}),this}static get cache(){return[].concat(_)}}switch(y._instance=null,x()){case"development":g.exports.setDefaultLevel("trace");break;case"test":g.exports.setDefaultLevel("warn");break;case"production":g.exports.setDefaultLevel("error")}function F(s,e){return w.isArray(s)?s.find(t=>e instanceof t)!==void 0:!1}function L(s){return s instanceof E?s.get():Array.isArray(s)?s:[s]}class E{constructor(e){this._instancesOf=[],this._items=[],this._protectedItems=[],this._instancesOf=Array.isArray(e)?e:[e]}get empty(){return this._items.length===0}get first(){return this._items.length>0?this._items[0]:null}forEach(e){this._items.forEach(e)}filter(e){return this._items.filter(e)}find(e){return this._items.find(e)}get last(){return this._items.length>0?this._items[this._items.length-1]:null}get length(){return this._items.length}add(e,t=!1){return L(e).filter(f=>{let c=!1;return this.contains(f)===!1?F(this._instancesOf,f)?(t&&this._protectedItems.push(f),this._items.push(f),c=!0):y.debug("The item does not have a valid instance type.",this):y.debug("The item is already in the list.",this),c}).length>0}remove(e){return L(e).filter(t=>{let f=!1,c=this._protectedItems.indexOf(t);return c===-1?(c=this._items.indexOf(t),c>=0?(this._items.splice(c,1),f=!0):y.debug("The item is not in the list.",this)):y.debug("The item is protected and cannot be removed.",this),f}).length>0}set(e,t=!1){const f=this.clear(),c=this.add(e,t);return f||c}get(e){return isNaN(e)===!1&&typeof e=="number"?this._items.slice(0,e):this._items}clear(){const e=this._items.length;return this._items=this._items.filter(t=>this._protectedItems.indexOf(t)>=0),e!==this._items.length}contains(e){return this._items.indexOf(e)>-1}}const C=new Intl.NumberFormat("de-DE",{currency:"EUR",maximumFractionDigits:2,minimumFractionDigits:2});function M(s){return isNaN(s)===!1&&typeof s=="number"?C.format(s):""}const S=new Intl.DateTimeFormat("de-DE");function U(s){return s instanceof Date?S.format(s):""}a.DI=D,a.Injector=p,a.ListOf=E,a.Log=y,a.Validator=w,a.currency=M,a.date=U,Object.defineProperty(a,"__esModule",{value:!0})});
-//# sourceMappingURL=bundle.js.map
diff --git a/packages/components/src/assets/@leanup/lib/bundle.js.map b/packages/components/src/assets/@leanup/lib/bundle.js.map
deleted file mode 100644
index 8678bd7a2f..0000000000
--- a/packages/components/src/assets/@leanup/lib/bundle.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"bundle.js","sources":["../src/helpers/injector.ts","../node_modules/loglevel/lib/loglevel.js","../src/helpers/validator.ts","../src/helpers/log.ts","../src/pattern/list-of.ts","../src/shares/filters.ts"],"sourcesContent":["export class Injector {\n private readonly services: Map = new Map();\n\n public register(identifier: string, service: T): Injector {\n if (\n typeof identifier === \"string\" &&\n this.services.has(identifier) === false\n ) {\n this.services.set(identifier, service);\n return this;\n } else {\n throw new Error(`The service '${identifier}' is allready registered!`);\n }\n }\n\n public get(identifier: string): T {\n if (\n typeof identifier === \"string\" &&\n this.services.has(identifier) === true\n ) {\n return this.services.get(identifier);\n } else {\n throw new Error(`The service '${identifier}' is not registered!`);\n }\n }\n}\n\nexport const DI: Injector = new Injector();\n","/*\n* loglevel - https://github.com/pimterry/loglevel\n*\n* Copyright (c) 2013 Tim Perry\n* Licensed under the MIT license.\n*/\n(function (root, definition) {\n \"use strict\";\n if (typeof define === 'function' && define.amd) {\n define(definition);\n } else if (typeof module === 'object' && module.exports) {\n module.exports = definition();\n } else {\n root.log = definition();\n }\n}(this, function () {\n \"use strict\";\n\n // Slightly dubious tricks to cut down minimized file size\n var noop = function() {};\n var undefinedType = \"undefined\";\n var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (\n /Trident\\/|MSIE /.test(window.navigator.userAgent)\n );\n\n var logMethods = [\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\"\n ];\n\n // Cross-browser bind equivalent that works at least back to IE6\n function bindMethod(obj, methodName) {\n var method = obj[methodName];\n if (typeof method.bind === 'function') {\n return method.bind(obj);\n } else {\n try {\n return Function.prototype.bind.call(method, obj);\n } catch (e) {\n // Missing bind shim or IE8 + Modernizr, fallback to wrapping\n return function() {\n return Function.prototype.apply.apply(method, [obj, arguments]);\n };\n }\n }\n }\n\n // Trace() doesn't print the message in IE, so for that case we need to wrap it\n function traceForIE() {\n if (console.log) {\n if (console.log.apply) {\n console.log.apply(console, arguments);\n } else {\n // In old IE, native console methods themselves don't have apply().\n Function.prototype.apply.apply(console.log, [console, arguments]);\n }\n }\n if (console.trace) console.trace();\n }\n\n // Build the best logging method possible for this env\n // Wherever possible we want to bind, not wrap, to preserve stack traces\n function realMethod(methodName) {\n if (methodName === 'debug') {\n methodName = 'log';\n }\n\n if (typeof console === undefinedType) {\n return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives\n } else if (methodName === 'trace' && isIE) {\n return traceForIE;\n } else if (console[methodName] !== undefined) {\n return bindMethod(console, methodName);\n } else if (console.log !== undefined) {\n return bindMethod(console, 'log');\n } else {\n return noop;\n }\n }\n\n // These private functions always need `this` to be set properly\n\n function replaceLoggingMethods(level, loggerName) {\n /*jshint validthis:true */\n for (var i = 0; i < logMethods.length; i++) {\n var methodName = logMethods[i];\n this[methodName] = (i < level) ?\n noop :\n this.methodFactory(methodName, level, loggerName);\n }\n\n // Define log.log as an alias for log.debug\n this.log = this.debug;\n }\n\n // In old IE versions, the console isn't present until you first open it.\n // We build realMethod() replacements here that regenerate logging methods\n function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {\n return function () {\n if (typeof console !== undefinedType) {\n replaceLoggingMethods.call(this, level, loggerName);\n this[methodName].apply(this, arguments);\n }\n };\n }\n\n // By default, we use closely bound real methods wherever possible, and\n // otherwise we wait for a console to appear, and then try again.\n function defaultMethodFactory(methodName, level, loggerName) {\n /*jshint validthis:true */\n return realMethod(methodName) ||\n enableLoggingWhenConsoleArrives.apply(this, arguments);\n }\n\n function Logger(name, defaultLevel, factory) {\n var self = this;\n var currentLevel;\n\n var storageKey = \"loglevel\";\n if (typeof name === \"string\") {\n storageKey += \":\" + name;\n } else if (typeof name === \"symbol\") {\n storageKey = undefined;\n }\n\n function persistLevelIfPossible(levelNum) {\n var levelName = (logMethods[levelNum] || 'silent').toUpperCase();\n\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage[storageKey] = levelName;\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=\" + levelName + \";\";\n } catch (ignore) {}\n }\n\n function getPersistedLevel() {\n var storedLevel;\n\n if (typeof window === undefinedType || !storageKey) return;\n\n try {\n storedLevel = window.localStorage[storageKey];\n } catch (ignore) {}\n\n // Fallback to cookies if local storage gives us nothing\n if (typeof storedLevel === undefinedType) {\n try {\n var cookie = window.document.cookie;\n var location = cookie.indexOf(\n encodeURIComponent(storageKey) + \"=\");\n if (location !== -1) {\n storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];\n }\n } catch (ignore) {}\n }\n\n // If the stored level is not valid, treat it as if nothing was stored.\n if (self.levels[storedLevel] === undefined) {\n storedLevel = undefined;\n }\n\n return storedLevel;\n }\n\n /*\n *\n * Public logger API - see https://github.com/pimterry/loglevel for details\n *\n */\n\n self.name = name;\n\n self.levels = { \"TRACE\": 0, \"DEBUG\": 1, \"INFO\": 2, \"WARN\": 3,\n \"ERROR\": 4, \"SILENT\": 5};\n\n self.methodFactory = factory || defaultMethodFactory;\n\n self.getLevel = function () {\n return currentLevel;\n };\n\n self.setLevel = function (level, persist) {\n if (typeof level === \"string\" && self.levels[level.toUpperCase()] !== undefined) {\n level = self.levels[level.toUpperCase()];\n }\n if (typeof level === \"number\" && level >= 0 && level <= self.levels.SILENT) {\n currentLevel = level;\n if (persist !== false) { // defaults to true\n persistLevelIfPossible(level);\n }\n replaceLoggingMethods.call(self, level, name);\n if (typeof console === undefinedType && level < self.levels.SILENT) {\n return \"No console available for logging\";\n }\n } else {\n throw \"log.setLevel() called with invalid level: \" + level;\n }\n };\n\n self.setDefaultLevel = function (level) {\n if (!getPersistedLevel()) {\n self.setLevel(level, false);\n }\n };\n\n self.enableAll = function(persist) {\n self.setLevel(self.levels.TRACE, persist);\n };\n\n self.disableAll = function(persist) {\n self.setLevel(self.levels.SILENT, persist);\n };\n\n // Initialize with the right level\n var initialLevel = getPersistedLevel();\n if (initialLevel == null) {\n initialLevel = defaultLevel == null ? \"WARN\" : defaultLevel;\n }\n self.setLevel(initialLevel, false);\n }\n\n /*\n *\n * Top-level API\n *\n */\n\n var defaultLogger = new Logger();\n\n var _loggersByName = {};\n defaultLogger.getLogger = function getLogger(name) {\n if ((typeof name !== \"symbol\" && typeof name !== \"string\") || name === \"\") {\n throw new TypeError(\"You must supply a name when creating a logger.\");\n }\n\n var logger = _loggersByName[name];\n if (!logger) {\n logger = _loggersByName[name] = new Logger(\n name, defaultLogger.getLevel(), defaultLogger.methodFactory);\n }\n return logger;\n };\n\n // Grab the current global log variable in case of overwrite\n var _log = (typeof window !== undefinedType) ? window.log : undefined;\n defaultLogger.noConflict = function() {\n if (typeof window !== undefinedType &&\n window.log === defaultLogger) {\n window.log = _log;\n }\n\n return defaultLogger;\n };\n\n defaultLogger.getLoggers = function getLoggers() {\n return _loggersByName;\n };\n\n // ES6 default export, for compatibility\n defaultLogger['default'] = defaultLogger;\n\n return defaultLogger;\n}));\n","export class Validator {\n private constructor() {}\n\n public static isNumber(any: any): boolean {\n return isNaN(any) === false && typeof any === 'number';\n }\n\n public static isArray(any: any, minLength = 0): boolean {\n return Array.isArray(any) && any.length >= minLength;\n }\n\n public static isObject(any: any): boolean {\n return typeof any === 'object' && any !== null && this.isArray(any) === false;\n }\n\n public static isString(any: any, minLength = 0): boolean {\n return typeof any === 'string' && any.length >= minLength;\n }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-member-access */\r\nimport * as log from 'loglevel';\r\n\r\nimport { Validator } from './validator';\r\n\r\nconst LOG_CACHE: Object[] = [];\r\n\r\n/**\r\n * Tiny hack\r\n */\r\nfunction getEnvironment(): string {\r\n return '$$NODE_ENV$$';\r\n}\r\n\r\ninterface LogMessage {\r\n className?: string;\r\n messageText: string;\r\n refObject?: unknown;\r\n}\r\n\r\nexport class Log {\r\n private static _instance: Log = null;\r\n\r\n private constructor() {}\r\n\r\n private static log(level: string, message: LogMessage): void {\r\n if (\r\n Validator.isObject(message.refObject) &&\r\n typeof message.refObject.constructor === 'function' &&\r\n Validator.isString(message.refObject.constructor.name)\r\n ) {\r\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\r\n message.className = `[${message.refObject.constructor.name}]:`;\r\n }\r\n\r\n LOG_CACHE.push({\r\n date: new Date().toUTCString(),\r\n level,\r\n message,\r\n });\r\n\r\n switch (level) {\r\n case 'trace':\r\n log.trace(message);\r\n break;\r\n case 'debug':\r\n log.debug(message);\r\n break;\r\n case 'info':\r\n log.info(message);\r\n break;\r\n case 'warn':\r\n log.warn(message);\r\n break;\r\n case 'error':\r\n log.error(message);\r\n }\r\n if (getEnvironment() === 'development' && level === 'error') {\r\n throw new Error(`Execution in development mode was canceled. See the error log above.`);\r\n }\r\n }\r\n\r\n public static trace(messageText: string, refObject?: Object): Log {\r\n this.log('trace', { messageText, refObject });\r\n return this;\r\n }\r\n public static debug(messageText: string, refObject?: Object): Log {\r\n this.log('debug', { messageText, refObject });\r\n return this;\r\n }\r\n public static info(messageText: string, refObject?: Object): Log {\r\n this.log('info', { messageText, refObject });\r\n return this;\r\n }\r\n public static warn(messageText: string, refObject?: Object): Log {\r\n this.log('warn', { messageText, refObject });\r\n return this;\r\n }\r\n public static error(messageText: string, refObject?: Object): Log {\r\n this.log('error', { messageText, refObject });\r\n return this;\r\n }\r\n\r\n public static get cache(): Object[] {\r\n return [].concat(LOG_CACHE);\r\n }\r\n}\r\n\r\nswitch (getEnvironment()) {\r\n case 'development':\r\n log.setDefaultLevel('trace');\r\n break;\r\n case 'test':\r\n log.setDefaultLevel('warn');\r\n break;\r\n case 'production':\r\n log.setDefaultLevel('error');\r\n}\r\n","import { Log } from '../helpers/log';\r\nimport { Validator } from '../helpers/validator';\r\n\r\nfunction isInstanceOf(instancesOf: any[], item: any): boolean {\r\n if (Validator.isArray(instancesOf)) {\r\n return (\r\n instancesOf.find((instanceOf: any): boolean => {\r\n return item instanceof instanceOf;\r\n }) !== undefined\r\n );\r\n }\r\n return false;\r\n}\r\n\r\nfunction normalizeListOfItems(items: unknown | unknown[] | ListOf): unknown[] {\r\n return (items instanceof ListOf ? items.get() : Array.isArray(items) ? items : [items]);\r\n}\r\n\r\nexport class ListOf {\r\n private _instancesOf: unknown[] = [];\r\n private _items: T[] = [];\r\n private _protectedItems: unknown[] = [];\r\n\r\n constructor(instancesOf: unknown | unknown[]) {\r\n this._instancesOf = (Array.isArray(instancesOf) ? instancesOf : [instancesOf]);\r\n }\r\n\r\n get empty(): boolean {\r\n return this._items.length === 0;\r\n }\r\n\r\n get first(): T | null {\r\n if (this._items.length > 0) {\r\n return this._items[0];\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n public forEach(action: Function | any): void {\r\n this._items.forEach(action);\r\n }\r\n\r\n public filter(action: Function | any): T[] {\r\n return this._items.filter(action);\r\n }\r\n\r\n public find(action: Function | any): T {\r\n return this._items.find(action);\r\n }\r\n\r\n get last(): any {\r\n if (this._items.length > 0) {\r\n return this._items[this._items.length - 1];\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n get length(): number {\r\n return this._items.length;\r\n }\r\n\r\n public add(items: T | T[] | ListOf, protect = false): boolean {\r\n return (\r\n normalizeListOfItems(items).filter((item: T): boolean => {\r\n let changed = false;\r\n if (this.contains(item) === false) {\r\n if (isInstanceOf(this._instancesOf, item)) {\r\n if (protect) {\r\n this._protectedItems.push(item);\r\n }\r\n this._items.push(item);\r\n changed = true;\r\n } else {\r\n Log.debug(`The item does not have a valid instance type.`, this);\r\n }\r\n } else {\r\n Log.debug(`The item is already in the list.`, this);\r\n }\r\n return changed;\r\n }).length > 0\r\n );\r\n }\r\n\r\n public remove(items: T | T[] | ListOf): boolean {\r\n return (\r\n normalizeListOfItems(items).filter((item: any): boolean => {\r\n let changed = false;\r\n let index: number = this._protectedItems.indexOf(item);\r\n if (index === -1) {\r\n index = this._items.indexOf(item);\r\n if (index >= 0) {\r\n this._items.splice(index, 1);\r\n changed = true;\r\n } else {\r\n Log.debug(`The item is not in the list.`, this);\r\n }\r\n } else {\r\n Log.debug(`The item is protected and cannot be removed.`, this);\r\n }\r\n return changed;\r\n }).length > 0\r\n );\r\n }\r\n\r\n public set(items: T | T[] | ListOf, protect = false): any | boolean {\r\n const cleared: boolean = this.clear();\r\n const added: boolean = this.add(items, protect);\r\n return cleared || added;\r\n }\r\n\r\n public get(length?: number): T[] {\r\n return isNaN(length) === false && typeof length === 'number' ? this._items.slice(0, length) : this._items;\r\n }\r\n\r\n public clear(): boolean {\r\n const length: number = this._items.length;\r\n this._items = this._items.filter((item: T): boolean => {\r\n return this._protectedItems.indexOf(item) >= 0;\r\n });\r\n return length !== this._items.length;\r\n }\r\n\r\n public contains(item: T): boolean {\r\n return this._items.indexOf(item) > -1;\r\n }\r\n}\r\n","const CURRENCY_FORMATTER: Intl.NumberFormat = new Intl.NumberFormat('de-DE', {\n currency: 'EUR',\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n});\n\nexport function currency(value: number): string {\n if (isNaN(value) === false && typeof value === 'number') {\n return CURRENCY_FORMATTER.format(value);\n } else {\n return '';\n }\n}\n\n/**\n * https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat\n *\n * Missing config for leading 0's 1.1.1970 instead of 01.01.1970\n */\nconst DATE_FORMATTER: Intl.DateTimeFormat = new Intl.DateTimeFormat('de-DE');\n\nexport function date(value: Date): string {\n if (value instanceof Date) {\n return DATE_FORMATTER.format(value);\n } else {\n return '';\n }\n}\n"],"names":["this"],"mappings":"0PAAsB,CAAf,aAAP,eACoD,GAAI,KAE/C,SAAY,EAAoB,EAAsB,IAEzD,MAAO,IAAe,UACtB,KAAK,SAAS,IAAI,KAAgB,eAE7B,SAAS,IAAI,EAAY,GACvB,UAED,IAAI,OAAM,gBAAgB,8BAI7B,IAAO,EAAuB,IAEjC,MAAO,IAAe,UACtB,KAAK,SAAS,IAAI,KAAgB,SAExB,MAAK,SAAS,IAAI,QAEtB,IAAI,OAAM,gBAAgB,+BAKzB,GAAe,GAAI,oLCrBhC,AAAC,UAAU,EAAM,EAAY,CAIlB,AAAkC,EAAO,QAC5C,UAAiB,IAEjB,EAAK,IAAM,MAEjBA,EAAM,UAAY,CAIhB,GAAI,GAAO,UAAW,GAClB,EAAgB,YAChB,EAAQ,MAAO,UAAW,GAAmB,MAAO,QAAO,YAAc,GACzE,kBAAkB,KAAK,OAAO,UAAU,WAGxC,EAAa,CACb,QACA,QACA,OACA,OACA,SAIJ,WAAoB,EAAK,EAAY,CACjC,GAAI,GAAS,EAAI,GACjB,GAAI,MAAO,GAAO,MAAS,WACvB,MAAO,GAAO,KAAK,GAEnB,GAAI,CACA,MAAO,UAAS,UAAU,KAAK,KAAK,EAAQ,SACvC,EAAP,CAEE,MAAO,WAAW,CACd,MAAO,UAAS,UAAU,MAAM,MAAM,EAAQ,CAAC,EAAK,cAOpE,YAAsB,CAClB,AAAI,QAAQ,KACR,CAAI,QAAQ,IAAI,MACZ,QAAQ,IAAI,MAAM,QAAS,WAG3B,SAAS,UAAU,MAAM,MAAM,QAAQ,IAAK,CAAC,QAAS,aAG1D,QAAQ,OAAO,QAAQ,QAK/B,WAAoB,EAAY,CAK5B,MAJI,KAAe,SACf,GAAa,OAGb,MAAO,WAAY,EACZ,GACA,IAAe,SAAW,EAC1B,EACA,QAAQ,KAAgB,OACxB,EAAW,QAAS,GACpB,QAAQ,MAAQ,OAChB,EAAW,QAAS,OAEpB,EAMf,WAA+B,EAAO,EAAY,CAE9C,OAAS,GAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CACxC,GAAI,GAAa,EAAW,GAC5B,KAAK,GAAe,EAAI,EACpB,EACA,KAAK,cAAc,EAAY,EAAO,GAI9C,KAAK,IAAM,KAAK,MAKpB,WAAyC,EAAY,EAAO,EAAY,CACpE,MAAO,WAAY,CACf,AAAI,MAAO,WAAY,GACnB,GAAsB,KAAK,KAAM,EAAO,GACxC,KAAK,GAAY,MAAM,KAAM,aAOzC,WAA8B,EAAY,EAAO,EAAY,CAEzD,MAAO,GAAW,IACX,EAAgC,MAAM,KAAM,WAGvD,WAAgB,EAAM,EAAc,EAAS,CAC3C,GAAI,GAAO,KACP,EAEA,EAAa,WACjB,AAAI,MAAO,IAAS,SAClB,GAAc,IAAM,EACX,MAAO,IAAS,UACzB,GAAa,QAGf,WAAgC,EAAU,CACtC,GAAI,GAAa,GAAW,IAAa,UAAU,cAEnD,GAAI,QAAO,UAAW,GAAiB,CAAC,GAGxC,IAAI,CACA,OAAO,aAAa,GAAc,EAClC,aACK,EAAP,EAGF,GAAI,CACA,OAAO,SAAS,OACd,mBAAmB,GAAc,IAAM,EAAY,UAChD,EAAP,IAGN,YAA6B,CACzB,GAAI,GAEJ,GAAI,QAAO,UAAW,GAAiB,CAAC,GAExC,IAAI,CACA,EAAc,OAAO,aAAa,SAC7B,EAAP,EAGF,GAAI,MAAO,KAAgB,EACvB,GAAI,CACA,GAAI,GAAS,OAAO,SAAS,OACzB,EAAW,EAAO,QAClB,mBAAmB,GAAc,KACrC,AAAI,IAAa,IACb,GAAc,WAAW,KAAK,EAAO,MAAM,IAAW,UAErD,EAAP,EAIN,MAAI,GAAK,OAAO,KAAiB,QAC7B,GAAc,QAGX,GASX,EAAK,KAAO,EAEZ,EAAK,OAAS,CAAE,MAAS,EAAG,MAAS,EAAG,KAAQ,EAAG,KAAQ,EACvD,MAAS,EAAG,OAAU,GAE1B,EAAK,cAAgB,GAAW,EAEhC,EAAK,SAAW,UAAY,CACxB,MAAO,IAGX,EAAK,SAAW,SAAU,EAAO,EAAS,CAItC,GAHI,MAAO,IAAU,UAAY,EAAK,OAAO,EAAM,iBAAmB,QAClE,GAAQ,EAAK,OAAO,EAAM,gBAE1B,MAAO,IAAU,UAAY,GAAS,GAAK,GAAS,EAAK,OAAO,QAMhE,GALA,EAAe,EACX,IAAY,IACZ,EAAuB,GAE3B,EAAsB,KAAK,EAAM,EAAO,GACpC,MAAO,WAAY,GAAiB,EAAQ,EAAK,OAAO,OACxD,MAAO,uCAGX,MAAM,6CAA+C,GAI7D,EAAK,gBAAkB,SAAU,EAAO,CACpC,AAAK,KACD,EAAK,SAAS,EAAO,KAI7B,EAAK,UAAY,SAAS,EAAS,CAC/B,EAAK,SAAS,EAAK,OAAO,MAAO,IAGrC,EAAK,WAAa,SAAS,EAAS,CAChC,EAAK,SAAS,EAAK,OAAO,OAAQ,IAItC,GAAI,GAAe,IACnB,AAAI,GAAgB,MAChB,GAAe,GAAgB,KAAO,OAAS,GAEnD,EAAK,SAAS,EAAc,IAS9B,GAAI,GAAgB,GAAI,GAEpB,EAAiB,GACrB,EAAc,UAAY,SAAmB,EAAM,CAC/C,GAAK,MAAO,IAAS,UAAY,MAAO,IAAS,UAAa,IAAS,GACrE,KAAM,IAAI,WAAU,kDAGtB,GAAI,GAAS,EAAe,GAC5B,MAAK,IACH,GAAS,EAAe,GAAQ,GAAI,GAClC,EAAM,EAAc,WAAY,EAAc,gBAE3C,GAIX,GAAI,GAAQ,MAAO,UAAW,EAAiB,OAAO,IAAM,OAC5D,SAAc,WAAa,UAAW,CAClC,MAAI,OAAO,UAAW,GACf,OAAO,MAAQ,GAClB,QAAO,IAAM,GAGV,GAGX,EAAc,WAAa,UAAsB,CAC7C,MAAO,IAIX,EAAc,QAAa,EAEpB,gBChRY,CACb,aAAc,QAER,UAAS,EAAmB,OACjC,OAAM,KAAS,IAAS,MAAO,IAAQ,eAGlC,SAAQ,EAAU,EAAY,EAAY,OAC/C,OAAM,QAAQ,IAAQ,EAAI,QAAU,QAG/B,UAAS,EAAmB,OACjC,OAAO,IAAQ,UAAY,IAAQ,MAAQ,KAAK,QAAQ,KAAS,SAG5D,UAAS,EAAU,EAAY,EAAY,OAChD,OAAO,IAAQ,UAAY,EAAI,QAAU,GCXpD,KAAM,GAAsB,GAK5B,YAAkC,OACzB,sBASQ,CAGP,aAAc,QAEP,KAAI,EAAe,EAA2B,QAEzD,EAAU,SAAS,EAAQ,YAC3B,MAAO,GAAQ,UAAU,aAAgB,YACzC,EAAU,SAAS,EAAQ,UAAU,YAAY,UAGzC,UAAY,IAAI,EAAQ,UAAU,YAAY,YAG9C,KAAK,CACb,KAAM,GAAI,QAAO,cACjB,QACA,YAGM,OACD,wBACO,aAEP,wBACO,aAEP,sBACM,aAEN,sBACM,aAEN,wBACO,UAOF,OAAM,EAAqB,EAAyB,aAC3D,IAAI,QAAS,CAAE,cAAa,cAC1B,WAEK,OAAM,EAAqB,EAAyB,aAC3D,IAAI,QAAS,CAAE,cAAa,cAC1B,WAEK,MAAK,EAAqB,EAAyB,aAC1D,IAAI,OAAQ,CAAE,cAAa,cACzB,WAEK,MAAK,EAAqB,EAAyB,aAC1D,IAAI,OAAQ,CAAE,cAAa,cACzB,WAEK,OAAM,EAAqB,EAAyB,aAC3D,IAAI,QAAS,CAAE,cAAa,cAC1B,eAGS,QAAkB,OAC3B,GAAG,OAAO,IAIrB,OApEO,EACU,UAAiB,KAmE1B,SACD,wCACiB,mBAEjB,iCACiB,kBAEjB,uCACiB,SC7FxB,WAAsB,EAAoB,EAAoB,OACxD,GAAU,QAAQ,GAElB,EAAY,KAAK,AAAC,GACT,YAAgB,MAClB,OAGJ,GAGT,WAA8B,EAAyD,OAClE,aAAiB,GAAS,EAAM,MAAQ,MAAM,QAAQ,GAAS,EAAQ,CAAC,UAGtE,CAKrB,YAAY,EAAkC,mBAJZ,eACZ,wBACe,QAG9B,aAA2B,MAAM,QAAQ,GAAe,EAAc,CAAC,MAG1E,QAAiB,OACZ,MAAK,OAAO,SAAW,KAG5B,QAAkB,OAChB,MAAK,OAAO,OAAS,EAChB,KAAK,OAAO,GAEZ,KAIJ,QAAQ,EAA8B,MACtC,OAAO,QAAQ,GAGf,OAAO,EAA6B,OAClC,MAAK,OAAO,OAAO,GAGrB,KAAK,EAA2B,OAC9B,MAAK,OAAO,KAAK,MAGtB,OAAY,OACV,MAAK,OAAO,OAAS,EAChB,KAAK,OAAO,KAAK,OAAO,OAAS,GAEjC,QAIP,SAAiB,OACZ,MAAK,OAAO,OAGd,IAAI,EAA4B,EAAU,GAAgB,OAE7D,GAAqB,GAAO,OAAO,AAAC,GAAqB,IACnD,GAAU,SACV,MAAK,SAAS,KAAU,GACtB,EAAa,KAAK,aAAc,GAC9B,SACG,gBAAgB,KAAK,QAEvB,OAAO,KAAK,KACP,MAEN,MAAM,gDAAiD,QAGzD,MAAM,mCAAoC,MAEzC,IACN,OAAS,EAIT,OAAO,EAAqC,OAE/C,GAAqB,GAAO,OAAO,AAAC,GAAuB,IACrD,GAAU,GACV,EAAgB,KAAK,gBAAgB,QAAQ,SAC7C,KAAU,MACJ,KAAK,OAAO,QAAQ,GACxB,GAAS,QACN,OAAO,OAAO,EAAO,KAChB,MAEN,MAAM,+BAAgC,SAGxC,MAAM,+CAAgD,MAErD,IACN,OAAS,EAIT,IAAI,EAA4B,EAAU,GAAsB,MAC/D,GAAmB,KAAK,QACxB,EAAiB,KAAK,IAAI,EAAO,SAChC,IAAW,EAGb,IAAI,EAAsB,OACxB,OAAM,KAAY,IAAS,MAAO,IAAW,SAAW,KAAK,OAAO,MAAM,EAAG,GAAU,KAAK,OAG9F,OAAiB,MAChB,GAAiB,KAAK,OAAO,mBAC9B,OAAS,KAAK,OAAO,OAAO,AAAC,GACzB,KAAK,gBAAgB,QAAQ,IAAS,GAExC,IAAW,KAAK,OAAO,OAGzB,SAAS,EAAkB,OACzB,MAAK,OAAO,QAAQ,GAAQ,IC7HvC,KAAM,GAAwC,GAAI,MAAK,aAAa,QAAS,CAC3E,SAAU,MACV,sBAAuB,EACvB,sBAAuB,eAGA,EAAuB,OAC1C,OAAM,KAAW,IAAS,MAAO,IAAU,SACtC,EAAmB,OAAO,GAE1B,GASX,KAAM,GAAsC,GAAI,MAAK,eAAe,oBAE/C,EAAqB,OACpC,aAAiB,MACZ,EAAe,OAAO,GAEtB"}
\ No newline at end of file
diff --git a/packages/components/src/assets/@leanup/lib/index.js b/packages/components/src/assets/@leanup/lib/index.js
deleted file mode 100644
index d97df3f8f6..0000000000
--- a/packages/components/src/assets/@leanup/lib/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LeanUpLib={})}(this,(function(e){"use strict";class t extends HTMLElement{constructor(){super(),this.dom=this}render(){}connectedCallback(){this.render()}}class o{constructor(){this.services=new Map,this.lazyLoaders=new Set}register(e,t,o={lazy:!1}){if("string"==typeof e&&!1===this.services.has(e))return this.services.set(e,t),!0===(null==o?void 0:o.lazy)&&this.lazyLoaders.add(e),this;throw new Error(`The service '${e}' is allready registered!`)}get(e){if(this.lazyLoaders.has(e)&&(this.services.set(e,this.services.get(e)()),this.lazyLoaders.delete(e)),"string"==typeof e&&!0===this.services.has(e))return this.services.get(e);throw new Error(`The service '${e}' is not registered!`)}}const i=new o;var r="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},s={exports:{}};!function(e){var t,o;t=r,o=function(){var e=function(){},t="undefined",o=typeof window!==t&&typeof window.navigator!==t&&/Trident\/|MSIE /.test(window.navigator.userAgent),i=["trace","debug","info","warn","error"];function r(e,t){var o=e[t];if("function"==typeof o.bind)return o.bind(e);try{return Function.prototype.bind.call(o,e)}catch(t){return function(){return Function.prototype.apply.apply(o,[e,arguments])}}}function s(){console.log&&(console.log.apply?console.log.apply(console,arguments):Function.prototype.apply.apply(console.log,[console,arguments])),console.trace&&console.trace()}function n(i){return"debug"===i&&(i="log"),typeof console!==t&&("trace"===i&&o?s:void 0!==console[i]?r(console,i):void 0!==console.log?r(console,"log"):e)}function l(t,o){for(var r=0;r=0&&o<=n.levels.SILENT))throw"log.setLevel() called with invalid level: "+o;if(s=o,!1!==r&&function(e){var o=(i[e]||"silent").toUpperCase();if(typeof window!==t&&a){try{return void(window.localStorage[a]=o)}catch(e){}try{window.document.cookie=encodeURIComponent(a)+"="+o+";"}catch(e){}}}(o),l.call(n,o,e),typeof console===t&&o0?t.shieldStyle:"color: white; background: #666; font-weight: bold; font-size: 10px; padding: 2px 6px; border-radius: 3px; border: 1px solid #000"]}static getInstance(e,t={}){if("string"==typeof e&&e.length>0)return!1===l.instances.has(e)&&l.instances.set(e,new l(e)),l.instances.get(e);throw new Error("The identifier of the Logger must be a string with a min length of 1.")}log(e,t){switch("object"==typeof t.refObject&&null!==t.refObject&&"function"==typeof t.refObject.constructor&&"string"==typeof t.refObject.constructor.name&&(t.className=`[${t.refObject.constructor.name}]:`),n.push({date:(new Date).toUTCString(),level:e,message:t}),e){case"trace":s.exports.trace(...this.shield,t);break;case"debug":s.exports.debug(...this.shield,t);break;case"info":s.exports.info(...this.shield,t);break;case"warn":s.exports.warn(...this.shield,t);break;default:if(s.exports.error(...this.shield,t),"error"===e)throw new Error("↑ Execution in development mode was canceled. See the error log above.")}}trace(e,t){return this.log("trace",{messageText:e,refObject:t}),this}debug(e,t){return this.log("debug",{messageText:e,refObject:t}),this}info(e,t){return this.log("info",{messageText:e,refObject:t}),this}warn(e,t){return this.log("warn",{messageText:e,refObject:t}),this}error(e,t){return this.log("error",{messageText:e,refObject:t}),this}static get cache(){return[].concat(n)}}l.instances=new Map,s.exports.setDefaultLevel("trace");const a=l.getInstance("leanup");function c(e){return e instanceof d?e.get():Array.isArray(e)?e:[e]}class d{constructor(e){this.items=new Set,this.protectedItems=new Set,this.instancesOf=Array.isArray(e)?e:[e]}get empty(){return 0===this.items.size}get first(){return this.items.size>0?Array.from(this.items)[0]:null}forEach(e){this.items.forEach(e)}filter(e){return Array.from(this.items).filter(e)}find(e){return Array.from(this.items).find(e)}get last(){return this.items.size>0?Array.from(this.items)[this.items.size-1]:null}get length(){return a.debug("The attribute ListOf.length is deprecated - please use ListOf.size instead."),this.size}get size(){return this.items.size}add(e,t=!1){return c(e).filter((e=>{let o=!1;return!1===this.has(e)?!function(e,t){return!!Array.isArray(e)&&void 0!==e.find((e=>t instanceof e))}(this.instancesOf,e)?a.debug("The item does not have a valid instance type.",this):(t&&this.protectedItems.add(e),this.items.add(e),o=!0):a.debug("The item is already in the list.",this),o})).length>0}remove(e){return a.debug("The method ListOf.remove() is deprecated - please use ListOf.delete() instead."),this.delete(e)}delete(e){return c(e).filter((e=>{let t=!1;return!1===this.protectedItems.has(e)?this.items.has(e)?(this.items.delete(e),t=!0):a.debug("The item is not in the list.",this):a.debug("The item is protected and cannot be removed.",this),t})).length>0}set(e,t=!1){const o=this.clear(),i=this.add(e,t);return o||i}get(e){return!1===isNaN(e)&&"number"==typeof e?Array.from(this.items).slice(0,e):Array.from(this.items)}clear(){const e=this.items.size;return this.items.forEach((e=>{!1===this.protectedItems.has(e)&&this.items.delete(e)})),e!==this.items.size}contains(e){return a.debug("The method ListOf.contains() is deprecated - please use ListOf.has() instead."),this.items.has(e)}has(e){return this.items.has(e)}}const h=new Intl.NumberFormat("de-DE",{currency:"EUR",maximumFractionDigits:2,minimumFractionDigits:2});const u=new Intl.DateTimeFormat("de-DE");e.AbstractController=class{constructor(e){this.couple=e}doDistroy(){var e,t,o,i;"function"==typeof(null===(t=null===(e=this.couple)||void 0===e?void 0:e.hooks)||void 0===t?void 0:t.doDistroy)&&(null===(i=null===(o=this.couple)||void 0===o?void 0:o.hooks)||void 0===i||i.doDistroy())}doRender(){var e,t;"function"==typeof(null===(t=null===(e=this.couple)||void 0===e?void 0:e.hooks)||void 0===t?void 0:t.doRender)&&(clearTimeout(this.doRenderTimeout),this.doRenderTimeout=setTimeout((()=>{var e,t;null===(t=null===(e=this.couple)||void 0===e?void 0:e.hooks)||void 0===t||t.doRender()}),50))}},e.ArchController=()=>()=>{},e.ArchModel=()=>()=>{},e.ArchService=()=>()=>{},e.ArchView=()=>()=>{},e.DI=i,e.Injector=o,e.Log=a,e.Logger=l,e.SetOf=d,e.VanillaComponent=t,e.currency=function(e){return!1===isNaN(e)&&"number"==typeof e?h.format(e):""},e.date=function(e){return e instanceof Date?u.format(e):""},Object.defineProperty(e,"__esModule",{value:!0})}));
-//# sourceMappingURL=index.js.map
diff --git a/packages/components/src/assets/@leanup/lib/index.js.map b/packages/components/src/assets/@leanup/lib/index.js.map
deleted file mode 100644
index 42a5b43699..0000000000
--- a/packages/components/src/assets/@leanup/lib/index.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"index.js","sources":["../src/components/vanilla.ts","../src/helpers/injector.ts","../node_modules/loglevel/lib/loglevel.js","../src/helpers/log.ts","../src/pattern/list-of.ts","../src/shares/filters.ts","../src/architecture/controller.ts","../src/architecture/decorators.ts"],"sourcesContent":[null,null,"/*\n* loglevel - https://github.com/pimterry/loglevel\n*\n* Copyright (c) 2013 Tim Perry\n* Licensed under the MIT license.\n*/\n(function (root, definition) {\n \"use strict\";\n if (typeof define === 'function' && define.amd) {\n define(definition);\n } else if (typeof module === 'object' && module.exports) {\n module.exports = definition();\n } else {\n root.log = definition();\n }\n}(this, function () {\n \"use strict\";\n\n // Slightly dubious tricks to cut down minimized file size\n var noop = function() {};\n var undefinedType = \"undefined\";\n var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (\n /Trident\\/|MSIE /.test(window.navigator.userAgent)\n );\n\n var logMethods = [\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\"\n ];\n\n // Cross-browser bind equivalent that works at least back to IE6\n function bindMethod(obj, methodName) {\n var method = obj[methodName];\n if (typeof method.bind === 'function') {\n return method.bind(obj);\n } else {\n try {\n return Function.prototype.bind.call(method, obj);\n } catch (e) {\n // Missing bind shim or IE8 + Modernizr, fallback to wrapping\n return function() {\n return Function.prototype.apply.apply(method, [obj, arguments]);\n };\n }\n }\n }\n\n // Trace() doesn't print the message in IE, so for that case we need to wrap it\n function traceForIE() {\n if (console.log) {\n if (console.log.apply) {\n console.log.apply(console, arguments);\n } else {\n // In old IE, native console methods themselves don't have apply().\n Function.prototype.apply.apply(console.log, [console, arguments]);\n }\n }\n if (console.trace) console.trace();\n }\n\n // Build the best logging method possible for this env\n // Wherever possible we want to bind, not wrap, to preserve stack traces\n function realMethod(methodName) {\n if (methodName === 'debug') {\n methodName = 'log';\n }\n\n if (typeof console === undefinedType) {\n return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives\n } else if (methodName === 'trace' && isIE) {\n return traceForIE;\n } else if (console[methodName] !== undefined) {\n return bindMethod(console, methodName);\n } else if (console.log !== undefined) {\n return bindMethod(console, 'log');\n } else {\n return noop;\n }\n }\n\n // These private functions always need `this` to be set properly\n\n function replaceLoggingMethods(level, loggerName) {\n /*jshint validthis:true */\n for (var i = 0; i < logMethods.length; i++) {\n var methodName = logMethods[i];\n this[methodName] = (i < level) ?\n noop :\n this.methodFactory(methodName, level, loggerName);\n }\n\n // Define log.log as an alias for log.debug\n this.log = this.debug;\n }\n\n // In old IE versions, the console isn't present until you first open it.\n // We build realMethod() replacements here that regenerate logging methods\n function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {\n return function () {\n if (typeof console !== undefinedType) {\n replaceLoggingMethods.call(this, level, loggerName);\n this[methodName].apply(this, arguments);\n }\n };\n }\n\n // By default, we use closely bound real methods wherever possible, and\n // otherwise we wait for a console to appear, and then try again.\n function defaultMethodFactory(methodName, level, loggerName) {\n /*jshint validthis:true */\n return realMethod(methodName) ||\n enableLoggingWhenConsoleArrives.apply(this, arguments);\n }\n\n function Logger(name, defaultLevel, factory) {\n var self = this;\n var currentLevel;\n defaultLevel = defaultLevel == null ? \"WARN\" : defaultLevel;\n\n var storageKey = \"loglevel\";\n if (typeof name === \"string\") {\n storageKey += \":\" + name;\n } else if (typeof name === \"symbol\") {\n storageKey = undefined;\n }\n\n function persistLevelIfPossible(levelNum) {\n var levelName = (logMethods[levelNum] || 'silent').toUpperCase();\n\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage[storageKey] = levelName;\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=\" + levelName + \";\";\n } catch (ignore) {}\n }\n\n function getPersistedLevel() {\n var storedLevel;\n\n if (typeof window === undefinedType || !storageKey) return;\n\n try {\n storedLevel = window.localStorage[storageKey];\n } catch (ignore) {}\n\n // Fallback to cookies if local storage gives us nothing\n if (typeof storedLevel === undefinedType) {\n try {\n var cookie = window.document.cookie;\n var location = cookie.indexOf(\n encodeURIComponent(storageKey) + \"=\");\n if (location !== -1) {\n storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];\n }\n } catch (ignore) {}\n }\n\n // If the stored level is not valid, treat it as if nothing was stored.\n if (self.levels[storedLevel] === undefined) {\n storedLevel = undefined;\n }\n\n return storedLevel;\n }\n\n function clearPersistedLevel() {\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage.removeItem(storageKey);\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC\";\n } catch (ignore) {}\n }\n\n /*\n *\n * Public logger API - see https://github.com/pimterry/loglevel for details\n *\n */\n\n self.name = name;\n\n self.levels = { \"TRACE\": 0, \"DEBUG\": 1, \"INFO\": 2, \"WARN\": 3,\n \"ERROR\": 4, \"SILENT\": 5};\n\n self.methodFactory = factory || defaultMethodFactory;\n\n self.getLevel = function () {\n return currentLevel;\n };\n\n self.setLevel = function (level, persist) {\n if (typeof level === \"string\" && self.levels[level.toUpperCase()] !== undefined) {\n level = self.levels[level.toUpperCase()];\n }\n if (typeof level === \"number\" && level >= 0 && level <= self.levels.SILENT) {\n currentLevel = level;\n if (persist !== false) { // defaults to true\n persistLevelIfPossible(level);\n }\n replaceLoggingMethods.call(self, level, name);\n if (typeof console === undefinedType && level < self.levels.SILENT) {\n return \"No console available for logging\";\n }\n } else {\n throw \"log.setLevel() called with invalid level: \" + level;\n }\n };\n\n self.setDefaultLevel = function (level) {\n defaultLevel = level;\n if (!getPersistedLevel()) {\n self.setLevel(level, false);\n }\n };\n\n self.resetLevel = function () {\n self.setLevel(defaultLevel, false);\n clearPersistedLevel();\n };\n\n self.enableAll = function(persist) {\n self.setLevel(self.levels.TRACE, persist);\n };\n\n self.disableAll = function(persist) {\n self.setLevel(self.levels.SILENT, persist);\n };\n\n // Initialize with the right level\n var initialLevel = getPersistedLevel();\n if (initialLevel == null) {\n initialLevel = defaultLevel;\n }\n self.setLevel(initialLevel, false);\n }\n\n /*\n *\n * Top-level API\n *\n */\n\n var defaultLogger = new Logger();\n\n var _loggersByName = {};\n defaultLogger.getLogger = function getLogger(name) {\n if ((typeof name !== \"symbol\" && typeof name !== \"string\") || name === \"\") {\n throw new TypeError(\"You must supply a name when creating a logger.\");\n }\n\n var logger = _loggersByName[name];\n if (!logger) {\n logger = _loggersByName[name] = new Logger(\n name, defaultLogger.getLevel(), defaultLogger.methodFactory);\n }\n return logger;\n };\n\n // Grab the current global log variable in case of overwrite\n var _log = (typeof window !== undefinedType) ? window.log : undefined;\n defaultLogger.noConflict = function() {\n if (typeof window !== undefinedType &&\n window.log === defaultLogger) {\n window.log = _log;\n }\n\n return defaultLogger;\n };\n\n defaultLogger.getLoggers = function getLoggers() {\n return _loggersByName;\n };\n\n // ES6 default export, for compatibility\n defaultLogger['default'] = defaultLogger;\n\n return defaultLogger;\n}));\n",null,null,null,null,null],"names":["VanillaComponent","HTMLElement","constructor","super","this","dom","render","connectedCallback","Injector","services","Map","lazyLoaders","Set","register","identifier","lazyLoaderOrService","options","lazy","has","set","add","Error","get","delete","DI","root","definition","noop","undefinedType","isIE","window","navigator","test","userAgent","logMethods","bindMethod","obj","methodName","method","bind","Function","prototype","call","e","apply","arguments","traceForIE","console","log","trace","realMethod","undefined","replaceLoggingMethods","level","loggerName","i","length","methodFactory","debug","enableLoggingWhenConsoleArrives","defaultMethodFactory","Logger","name","defaultLevel","factory","currentLevel","self","storageKey","getPersistedLevel","storedLevel","localStorage","ignore","cookie","document","location","indexOf","encodeURIComponent","exec","slice","levels","TRACE","DEBUG","INFO","WARN","ERROR","SILENT","getLevel","setLevel","persist","toUpperCase","levelNum","levelName","persistLevelIfPossible","setDefaultLevel","resetLevel","removeItem","clearPersistedLevel","enableAll","disableAll","initialLevel","defaultLogger","_loggersByName","getLogger","TypeError","logger","_log","noConflict","getLoggers","module","exports","LOG_CACHE","shield","shieldStyle","static","instances","message","refObject","className","push","date","Date","toUTCString","loglevel.trace","loglevel.debug","loglevel.info","loglevel.warn","loglevel.error","messageText","info","warn","error","cache","concat","loglevel.setDefaultLevel","Log","getInstance","normalizeSetOfItems","items","SetOf","Array","isArray","instancesOf","protectedItems","empty","size","first","from","forEach","action","filter","find","last","protect","item","changed","instanceOf","isInstanceOf","remove","cleared","clear","added","isNaN","contains","CURRENCY_FORMATTER","Intl","NumberFormat","currency","maximumFractionDigits","minimumFractionDigits","DATE_FORMATTER","DateTimeFormat","couple","doDistroy","_b","_a","hooks","_d","_c","doRender","clearTimeout","doRenderTimeout","setTimeout","value","format"],"mappings":"iPAAM,MAAOA,UAAyBC,YAGpCC,cACEC,QACAC,KAAKC,IAAMD,KAMHE,UAEHC,oBACLH,KAAKE,gBCRIE,EAAbN,cACmBE,KAAAK,SAAW,IAAIC,IACfN,KAAAO,YAAc,IAAIC,IAE5BC,SACLC,EACAC,EACAC,EAA2B,CACzBC,MAAM,IAGR,GAA0B,iBAAfH,IAA6D,IAAlCV,KAAKK,SAASS,IAAIJ,GAKtD,OAJAV,KAAKK,SAASU,IAAIL,EAAYC,IACR,KAAlBC,MAAAA,OAAO,EAAPA,EAASC,OACXb,KAAKO,YAAYS,IAAIN,GAEhBV,KAEP,MAAM,IAAIiB,MAAM,gBAAgBP,8BAI7BQ,IAAOR,GAKZ,GAJIV,KAAKO,YAAYO,IAAIJ,KACvBV,KAAKK,SAASU,IAAIL,EAA4BV,KAAKK,SAASa,IAAIR,EAAlBV,IAC9CA,KAAKO,YAAYY,OAAOT,IAEA,iBAAfA,IAA6D,IAAlCV,KAAKK,SAASS,IAAIJ,GACtD,OAAUV,KAAKK,SAASa,IAAIR,GAE5B,MAAM,IAAIO,MAAM,gBAAgBP,0BAKzB,MAAAU,EAAe,IAAIhB,mLCnC/B,IAAUiB,EAAMC,EAAND,EASTrB,EATesB,EAST,WAIJ,IAAIC,EAAO,aACPC,EAAgB,YAChBC,SAAeC,SAAWF,UAA0BE,OAAOC,YAAcH,GACzE,kBAAkBI,KAAKF,OAAOC,UAAUE,WAGxCC,EAAa,CACb,QACA,QACA,OACA,OACA,SAIJ,SAASC,EAAWC,EAAKC,GACrB,IAAIC,EAASF,EAAIC,GACjB,GAA2B,mBAAhBC,EAAOC,KACd,OAAOD,EAAOC,KAAKH,GAEnB,IACI,OAAOI,SAASC,UAAUF,KAAKG,KAAKJ,EAAQF,GAC9C,MAAOO,GAEL,OAAO,WACH,OAAOH,SAASC,UAAUG,MAAMA,MAAMN,EAAQ,CAACF,EAAKS,cAOpE,SAASC,IACDC,QAAQC,MACJD,QAAQC,IAAIJ,MACZG,QAAQC,IAAIJ,MAAMG,QAASF,WAG3BL,SAASC,UAAUG,MAAMA,MAAMG,QAAQC,IAAK,CAACD,QAASF,aAG1DE,QAAQE,OAAOF,QAAQE,QAK/B,SAASC,EAAWb,GAKhB,MAJmB,UAAfA,IACAA,EAAa,cAGNU,UAAYnB,IAEG,UAAfS,GAA0BR,EAC1BiB,OACwBK,IAAxBJ,QAAQV,GACRF,EAAWY,QAASV,QACJc,IAAhBJ,QAAQC,IACRb,EAAWY,QAAS,OAEpBpB,GAMf,SAASyB,EAAsBC,EAAOC,GAElC,IAAK,IAAIC,EAAI,EAAGA,EAAIrB,EAAWsB,OAAQD,IAAK,CACxC,IAAIlB,EAAaH,EAAWqB,GAC5BnD,KAAKiC,GAAekB,EAAIF,EACpB1B,EACAvB,KAAKqD,cAAcpB,EAAYgB,EAAOC,GAI9ClD,KAAK4C,IAAM5C,KAAKsD,MAKpB,SAASC,EAAgCtB,EAAYgB,EAAOC,GACxD,OAAO,kBACQP,UAAYnB,IACnBwB,EAAsBV,KAAKtC,KAAMiD,EAAOC,GACxClD,KAAKiC,GAAYO,MAAMxC,KAAMyC,aAOzC,SAASe,EAAqBvB,EAAYgB,EAAOC,GAE7C,OAAOJ,EAAWb,IACXsB,EAAgCf,MAAMxC,KAAMyC,WAGvD,SAASgB,EAAOC,EAAMC,EAAcC,GAClC,IACIC,EADAC,EAAO9D,KAEX2D,EAA+B,MAAhBA,EAAuB,OAASA,EAE/C,IAAII,EAAa,WAyBjB,SAASC,IACL,IAAIC,EAEJ,UAAWvC,SAAWF,GAAkBuC,EAAxC,CAEA,IACIE,EAAcvC,OAAOwC,aAAaH,GACpC,MAAOI,IAGT,UAAWF,IAAgBzC,EACvB,IACI,IAAI4C,EAAS1C,OAAO2C,SAASD,OACzBE,EAAWF,EAAOG,QAClBC,mBAAmBT,GAAc,MACnB,IAAdO,IACAL,EAAc,WAAWQ,KAAKL,EAAOM,MAAMJ,IAAW,IAE5D,MAAOH,IAQb,YAJiCpB,IAA7Be,EAAKa,OAAOV,KACZA,OAAclB,GAGXkB,GAlDS,iBAATP,EACTK,GAAc,IAAML,EACK,iBAATA,IAChBK,OAAahB,GAwEfe,EAAKJ,KAAOA,EAEZI,EAAKa,OAAS,CAAEC,MAAS,EAAGC,MAAS,EAAGC,KAAQ,EAAGC,KAAQ,EACvDC,MAAS,EAAGC,OAAU,GAE1BnB,EAAKT,cAAgBO,GAAWJ,EAEhCM,EAAKoB,SAAW,WACZ,OAAOrB,GAGXC,EAAKqB,SAAW,SAAUlC,EAAOmC,GAI7B,GAHqB,iBAAVnC,QAA2DF,IAArCe,EAAKa,OAAO1B,EAAMoC,iBAC/CpC,EAAQa,EAAKa,OAAO1B,EAAMoC,kBAET,iBAAVpC,GAAsBA,GAAS,GAAKA,GAASa,EAAKa,OAAOM,QAUhE,KAAM,6CAA+ChC,EAJrD,GALAY,EAAeZ,GACC,IAAZmC,GAtFZ,SAAgCE,GAC5B,IAAIC,GAAazD,EAAWwD,IAAa,UAAUD,cAEnD,UAAW3D,SAAWF,GAAkBuC,EAAxC,CAGA,IAEI,YADArC,OAAOwC,aAAaH,GAAcwB,GAEpC,MAAOpB,IAGT,IACIzC,OAAO2C,SAASD,OACdI,mBAAmBT,GAAc,IAAMwB,EAAY,IACvD,MAAOpB,MAwEDqB,CAAuBvC,GAE3BD,EAAsBV,KAAKwB,EAAMb,EAAOS,UAC7Bf,UAAYnB,GAAiByB,EAAQa,EAAKa,OAAOM,OACxD,MAAO,oCAOnBnB,EAAK2B,gBAAkB,SAAUxC,GAC7BU,EAAeV,EACVe,KACDF,EAAKqB,SAASlC,GAAO,IAI7Ba,EAAK4B,WAAa,WACd5B,EAAKqB,SAASxB,GAAc,GA3DhC,WACI,UAAWjC,SAAWF,GAAkBuC,EAAxC,CAGA,IAEI,YADArC,OAAOwC,aAAayB,WAAW5B,GAEjC,MAAOI,IAGT,IACIzC,OAAO2C,SAASD,OACdI,mBAAmBT,GAAc,2CACrC,MAAOI,MA+CTyB,IAGJ9B,EAAK+B,UAAY,SAAST,GACtBtB,EAAKqB,SAASrB,EAAKa,OAAOC,MAAOQ,IAGrCtB,EAAKgC,WAAa,SAASV,GACvBtB,EAAKqB,SAASrB,EAAKa,OAAOM,OAAQG,IAItC,IAAIW,EAAe/B,IACC,MAAhB+B,IACAA,EAAepC,GAEnBG,EAAKqB,SAASY,GAAc,GAS9B,IAAIC,EAAgB,IAAIvC,EAEpBwC,EAAiB,GACrBD,EAAcE,UAAY,SAAmBxC,GACzC,GAAqB,iBAATA,GAAqC,iBAATA,GAA+B,KAATA,EAC5D,MAAM,IAAIyC,UAAU,kDAGtB,IAAIC,EAASH,EAAevC,GAK5B,OAJK0C,IACHA,EAASH,EAAevC,GAAQ,IAAID,EAClCC,EAAMsC,EAAcd,WAAYc,EAAc3C,gBAE3C+C,GAIX,IAAIC,SAAe3E,SAAWF,EAAiBE,OAAOkB,SAAMG,EAiB5D,OAhBAiD,EAAcM,WAAa,WAMvB,cALW5E,SAAWF,GACfE,OAAOkB,MAAQoD,IAClBtE,OAAOkB,IAAMyD,GAGVL,GAGXA,EAAcO,WAAa,WACvB,OAAON,GAIXD,EAAuB,QAAIA,EAEpBA,GA7RkCQ,EAAOC,QAC5CD,EAAAC,QAAiBnF,IAEjBD,EAAKuB,IAAMtB,QCVnB,MAAMoF,EAAsB,SAmBfjD,EAKX3D,YAAoBY,EAAoBE,EAAyB,IAC/DZ,KAAK2G,OAAS,CACZ,KAAKjG,IAC0B,iBAAxBE,EAAQgG,aAA4BhG,EAAQgG,YAAYxD,OAAS,EACpExC,EAAQgG,YACR,oIAIDC,mBAAmBnG,EAAoBE,EAAyB,IACrE,GAA0B,iBAAfF,GAA2BA,EAAW0C,OAAS,EAIxD,OAHyC,IAArCK,EAAOqD,UAAUhG,IAAIJ,IACvB+C,EAAOqD,UAAU/F,IAAIL,EAAY,IAAI+C,EAAO/C,IAEvC+C,EAAOqD,UAAU5F,IAAIR,GAE5B,MAAM,IAAIO,MAAM,yEAIZ2B,IAAIK,EAAe8D,GAiBzB,OAf+B,iBAAtBA,EAAQC,WACO,OAAtBD,EAAQC,WACiC,mBAAlCD,EAAQC,UAAUlH,aACqB,iBAAvCiH,EAAQC,UAAUlH,YAAY4D,OAGrCqD,EAAQE,UAAY,IAAIF,EAAQC,UAAUlH,YAAY4D,UAGxDgD,EAAUQ,KAAK,CACbC,MAAM,IAAIC,MAAOC,cACjBpE,MAAAA,EACA8D,QAAAA,IAGM9D,GACN,IAAK,QACHqE,EAAAA,QAAAA,SAAkBtH,KAAK2G,OAAQI,GAC/B,MACF,IAAK,QACHQ,EAAAA,QAAAA,SAAkBvH,KAAK2G,OAAQI,GAC/B,MACF,IAAK,OACHS,EAAAA,QAAAA,QAAiBxH,KAAK2G,OAAQI,GAC9B,MACF,IAAK,OACHU,EAAAA,QAAAA,QAAiBzH,KAAK2G,OAAQI,GAC9B,MAEF,QAEE,GADAW,EAAAA,QAAAA,SAAkB1H,KAAK2G,OAAQI,GACqB,UAAV9D,EACxC,MAAM,IAAIhC,MAAM,2EAKjB4B,MAAM8E,EAAqBX,GAEhC,OADAhH,KAAK4C,IAAI,QAAS,CAAE+E,YAAAA,EAAaX,UAAAA,IAC1BhH,KAEFsD,MAAMqE,EAAqBX,GAEhC,OADAhH,KAAK4C,IAAI,QAAS,CAAE+E,YAAAA,EAAaX,UAAAA,IAC1BhH,KAEF4H,KAAKD,EAAqBX,GAE/B,OADAhH,KAAK4C,IAAI,OAAQ,CAAE+E,YAAAA,EAAaX,UAAAA,IACzBhH,KAEF6H,KAAKF,EAAqBX,GAE/B,OADAhH,KAAK4C,IAAI,OAAQ,CAAE+E,YAAAA,EAAaX,UAAAA,IACzBhH,KAEF8H,MAAMH,EAAqBX,GAEhC,OADAhH,KAAK4C,IAAI,QAAS,CAAE+E,YAAAA,EAAaX,UAAAA,IAC1BhH,KAGS+H,mBAChB,MAAO,GAAGC,OAAOtB,IArFKjD,EAAAqD,UAAiC,IAAIxG,IA2F3D2H,EAAwBxB,QAAAhB,gBAAC,SAUhB,MAAAyC,EAAczE,EAAO0E,YAAY,UC/G9C,SAASC,EAAoBC,GAC3B,OAAmBA,aAAiBC,EAAQD,EAAMnH,MAAQqH,MAAMC,QAAQH,GAASA,EAAQ,CAACA,SAG/EC,EAKXxI,YAAY2I,GAHJzI,KAAAqI,MAAgB,IAAI7H,IACpBR,KAAA0I,eAAyB,IAAIlI,IAGnCR,KAAKyI,YAA6CF,MAAMC,QAAQC,GAAeA,EAAc,CAACA,GAG5FE,YACF,OAA2B,IAApB3I,KAAKqI,MAAMO,KAGhBC,YACF,OAAI7I,KAAKqI,MAAMO,KAAO,EACbL,MAAMO,KAAK9I,KAAKqI,OAAO,GAEvB,KAIJU,QAAQC,GACbhJ,KAAKqI,MAAMU,QAAQC,GAGdC,OAAOD,GACZ,OAAOT,MAAMO,KAAK9I,KAAKqI,OAAOY,OAAOD,GAGhCE,KAAKF,GACV,OAAOT,MAAMO,KAAK9I,KAAKqI,OAAOa,KAAKF,GAGjCG,WACF,OAAInJ,KAAKqI,MAAMO,KAAO,EACbL,MAAMO,KAAK9I,KAAKqI,OAAOrI,KAAKqI,MAAMO,KAAO,GAEzC,KAIPxF,aAEF,OADA8E,EAAI5E,MAAM,+EACHtD,KAAK4I,KAGVA,WACF,OAAO5I,KAAKqI,MAAMO,KAGb5H,IAAIqH,EAA2Be,GAAU,GAC9C,OACEhB,EAAoBC,GAAOY,QAAQI,IACjC,IAAIC,GAAU,EAcd,OAbuB,IAAnBtJ,KAAKc,IAAIuI,IArErB,SAAsBZ,EAAoBY,GACxC,QAAId,MAAMC,QAAQC,SAIP1F,IAFP0F,EAAYS,MAAMK,GACTF,aAAgBE,IAkEjBC,CAAaxJ,KAAKyI,YAAaY,GAOjCnB,EAAI5E,MAAM,gDAAiDtD,OANvDoJ,GACFpJ,KAAK0I,eAAe1H,IAAIqI,GAE1BrJ,KAAKqI,MAAMrH,IAAIqI,GACfC,GAAU,GAKZpB,EAAI5E,MAAM,mCAAoCtD,MAEzCsJ,KACNlG,OAAS,EAITqG,OAAOpB,GAEZ,OADAH,EAAI5E,MAAM,kFACHtD,KAAKmB,OAAOkH,GAGdlH,OAAOkH,GACZ,OACED,EAAoBC,GAAOY,QAAQI,IACjC,IAAIC,GAAU,EAWd,OAVsC,IAAlCtJ,KAAK0I,eAAe5H,IAAIuI,GACtBrJ,KAAKqI,MAAMvH,IAAIuI,IACjBrJ,KAAKqI,MAAMlH,OAAOkI,GAClBC,GAAU,GAEVpB,EAAI5E,MAAM,+BAAgCtD,MAG5CkI,EAAI5E,MAAM,+CAAgDtD,MAErDsJ,KACNlG,OAAS,EAITrC,IAAIsH,EAA2Be,GAAU,GAC9C,MAAMM,EAAmB1J,KAAK2J,QACxBC,EAAiB5J,KAAKgB,IAAIqH,EAAOe,GACvC,OAAOM,GAAWE,EAGb1I,IAAIkC,GACT,OAAyB,IAAlByG,MAAMzG,IAAuC,iBAAXA,EACrCmF,MAAMO,KAAK9I,KAAKqI,OAAO3D,MAAM,EAAGtB,GAChCmF,MAAMO,KAAK9I,KAAKqI,OAGfsB,QACL,MAAMf,EAAe5I,KAAKqI,MAAMO,KAMhC,OALA5I,KAAKqI,MAAMU,SAASM,KACoB,IAAlCrJ,KAAK0I,eAAe5H,IAAIuI,IAC1BrJ,KAAKqI,MAAMlH,OAAOkI,MAGfT,IAAS5I,KAAKqI,MAAMO,KAGtBkB,SAAST,GAEd,OADAnB,EAAI5E,MAAM,iFACHtD,KAAKqI,MAAMvH,IAAIuI,GAGjBvI,IAAIuI,GACT,OAAOrJ,KAAKqI,MAAMvH,IAAIuI,IC7I1B,MAAMU,EAAwC,IAAIC,KAAKC,aAAa,QAAS,CAC3EC,SAAU,MACVC,sBAAuB,EACvBC,sBAAuB,IAgBzB,MAAMC,EAAsC,IAAIL,KAAKM,eAAe,oCCblExK,YAAmByK,GACjBvK,KAAKuK,OAASA,EAGNC,wBACqC,mBAAd,QAApBC,EAAa,QAAbC,EAAA1K,KAAKuK,cAAQ,IAAAG,OAAA,EAAAA,EAAAC,aAAO,IAAAF,OAAA,EAAAA,EAAAD,aACX,QAAlBI,UAAAC,EAAA7K,KAAKuK,6BAAQI,aAAK,IAAAC,GAAAA,EAAEJ,aAIdM,mBACoC,mBAAb,QAApBL,EAAa,QAAbC,EAAA1K,KAAKuK,cAAQ,IAAAG,OAAA,EAAAA,EAAAC,aAAO,IAAAF,OAAA,EAAAA,EAAAK,YAC7BC,aAAa/K,KAAKgL,iBAClBhL,KAAKgL,gBAAkBC,YAAW,aACd,QAAlBR,UAAAC,EAAA1K,KAAKuK,6BAAQI,aAAK,IAAAF,GAAAA,EAAEK,aACnB,wBCrBqB,IACrB,mBAEgB,IAChB,qBAEkB,IAClB,kBAEe,IACf,wFFJH,SAAmBI,GACvB,OAAqB,IAAjBrB,MAAMqB,IAAqC,iBAAVA,EAC5BnB,EAAmBoB,OAAOD,GAE1B,WAWL,SAAeA,GACnB,OAAIA,aAAiB9D,KACZiD,EAAec,OAAOD,GAEtB"}
\ No newline at end of file
diff --git a/packages/components/src/assets/codicons/LICENSE b/packages/components/src/assets/codicons/LICENSE
index a2c95fc155..12dd39b6ae 100644
--- a/packages/components/src/assets/codicons/LICENSE
+++ b/packages/components/src/assets/codicons/LICENSE
@@ -49,7 +49,7 @@ exhaustive, and do not form part of our licenses.
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
- for the public:
+ for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
diff --git a/packages/components/src/assets/codicons/codicon.css b/packages/components/src/assets/codicons/codicon.css
index 404f5e1031..739be06ee4 100644
--- a/packages/components/src/assets/codicons/codicon.css
+++ b/packages/components/src/assets/codicons/codicon.css
@@ -6,7 +6,7 @@
@font-face {
font-family: "codicon";
font-display: block;
- src: url("./codicon.ttf?0e5b0adf625a37fbcd638d31f0fe72aa") format("truetype");
+ src: url("./codicon.ttf?be64b7213e352cd7f91ef58198e71237") format("truetype");
}
.codicon[class*='codicon-'] {
@@ -72,6 +72,7 @@
.codicon-record-keys:before { content: "\ea65" }
.codicon-keyboard:before { content: "\ea65" }
.codicon-tag:before { content: "\ea66" }
+.codicon-git-pull-request-label:before { content: "\ea66" }
.codicon-tag-add:before { content: "\ea66" }
.codicon-tag-remove:before { content: "\ea66" }
.codicon-person:before { content: "\ea67" }
@@ -107,6 +108,7 @@
.codicon-debug-breakpoint:before { content: "\ea71" }
.codicon-debug-breakpoint-disabled:before { content: "\ea71" }
.codicon-debug-hint:before { content: "\ea71" }
+.codicon-terminal-decoration-success:before { content: "\ea71" }
.codicon-primitive-square:before { content: "\ea72" }
.codicon-edit:before { content: "\ea73" }
.codicon-pencil:before { content: "\ea73" }
@@ -226,7 +228,9 @@
.codicon-chrome-minimize:before { content: "\eaba" }
.codicon-chrome-restore:before { content: "\eabb" }
.codicon-circle-outline:before { content: "\eabc" }
+.codicon-circle:before { content: "\eabc" }
.codicon-debug-breakpoint-unverified:before { content: "\eabc" }
+.codicon-terminal-decoration-incomplete:before { content: "\eabc" }
.codicon-circle-slash:before { content: "\eabd" }
.codicon-circuit-board:before { content: "\eabe" }
.codicon-clear-all:before { content: "\eabf" }
@@ -261,6 +265,7 @@
.codicon-diff-removed:before { content: "\eadf" }
.codicon-diff-renamed:before { content: "\eae0" }
.codicon-diff:before { content: "\eae1" }
+.codicon-diff-sidebyside:before { content: "\eae1" }
.codicon-discard:before { content: "\eae2" }
.codicon-editor-layout:before { content: "\eae3" }
.codicon-empty-window:before { content: "\eae4" }
@@ -324,6 +329,7 @@
.codicon-megaphone:before { content: "\eb1e" }
.codicon-mention:before { content: "\eb1f" }
.codicon-milestone:before { content: "\eb20" }
+.codicon-git-pull-request-milestone:before { content: "\eb20" }
.codicon-mortar-board:before { content: "\eb21" }
.codicon-move:before { content: "\eb22" }
.codicon-multiple-windows:before { content: "\eb23" }
@@ -435,6 +441,7 @@
.codicon-debug-stackframe-active:before { content: "\eb89" }
.codicon-circle-small-filled:before { content: "\eb8a" }
.codicon-debug-stackframe-dot:before { content: "\eb8a" }
+.codicon-terminal-decoration-mark:before { content: "\eb8a" }
.codicon-debug-stackframe:before { content: "\eb8b" }
.codicon-debug-stackframe-focused:before { content: "\eb8b" }
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
@@ -448,9 +455,11 @@
.codicon-menu:before { content: "\eb94" }
.codicon-expand-all:before { content: "\eb95" }
.codicon-feedback:before { content: "\eb96" }
+.codicon-git-pull-request-reviewer:before { content: "\eb96" }
.codicon-group-by-ref-type:before { content: "\eb97" }
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
.codicon-account:before { content: "\eb99" }
+.codicon-git-pull-request-assignee:before { content: "\eb99" }
.codicon-bell-dot:before { content: "\eb9a" }
.codicon-debug-console:before { content: "\eb9b" }
.codicon-library:before { content: "\eb9c" }
@@ -479,6 +488,7 @@
.codicon-pinned-dirty:before { content: "\ebb2" }
.codicon-pass-filled:before { content: "\ebb3" }
.codicon-circle-large-filled:before { content: "\ebb4" }
+.codicon-circle-large:before { content: "\ebb5" }
.codicon-circle-large-outline:before { content: "\ebb5" }
.codicon-combine:before { content: "\ebb6" }
.codicon-gather:before { content: "\ebb6" }
@@ -552,6 +562,7 @@
.codicon-indent:before { content: "\ebf9" }
.codicon-record-small:before { content: "\ebfa" }
.codicon-error-small:before { content: "\ebfb" }
+.codicon-terminal-decoration-error:before { content: "\ebfb" }
.codicon-arrow-circle-down:before { content: "\ebfc" }
.codicon-arrow-circle-left:before { content: "\ebfd" }
.codicon-arrow-circle-right:before { content: "\ebfe" }
@@ -562,10 +573,63 @@
.codicon-blank:before { content: "\ec03" }
.codicon-heart-filled:before { content: "\ec04" }
.codicon-map:before { content: "\ec05" }
+.codicon-map-horizontal:before { content: "\ec05" }
+.codicon-fold-horizontal:before { content: "\ec05" }
.codicon-map-filled:before { content: "\ec06" }
+.codicon-map-horizontal-filled:before { content: "\ec06" }
+.codicon-fold-horizontal-filled:before { content: "\ec06" }
.codicon-circle-small:before { content: "\ec07" }
.codicon-bell-slash:before { content: "\ec08" }
.codicon-bell-slash-dot:before { content: "\ec09" }
.codicon-comment-unresolved:before { content: "\ec0a" }
.codicon-git-pull-request-go-to-changes:before { content: "\ec0b" }
.codicon-git-pull-request-new-changes:before { content: "\ec0c" }
+.codicon-search-fuzzy:before { content: "\ec0d" }
+.codicon-comment-draft:before { content: "\ec0e" }
+.codicon-send:before { content: "\ec0f" }
+.codicon-sparkle:before { content: "\ec10" }
+.codicon-insert:before { content: "\ec11" }
+.codicon-mic:before { content: "\ec12" }
+.codicon-thumbsdown-filled:before { content: "\ec13" }
+.codicon-thumbsup-filled:before { content: "\ec14" }
+.codicon-coffee:before { content: "\ec15" }
+.codicon-snake:before { content: "\ec16" }
+.codicon-game:before { content: "\ec17" }
+.codicon-vr:before { content: "\ec18" }
+.codicon-chip:before { content: "\ec19" }
+.codicon-piano:before { content: "\ec1a" }
+.codicon-music:before { content: "\ec1b" }
+.codicon-mic-filled:before { content: "\ec1c" }
+.codicon-repo-fetch:before { content: "\ec1d" }
+.codicon-copilot:before { content: "\ec1e" }
+.codicon-lightbulb-sparkle:before { content: "\ec1f" }
+.codicon-robot:before { content: "\ec20" }
+.codicon-sparkle-filled:before { content: "\ec21" }
+.codicon-diff-single:before { content: "\ec22" }
+.codicon-diff-multiple:before { content: "\ec23" }
+.codicon-surround-with:before { content: "\ec24" }
+.codicon-share:before { content: "\ec25" }
+.codicon-git-stash:before { content: "\ec26" }
+.codicon-git-stash-apply:before { content: "\ec27" }
+.codicon-git-stash-pop:before { content: "\ec28" }
+.codicon-vscode:before { content: "\ec29" }
+.codicon-vscode-insiders:before { content: "\ec2a" }
+.codicon-code-oss:before { content: "\ec2b" }
+.codicon-run-coverage:before { content: "\ec2c" }
+.codicon-run-all-coverage:before { content: "\ec2d" }
+.codicon-coverage:before { content: "\ec2e" }
+.codicon-github-project:before { content: "\ec2f" }
+.codicon-map-vertical:before { content: "\ec30" }
+.codicon-fold-vertical:before { content: "\ec30" }
+.codicon-map-vertical-filled:before { content: "\ec31" }
+.codicon-fold-vertical-filled:before { content: "\ec31" }
+.codicon-go-to-search:before { content: "\ec32" }
+.codicon-percentage:before { content: "\ec33" }
+.codicon-sort-percentage:before { content: "\ec33" }
+.codicon-attach:before { content: "\ec34" }
+.codicon-go-to-editing-session:before { content: "\ec35" }
+.codicon-edit-session:before { content: "\ec36" }
+.codicon-code-review:before { content: "\ec37" }
+.codicon-copilot-warning:before { content: "\ec38" }
+.codicon-python:before { content: "\ec39" }
+.codicon-git-fetch:before { content: "\f101" }
diff --git a/packages/components/src/assets/codicons/codicon.csv b/packages/components/src/assets/codicons/codicon.csv
index 0fd7d656ad..9ff6867799 100644
--- a/packages/components/src/assets/codicons/codicon.csv
+++ b/packages/components/src/assets/codicons/codicon.csv
@@ -17,6 +17,7 @@ arrow-small-right,,EA9F
arrow-small-up,,EAA0
arrow-swap,,EBCB
arrow-up,,EAA1
+attach,,EC34
azure-devops,,EBE8
azure,,EBD8
beaker-stop,,EBE1
@@ -46,17 +47,18 @@ chevron-down,,EAB4
chevron-left,,EAB5
chevron-right,,EAB6
chevron-up,,EAB7
+chip,,EC19
chrome-close,,EAB8
chrome-maximize,,EAB9
chrome-minimize,,EABA
chrome-restore,,EABB
circle-filled,,EA71
circle-large-filled,,EBB4
-circle-large-outline,,EBB5
-circle-outline,,EABC
+circle-large,,EBB5
circle-slash,,EABD
circle-small-filled,,EB8A
circle-small,,EC07
+circle,,EABC
circuit-board,,EABE
clear-all,,EABF
clippy,,EAC0
@@ -65,17 +67,24 @@ close,,EA76
cloud-download,,EAC2
cloud-upload,,EAC3
cloud,,EBAA
+code-oss,,EC2B
+code-review,,EC37
code,,EAC4
+coffee,,EC15
collapse-all,,EAC5
color-mode,,EAC6
combine,,EBB6
comment-discussion,,EAC7
+comment-draft,,EC0E
comment-unresolved,,EC0A
comment,,EA6B
compass-active,,EBD7
compass-dot,,EBD6
compass,,EBD5
+copilot-warning,,EC38
+copilot,,EC1E
copy,,EBCC
+coverage,,EC2E
credit-card,,EAC9
dash,,EACC
dashboard,,EACD
@@ -119,10 +128,13 @@ device-mobile,,EADB
diff-added,,EADC
diff-ignored,,EADD
diff-modified,,EADE
+diff-multiple,,EC23
diff-removed,,EADF
diff-renamed,,EAE0
+diff-single,,EC22
diff,,EAE1
discard,,EAE2
+edit-session,,EC36
edit,,EA73
editor-layout,,EAE3
ellipsis,,EA7C
@@ -156,11 +168,13 @@ folder-active,,EAF6
folder-library,,EBDF
folder-opened,,EAF7
folder,,EA83
+game,,EC17
gear,,EAF8
gift,,EAF9
gist-secret,,EAFA
git-commit,,EAFC
git-compare,,EAFD
+git-fetch,,F101
git-merge,,EAFE
git-pull-request-closed,,EBDA
git-pull-request-create,,EBBC
@@ -168,12 +182,18 @@ git-pull-request-draft,,EBDB
git-pull-request-go-to-changes,,EC0B
git-pull-request-new-changes,,EC0C
git-pull-request,,EA64
+git-stash-apply,,EC27
+git-stash-pop,,EC28
+git-stash,,EC26
github-action,,EAFF
github-alt,,EB00
github-inverted,,EBA1
+github-project,,EC2F
github,,EA84
globe,,EB01
+go-to-editing-session,,EC35
go-to-file,,EA94
+go-to-search,,EC32
grabber,,EB02
graph-left,,EBAD
graph-line,,EBE2
@@ -190,6 +210,7 @@ hubot,,EB08
inbox,,EB09
indent,,EBF9
info,,EA74
+insert,,EC11
inspect,,EBD1
issue-draft,,EBD9
issue-reopened,,EB0B
@@ -221,6 +242,7 @@ layout-statusbar,,EBF5
layout,,EBEB
library,,EB9C
lightbulb-autofix,,EB13
+lightbulb-sparkle,,EC1F
lightbulb,,EA61
link-external,,EB14
link,,EB15
@@ -239,17 +261,22 @@ magnet,,EBAE
mail-read,,EB1B
mail,,EB1C
map-filled,,EC06
+map-vertical-filled,,EC31
+map-vertical,,EC30
map,,EC05
markdown,,EB1D
megaphone,,EB1E
mention,,EB1F
menu,,EB94
merge,,EBAB
+mic-filled,,EC1C
+mic,,EC12
milestone,,EB20
mirror,,EA69
mortar-board,,EB21
move,,EB22
multiple-windows,,EB23
+music,,EC1B
mute,,EB24
new-file,,EA7F
new-folder,,EA80
@@ -266,8 +293,10 @@ package,,EB29
paintcan,,EB2A
pass-filled,,EBB3
pass,,EBA4
+percentage,,EC33
person-add,,EBCD
person,,EA67
+piano,,EC1A
pie-chart,,EBE4
pin,,EB2B
pinned-dirty,,EBB2
@@ -280,6 +309,7 @@ preview,,EB2F
primitive-square,,EA72
project,,EB30
pulse,,EB31
+python,,EC39
question,,EB32
quote,,EB33
radio-tower,,EB34
@@ -298,6 +328,7 @@ replace-all,,EB3C
replace,,EB3D
reply,,EA7D
repo-clone,,EB3E
+repo-fetch,,EC1D
repo-force-push,,EB3F
repo-forked,,EA63
repo-pull,,EB40
@@ -305,33 +336,42 @@ repo-push,,EB41
repo,,EA62
report,,EB42
request-changes,,EB43
+robot,,EC20
rocket,,EB44
root-folder-opened,,EB45
root-folder,,EB46
rss,,EB47
ruby,,EB48
run-above,,EBBD
+run-all-coverage,,EC2D
run-all,,EB9E
run-below,,EBBE
+run-coverage,,EC2C
run-errors,,EBDE
save-all,,EB49
save-as,,EB4A
save,,EB4B
screen-full,,EB4C
screen-normal,,EB4D
+search-fuzzy,,EC0D
search-stop,,EB4E
search,,EA6D
+send,,EC0F
server-environment,,EBA3
server-process,,EBA2
server,,EB50
settings-gear,,EB51
settings,,EB52
+share,,EC25
shield,,EB53
sign-in,,EA6F
sign-out,,EA6E
smiley,,EB54
+snake,,EC16
sort-precedence,,EB55
source-control,,EA68
+sparkle-filled,,EC21
+sparkle,,EC10
split-horizontal,,EB56
split-vertical,,EB57
squirrel,,EB58
@@ -339,6 +379,7 @@ star-empty,,EA6A
star-full,,EB59
star-half,,EB5A
stop-circle,,EBA5
+surround-with,,EC24
symbol-array,,EA8A
symbol-boolean,,EA8F
symbol-class,,EB5B
@@ -381,7 +422,9 @@ terminal-ubuntu,,EBC9
terminal,,EA85
text-size,,EB69
three-bars,,EB6A
+thumbsdown-filled,,EC13
thumbsdown,,EB6B
+thumbsup-filled,,EC14
thumbsup,,EB6C
tools,,EB6D
trash,,EA81
@@ -407,6 +450,9 @@ vm-connect,,EBA9
vm-outline,,EB7A
vm-running,,EB7B
vm,,EA7A
+vr,,EC18
+vscode-insiders,,EC2A
+vscode,,EC29
wand,,EBCF
warning,,EA6C
watch,,EB7C
diff --git a/packages/components/src/assets/codicons/codicon.html b/packages/components/src/assets/codicons/codicon.html
index ec8a322495..d883dd2483 100644
--- a/packages/components/src/assets/codicons/codicon.html
+++ b/packages/components/src/assets/codicons/codicon.html
@@ -297,6 +297,14 @@ codicon
arrow-up
+
+
+
+
+
+ attach
+
+
@@ -529,6 +537,14 @@ codicon
chevron-up
+
+
+
+
+
+ chip
+
+
@@ -577,20 +593,12 @@ codicon
circle-large-filled
-
-
-
-
-
- circle-large-outline
-
-
-
+
-
+
- circle-outline
+ circle-large
@@ -617,6 +625,14 @@
codicon
circle-small
+
+
+
+
+
+ circle
+
+
@@ -681,6 +697,22 @@ codicon
cloud
+
+
+
+
+
+ code-oss
+
+
+
+
+
+
+
+ code-review
+
+
@@ -689,6 +721,14 @@ codicon
code
+
+
+
+
+
+ coffee
+
+
@@ -721,6 +761,14 @@ codicon
comment-discussion
+
+
+
+
+
+ comment-draft
+
+
@@ -761,6 +809,22 @@ codicon
compass
+
+
+
+
+
+ copilot-warning
+
+
+
+
+
+
+
+ copilot
+
+
@@ -769,6 +833,14 @@ codicon
copy
+
+
+
+
+
+ coverage
+
+
@@ -1113,6 +1185,14 @@ codicon
diff-modified
+
+
+
+
+
+ diff-multiple
+
+
@@ -1129,6 +1209,14 @@ codicon
diff-renamed
+
+
+
+
+
+ diff-single
+
+
@@ -1145,6 +1233,14 @@ codicon
discard
+
+
+
+
+
+ edit-session
+
+
@@ -1409,6 +1505,14 @@ codicon
folder
+
+
+
+
+
+ game
+
+
@@ -1457,6 +1561,14 @@ codicon
git-compare
+
+
+
+
+
+ git-fetch
+
+
@@ -1513,6 +1625,30 @@ codicon
git-pull-request
+
+
+
+
+
+ git-stash-apply
+
+
+
+
+
+
+
+ git-stash-pop
+
+
+
+
+
+
+
+ git-stash
+
+
@@ -1537,6 +1673,14 @@ codicon
github-inverted
+
+
+
+
+
+ github-project
+
+
@@ -1553,6 +1697,14 @@ codicon
globe
+
+
+
+
+
+ go-to-editing-session
+
+
@@ -1561,6 +1713,14 @@ codicon
go-to-file
+
+
+
+
+
+ go-to-search
+
+
@@ -1689,6 +1849,14 @@ codicon
info
+
+
+
+
+
+ insert
+
+
@@ -1937,6 +2105,14 @@ codicon
lightbulb-autofix
+
+
+
+
+
+ lightbulb-sparkle
+
+
@@ -2081,6 +2257,22 @@ codicon
map-filled
+
+
+
+
+
+ map-vertical-filled
+
+
+
+
+
+
+
+ map-vertical
+
+
@@ -2129,6 +2321,22 @@ codicon
merge
+
+
+
+
+
+ mic-filled
+
+
+
+
+
+
+
+ mic
+
+
@@ -2169,6 +2377,14 @@ codicon
multiple-windows
+
+
+
+
+
+ music
+
+
@@ -2297,6 +2513,14 @@ codicon
pass
+
+
+
+
+
+ percentage
+
+
@@ -2313,6 +2537,14 @@ codicon
person
+
+
+
+
+
+ piano
+
+
@@ -2409,6 +2641,14 @@ codicon
pulse
+
+
+
+
+
+ python
+
+
@@ -2553,6 +2793,14 @@ codicon
repo-clone
+
+
+
+
+
+ repo-fetch
+
+
@@ -2609,6 +2857,14 @@ codicon
request-changes
+
+
+
+
+
+ robot
+
+
@@ -2657,6 +2913,14 @@ codicon
run-above
+
+
+
+
+
+ run-all-coverage
+
+
@@ -2673,6 +2937,14 @@ codicon
run-below
+
+
+
+
+
+ run-coverage
+
+
@@ -2721,6 +2993,14 @@ codicon
screen-normal
+
+
+
+
+
+ search-fuzzy
+
+
@@ -2737,6 +3017,14 @@ codicon
search
+
+
+
+
+
+ send
+
+
@@ -2777,6 +3065,14 @@ codicon
settings
+
+
+
+
+
+ share
+
+
@@ -2809,6 +3105,14 @@ codicon
smiley
+
+
+
+
+
+ snake
+
+
@@ -2825,6 +3129,22 @@ codicon
source-control
+
+
+
+
+
+ sparkle-filled
+
+
+
+
+
+
+
+ sparkle
+
+
@@ -2881,6 +3201,14 @@ codicon
stop-circle
+
+
+
+
+
+ surround-with
+
+
@@ -3217,6 +3545,14 @@ codicon
three-bars
+
+
+
+
+
+ thumbsdown-filled
+
+
@@ -3225,6 +3561,14 @@ codicon
thumbsdown
+
+
+
+
+
+ thumbsup-filled
+
+
@@ -3425,6 +3769,30 @@ codicon
vm
+
+
+
+
+
+ vr
+
+
+
+
+
+
+
+ vscode-insiders
+
+
+
+
+
+
+
+ vscode
+
+
@@ -3663,11 +4031,11 @@ codicon
description: 'dot round bullet'
},
{
- name: 'circle-large-outline',
+ name: 'circle-large',
description: 'dot round bullet'
},
{
- name: 'circle-outline',
+ name: 'circle',
description: 'dot round small bullet unverified breakpoint'
},
{
diff --git a/packages/components/src/assets/codicons/codicon.svg b/packages/components/src/assets/codicons/codicon.svg
index 7689b4d9f5..141bbdd3ae 100644
--- a/packages/components/src/assets/codicons/codicon.svg
+++ b/packages/components/src/assets/codicons/codicon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/packages/components/src/assets/codicons/codicon.ttf b/packages/components/src/assets/codicons/codicon.ttf
index 5abfa748fb..4a4d15cc2d 100644
Binary files a/packages/components/src/assets/codicons/codicon.ttf and b/packages/components/src/assets/codicons/codicon.ttf differ
diff --git a/packages/components/src/assets/favicon.ico b/packages/components/src/assets/favicon.ico
deleted file mode 100644
index 760963b074..0000000000
Binary files a/packages/components/src/assets/favicon.ico and /dev/null differ
diff --git a/packages/components/src/assets/images/abgrenzung.jpg b/packages/components/src/assets/images/abgrenzung.jpg
deleted file mode 100644
index a0efeb9be4..0000000000
Binary files a/packages/components/src/assets/images/abgrenzung.jpg and /dev/null differ
diff --git a/packages/components/src/assets/itzbund.logo.svg b/packages/components/src/assets/itzbund.logo.svg
deleted file mode 100644
index 46b1351947..0000000000
--- a/packages/components/src/assets/itzbund.logo.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/components/src/assets/kolibri.ico b/packages/components/src/assets/kolibri.ico
new file mode 100644
index 0000000000..77859ee3f9
Binary files /dev/null and b/packages/components/src/assets/kolibri.ico differ
diff --git a/packages/components/src/assets/kolibri.logo.svg b/packages/components/src/assets/kolibri.logo.svg
deleted file mode 100644
index 03faf0fe40..0000000000
--- a/packages/components/src/assets/kolibri.logo.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/components/src/assets/loader.css b/packages/components/src/assets/loader.css
deleted file mode 100644
index 767570d6e5..0000000000
--- a/packages/components/src/assets/loader.css
+++ /dev/null
@@ -1,46 +0,0 @@
-/* https://github.com/vineethtrv/css-loader */
-.loader {
- width: 48px;
- height: 48px;
- border: 3px dotted #3d3d3d;
- border-style: solid solid dotted dotted;
- border-radius: 50%;
- display: inline-block;
- position: relative;
- box-sizing: border-box;
- animation: rotation 4s linear infinite;
-}
-.loader::after {
- content: '';
- box-sizing: border-box;
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- margin: auto;
- border: 3px dotted #ff3d00;
- border-style: solid solid dotted;
- width: 24px;
- height: 24px;
- border-radius: 50%;
- animation: rotationBack 2s linear infinite;
- transform-origin: center center;
-}
-
-@keyframes rotation {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
-@keyframes rotationBack {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(-360deg);
- }
-}
diff --git a/packages/components/src/assets/logo.kolibri.invert.svg b/packages/components/src/assets/logo.kolibri.invert.svg
deleted file mode 100644
index 956c447e34..0000000000
--- a/packages/components/src/assets/logo.kolibri.invert.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/packages/components/src/assets/logo.kolibri.svg b/packages/components/src/assets/logo.kolibri.svg
deleted file mode 100644
index e07240132a..0000000000
--- a/packages/components/src/assets/logo.kolibri.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/packages/components/src/assets/logo.kolibri.text.invert.svg b/packages/components/src/assets/logo.kolibri.text.invert.svg
deleted file mode 100644
index 14018e754c..0000000000
--- a/packages/components/src/assets/logo.kolibri.text.invert.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
- KoliBri
-
diff --git a/packages/components/src/assets/logo.kolibri.text.svg b/packages/components/src/assets/logo.kolibri.text.svg
deleted file mode 100644
index 0bea8903c4..0000000000
--- a/packages/components/src/assets/logo.kolibri.text.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
- KoliBri
-
diff --git a/packages/components/src/assets/simulations/alert-simulation.js b/packages/components/src/assets/simulations/alert-simulation.js
deleted file mode 100644
index 5578828d82..0000000000
--- a/packages/components/src/assets/simulations/alert-simulation.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const on = {
- onClose: console.log,
-};
-const timeout = setTimeout(() => {
- document.querySelectorAll('kol-alert').forEach((alert) => {
- if (Math.random() > 0.5) {
- alert._on = on;
- alert.setAttribute('_has-closer', '');
- }
- });
-}, 2500);
diff --git a/packages/components/src/assets/simulations/button-simulation.js b/packages/components/src/assets/simulations/button-simulation.js
deleted file mode 100644
index 4b2245fcf9..0000000000
--- a/packages/components/src/assets/simulations/button-simulation.js
+++ /dev/null
@@ -1,8 +0,0 @@
-var buttons = document.querySelectorAll('kol-button.not-used');
-buttons.forEach((button) => {
- button._on = {
- onClick: () => {
- alert(`Button "${button._label}" wurde geklickt.`);
- },
- };
-});
diff --git a/packages/components/src/assets/simulations/form-simulation.js b/packages/components/src/assets/simulations/form-simulation.js
deleted file mode 100644
index 3c869e266f..0000000000
--- a/packages/components/src/assets/simulations/form-simulation.js
+++ /dev/null
@@ -1,989 +0,0 @@
-const FORMULAR_FORM = LeanUpForm.FormFactory.createForm('anschrift', {
- anschrift: {
- anrede: {
- ansprache: 'Frau',
- vorname: 'Elke',
- nachname: 'Mustermann',
- },
- adresse: {
- strasse: 'Musterstraße',
- hausnummer: '1a',
- ort: 'Musterstadt',
- plz: '54321',
- },
- },
- email: '',
- text: '',
- datum: '2000-12-24',
- password: 'Passwort',
- betrag: 45,
- status: 0,
- agb: null,
- datenschutz: null,
-});
-
-console.log(FORMULAR_FORM);
-
-const ANSCHRIFT_FORM = FORMULAR_FORM.getControl('anschrift');
-const ANREDE_FORM = ANSCHRIFT_FORM.getControl('anrede');
-const ANREDE_ANSPRACHE_INPUT = ANREDE_FORM.getControl('ansprache');
-const ANREDE_VORNAME_INPUT = ANREDE_FORM.getControl('vorname');
-const ANREDE_NACHNAME_INPUT = ANREDE_FORM.getControl('nachname');
-
-ANREDE_ANSPRACHE_INPUT.label = 'Anrede';
-ANREDE_ANSPRACHE_INPUT.mandatory = true;
-ANREDE_VORNAME_INPUT.label = 'Vorname';
-ANREDE_VORNAME_INPUT.mandatory = true;
-ANREDE_VORNAME_INPUT.info = 'Bitte geben Sie einen schönen Vorname ein.';
-ANREDE_NACHNAME_INPUT.label = 'Nachname';
-
-ANREDE_VORNAME_INPUT.changeListeners.add((...args) => {
- console.log(...args);
-});
-
-class DemoFehler extends LeanUpForm.AbstractValidator {
- constructor() {
- super('Test');
- }
- isValid(value) {
- if ((typeof value === 'string' && value.length > 5) || (typeof value === 'boolean' && value === false)) {
- return false;
- }
- return true;
- }
-}
-
-class DemoFormatter extends LeanUpForm.AbstractFormatter {
- format(value) {
- return value.toLocaleUpperCase();
- }
- parse(value) {
- return value;
- }
-}
-
-class Demo4SignSepFormatter extends LeanUpForm.AbstractFormatter {
- format(value) {
- const words = value.match(/(.{1,4})/g);
- return Array.isArray(words) ? words.join(' ') : value;
- }
- parse(value) {
- return value.replace(/ +/g, '');
- }
-}
-
-class DemoMaxLength extends LeanUpForm.AbstractFormatter {
- format(value) {
- return value;
- }
- parse(value) {
- return value.substring(0, 6);
- }
-}
-
-const VALIDATION_HANDLER = new LeanUpForm.ValidationHandler();
-VALIDATION_HANDLER.validators.add(new DemoFehler());
-ANREDE_VORNAME_INPUT.setValidationHandler(VALIDATION_HANDLER);
-ANREDE_NACHNAME_INPUT.setValidationHandler(VALIDATION_HANDLER);
-
-const FORMAT_HANDLER = new LeanUpForm.FormatHandler();
-FORMAT_HANDLER.formatters.add([new DemoFormatter(), new Demo4SignSepFormatter(), new DemoMaxLength()]);
-ANREDE_VORNAME_INPUT.setFormatHandler(FORMAT_HANDLER);
-
-document.querySelector('#kol-input-text')._control = ANREDE_VORNAME_INPUT;
-
-// console.log(VALIDATION_HANDLER);
-// console.log(ANREDE_VORNAME_INPUT);
-// console.log(ANREDE_NACHNAME_INPUT);
-
-const ADRESSE_FORM = ANSCHRIFT_FORM.getControl('adresse');
-const ADRESSE_STRASSE_INPUT = ADRESSE_FORM.getControl('strasse');
-const ADRESSE_HAUSNUMMER_INPUT = ADRESSE_FORM.getControl('hausnummer');
-const ADRESSE_PLZ_INPUT = ADRESSE_FORM.getControl('plz');
-const ADRESSE_ORT_INPUT = ADRESSE_FORM.getControl('ort');
-
-ADRESSE_STRASSE_INPUT.label = 'Straße';
-ADRESSE_HAUSNUMMER_INPUT.label = 'Hausnummer';
-ADRESSE_PLZ_INPUT.label = 'Postleitzahl';
-ADRESSE_ORT_INPUT.label = 'Ort';
-
-const STATUS_INPUT = FORMULAR_FORM.getControl('status');
-const EMAIL_INPUT = FORMULAR_FORM.getControl('email');
-const TEXT_INPUT = FORMULAR_FORM.getControl('text');
-const BETRAG_INPUT = FORMULAR_FORM.getControl('betrag');
-const AGB_INPUT = FORMULAR_FORM.getControl('agb');
-const DATENSCHUTZ_INPUT = FORMULAR_FORM.getControl('datenschutz');
-
-STATUS_INPUT.label = 'Status';
-EMAIL_INPUT.label = 'E-Mail-Adresse';
-// EMAIL_INPUT.mandatory = true;
-EMAIL_INPUT.info = 'Bitte geben Sie hier eine E-Mail-Adresse ein.';
-TEXT_INPUT.label = 'Text';
-TEXT_INPUT.mandatory = true;
-TEXT_INPUT.setValidationHandler(VALIDATION_HANDLER);
-BETRAG_INPUT.label = 'Betrag';
-BETRAG_INPUT.mandatory = true;
-BETRAG_INPUT.setValidationHandler(VALIDATION_HANDLER);
-AGB_INPUT.label = 'Ich akzeptiere die Allgemeinen Geschäftsbedingungen.';
-AGB_INPUT.mandatory = true;
-AGB_INPUT.setValidationHandler(VALIDATION_HANDLER);
-DATENSCHUTZ_INPUT.label = 'Ich akzeptiere die Datenschutzerklärung.';
-
-const PASSWORD_INPUT = FORMULAR_FORM.getControl('password');
-const DATUM_INPUT = FORMULAR_FORM.getControl('datum');
-PASSWORD_INPUT.label = 'Passwort';
-DATUM_INPUT.label = 'Datum';
-
-ANREDE_ANSPRACHE_INPUT.readonly = true;
-ANREDE_ANSPRACHE_INPUT.changeListeners.add((value) => {
- ANREDE_VORNAME_INPUT.disabled = !ANREDE_VORNAME_INPUT.disabled;
- ANREDE_NACHNAME_INPUT.readonly = !ANREDE_NACHNAME_INPUT.readonly;
- AGB_INPUT.readonly = !AGB_INPUT.readonly;
- DATENSCHUTZ_INPUT.disabled = !DATENSCHUTZ_INPUT.disabled;
-});
-ANREDE_VORNAME_INPUT.changeListeners.add(() => {
- // document.querySelector('#vorname').setAttribute('_error', ANREDE_VORNAME_INPUT.error);
-});
-ANREDE_NACHNAME_INPUT.changeListeners.add(() => {
- document.querySelector('#nachname').setAttribute('_readonly', ANREDE_NACHNAME_INPUT.readonly);
-});
-// EMAIL_INPUT.changeListeners.add(() => {
-// document.querySelector('#email').setAttribute('_error', EMAIL_INPUT.error);
-// document.querySelector('#email').setAttribute('_disabled', EMAIL_INPUT.disabled);
-// });
-// AGB_INPUT.changeListeners.add((value) => {
-// ANREDE_ANSPRACHE_INPUT.disabled = !ANREDE_ANSPRACHE_INPUT.disabled;
-// });
-
-function domReady() {
- document.querySelector('#anrede-adapter')._control = ANREDE_ANSPRACHE_INPUT;
- const ANREDE_ANSPRACHE_OPTIONS = [
- {
- label: 'Herr',
- value: 'Herr',
- },
- {
- label: 'Frau',
- value: 'Frau',
- },
- ];
- document.querySelectorAll('kol-input-radido').forEach((inputRadio) => {
- inputRadio._list = ANREDE_ANSPRACHE_OPTIONS;
- inputRadio._on = {
- onChange: console.log,
- };
- });
-
- // document.querySelector('#vorname')._control = ANREDE_VORNAME_INPUT;
- // document.querySelector('#nachname')._control = ANREDE_NACHNAME_INPUT;
-
- document.querySelector('kol-form').addEventListener('submit', (event) => {
- event.stopPropagation();
- console.log(event, ANREDE_FORM.getData());
- });
- // document.querySelector('#strasse')._control = ADRESSE_STRASSE_INPUT;
- // document.querySelector('#hausnummer')._control = ADRESSE_HAUSNUMMER_INPUT;
- // document.querySelector('#plz')._control = ADRESSE_PLZ_INPUT;
- // document.querySelector('#ort')._control = ADRESSE_ORT_INPUT;
-
- // document.querySelector('#status')._control = STATUS_INPUT;
- const STATUS_OPTIONS = [
- {
- value: null,
- label: '- keine Auswahl -',
- },
- {
- label: 'Optgroup 1',
- options: [
- {
- value: 'a1',
- label: 'A1',
- },
- {
- disabled: true,
- value: 'b1',
- label: 'B1',
- },
- {
- label: 'Optgroup 2',
- options: [
- {
- value: 'a2',
- label: 'A2',
- },
- {
- value: 'b2',
- label: 'B2',
- },
- ],
- },
- {
- value: 'c1',
- label: 'C1',
- },
- ],
- },
- {
- value: '1',
- label: 'Gute Laune',
- },
- {
- value: '2',
- label: 'Geht so',
- },
- {
- value: '3',
- label: 'Schlechte Laune',
- },
- {
- value: '4',
- label: 'ich_bin_ein_echt_langes_zusammengesetztes_Worte_und_versuche_das_Layout_zu_brechen',
- },
- ];
- // document.querySelector('#status')._options = STATUS_OPTIONS;
-
- // document.querySelector('#email')._control = EMAIL_INPUT;
- // document.querySelector('#email').setAttribute('_mandatory', EMAIL_INPUT.mandatory);
- // document.querySelector('#email').setAttribute('_info', EMAIL_INPUT.info);
-
- // document.querySelector('#texteingabe')._control = TEXT_INPUT;
- // document.querySelector('#slider')._control = BETRAG_INPUT;
-
- document.querySelectorAll('.datenschutz-checkbox').forEach((input) => {
- input._control = AGB_INPUT;
- });
- document.querySelector('#new-input-checkbox')._control = AGB_INPUT;
- document.querySelector('#new-input-checkbox-leanup')._control = AGB_INPUT;
- document.querySelectorAll('kol-input-radio.herr-frau').forEach((input) => {
- input._list = ANREDE_ANSPRACHE_OPTIONS;
- });
-
- document.querySelector('#kol-input-text')._control = ANREDE_VORNAME_INPUT;
- document.querySelector('kol-input-text.vorname')._list = NAMEN;
-
- document.querySelector('#new-input-email')._control = EMAIL_INPUT;
- document.querySelector('#new-input-color')._control = new LeanUpForm.InputControl('color', {
- label: 'Farbe',
- value: '#ff0000',
- });
- document.querySelector('#new-input-file')._control = new LeanUpForm.InputControl('file', {
- label: 'Datei(en) hochladen',
- });
- document.querySelector('#new-input-range')._control = BETRAG_INPUT;
-
- document.querySelector('#new-textarea')._control = TEXT_INPUT;
- const interval = setInterval(() => {
- TEXT_INPUT.value = `${TEXT_INPUT.value}A`;
- document.querySelector('kol-textarea[_hide-label=""]')._value = TEXT_INPUT.value;
- }, 1000);
- const timeout = setTimeout(() => {
- clearInterval(interval);
- clearTimeout(timeout);
- }, 10);
- STATUS_INPUT.value = `['c1','2']`;
- document.querySelectorAll('kol-select').forEach((select) => {
- select._on = {
- onChange: console.log,
- };
- });
- document.querySelectorAll('kol-select.list4value').forEach((select) => {
- select._list =
- "[{'value':null,'label':'- keine Auswahl -'},{'label':'Optgroup 1','options':[{'value':'a1','label':'A1'},{'disabled':true,'value':'b1','label':'B1'},{'label':'Optgroup 2','options':[{'value':'a2','label':'A2'},{'value':'b2','label':'B2'}]},{'value':'c1','label':'C1'}]},{'value':'1','label':'Gute Laune'},{'value':'2','label':'Geht so'},{'value':'3','label':'Schlechte Laune'},{'value':'4','label':'ich_bin_ein_echt_langes_zusammengesetztes_Worte_und_versuche_das_Layout_zu_brechen'}]";
- });
- document.querySelectorAll('kol-select.value4list').forEach((select) => {
- select._value = STATUS_INPUT.value;
- });
- setTimeout(() => {
- document.querySelectorAll('kol-select.value4list').forEach((select) => {
- select._list =
- "[{'value':null,'label':'- keine Auswahl -'},{'label':'Optgroup 1','options':[{'value':'a1','label':'A1'},{'disabled':true,'value':'b1','label':'B1'},{'label':'Optgroup 2','options':[{'value':'a2','label':'A2'},{'value':'b2','label':'B2'}]},{'value':'c1','label':'C1'}]},{'value':'1','label':'Gute Laune'},{'value':'2','label':'Geht so'},{'value':'3','label':'Schlechte Laune'},{'value':'4','label':'ich_bin_ein_echt_langes_zusammengesetztes_Worte_und_versuche_das_Layout_zu_brechen'}]";
- });
- document.querySelectorAll('.select-adapter').forEach((select) => {
- select._control = STATUS_INPUT;
- });
- document.querySelectorAll('kol-select.list4value').forEach((select) => {
- select._value = STATUS_INPUT.value;
- });
- }, 5000);
-
- document.querySelector('#new-input-date')._control = DATUM_INPUT;
-
- document.querySelector('#filter-table')._data = DATA;
- document.querySelector('#filter-input')._on = {
- onChange: (event) => {
- console.log(event.target.value);
- document.querySelector('#filter-table')._data = DATA.filter((tupel) => {
- const regExp = new RegExp(event.target.value, 'i');
- return (
- regExp.test(tupel.montag) || regExp.test(tupel.dienstag) || regExp.test(tupel.mittwoch) || regExp.test(tupel.donnerstag) || regExp.test(tupel.freitag)
- );
- });
- },
- };
-
- var fixSelect = document.querySelector('#fix-select-multi');
- if (fixSelect instanceof HTMLElement) {
- fixSelect._list = [
- { label: 'Baum', value: Date.now() },
- { label: 'Baum', value: Date.now() },
- ];
- fixSelect._on = {
- // onClick: (...args) => {
- // console.log('onClick', args);
- // },
- onChange: (...args) => {
- console.log('onChange', args);
- setTimeout(() => {
- fixSelect._list = [{ label: 'Baum', value: Date.now() }].concat(fixSelect._list);
- setTimeout(() => {
- console.log(fixSelect._value);
- }, 100);
- }, 100);
- },
- };
- }
-}
-
-document.onreadystatechange = function () {
- if (document.readyState == 'complete') {
- setTimeout(domReady, 1000);
- }
-};
-
-const DATA = [
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Hong', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
-];
-
-const NAMEN = [
- 'Lucy',
- 'Lukas',
- 'Ella',
- 'Konstantin',
- 'Amy',
- 'Ben',
- 'Emely',
- 'Jonas',
- 'Finja',
- 'Elias',
- 'Amelie',
- 'Niklas',
- 'Luise',
- 'David',
- 'Frieda',
- 'Oskar',
- 'Katharina',
- 'Philipp',
- 'Romy',
- 'Leon',
- 'Juna',
- 'Noah',
- 'Theresa',
- 'Luis',
- 'Eva',
- 'Paul',
- 'Julia',
- 'Finn',
- 'Anna',
- 'Felix',
- 'Carla',
- 'Julian',
- 'Paulina',
- 'Maximilian',
- 'Elisabeth',
- 'Henry',
- 'Rosa',
- 'Tim',
- 'Mia',
- 'Karl',
- 'Maya',
- 'Friedrich',
- 'Selma',
- 'Peter',
- 'Edda',
- 'Quirin',
- 'Flora',
- 'Liam',
- 'Berenike',
- 'Linus',
- 'Simone',
- 'Quentin',
- 'Elena',
- 'Paul',
- 'Meike',
- 'Johannes',
- 'Susanne',
- 'Alexander',
- 'Annika',
- 'Anton',
- 'Augusta',
- 'Aras',
- 'Alba',
- 'Asis',
- 'Wilma',
- 'Adrian',
- 'Annegret',
- 'Arthur',
- 'Aglaia',
- 'Adam',
- 'Aaliyah',
- 'Arian',
- 'Annabelle',
- 'Amos',
- 'Alma',
- 'Arik',
- 'Alicia',
- 'Ake',
- 'Anette',
- 'Altfried',
- 'Astrid',
- 'Ari',
- 'Anisha',
- 'Andreas',
- 'Antke',
- 'Allessandro',
- 'Abigail',
- 'Achim',
- 'Aideen',
- 'Ben',
- 'Aini',
- 'Bela',
- 'Aida',
- 'Baldur',
- 'Aamenah',
- 'Benedikt',
- 'Ariane',
- 'Beat',
- 'Adriana',
- 'Bernd',
- 'Alexandra',
- 'Bertram',
- 'Ava',
- 'Blue',
- 'Arielle',
- 'Badi',
- 'Allissa',
- 'Batiste',
- 'Aamu',
- 'Bastian',
- 'Arzu',
- 'Caleb',
- 'Anouk',
- 'Caspar',
- 'Andrea',
- 'Calvin',
- 'Bianca',
- 'Cadmus',
- 'Blanka',
- 'Christoph',
- 'Benita',
- 'Cedrik',
- 'Bettina',
- 'Camern',
- 'Bamika',
- 'Carsten',
- 'Bente',
- 'Cainan',
- 'Barbara',
- 'Cem',
- 'Berit',
- 'Carl',
- 'Bentje',
- 'Cyranus',
- 'Birte',
- 'Curt',
- 'Brigitte',
- 'Daniel',
- 'Christiane',
- 'Dominik',
- 'Charlotte',
- 'Darius',
- 'Catherina',
- 'Dario',
- 'Caroline',
- 'Dag',
- 'Caren',
- 'Diminic',
- 'Caecilia',
- 'Damian',
- 'Celine',
- 'Diego',
- 'Coco',
- 'Dieter',
- 'Chaya',
- 'Demian',
- 'Dalia',
- 'Dewis',
- 'Deenah',
- 'Dirk',
- 'Daphne',
- 'Donald',
- 'Delia',
- 'Enzo',
- 'Dari',
- 'Emil',
- 'Doerte',
- 'Erik',
- 'Djamila',
- 'Edwin',
- 'Dominique',
- 'Eliah',
- 'Doerte',
- 'Ethan',
- 'Dorothee',
- 'Erwin',
- 'Emira',
- 'Eliot',
- 'Emily',
- 'Enes',
- 'Elif',
- 'Emilio',
- 'Ellen',
- 'Ebbo',
- 'Enna',
- 'Eberhard',
- 'Ebba',
- 'Edgar',
- 'Eleni',
- 'Fabrizius',
- 'Freya',
- 'Finn',
- 'Fiona',
- 'Fabian',
- 'Franziska',
- 'Fabio',
- 'Luzia',
- 'Finjas',
- 'Fabienne',
- 'Franz',
- 'Mädchen',
- 'Jungen',
- 'Fiona',
- 'Falko',
- 'Felina',
- 'Fatih',
- 'Felicitas',
- 'Fynn',
- 'Fabia',
- 'Flavio',
- 'Fabiola',
- 'Fady',
- 'Fabrizia',
- 'Fritz',
- 'Filomae',
- 'Falko',
- 'Floris',
- 'Gabriel',
- 'Fae',
- 'Gustav',
- 'Fanny',
- 'Guiseppe',
- 'Fritzi',
- 'Günter',
- 'Greta',
- 'Gerhard',
- 'Gabrielle',
- 'Georg',
- 'Grit',
- 'Gel',
- 'Gwen',
- 'Gerald',
- 'Gabi',
- 'Geoffrey',
- 'Gila',
- 'Gismund',
- 'Giorgina',
- 'Giulio',
- 'Gisele',
- 'Godo',
- 'Heike',
- 'Henri',
- 'Hanna',
- 'Hannes',
- 'Helena',
- 'Henry',
- 'Haima',
- 'Henrik',
- 'Heike',
- 'Hendrik',
- 'Helen',
- 'Heiko',
- 'Isabell',
- 'Haku',
- 'Ida',
- 'Hanno',
- 'Ilona',
- 'Hugo',
- 'Ingrid',
- 'Henryk',
- 'Iris',
- 'Hardy',
- 'Ira',
- 'Hagar',
- 'Iara',
- 'Hafiz',
- 'Ivette',
- 'Haile',
- 'Irma',
- 'Hakan',
- 'Jardis',
- 'Hasso',
- 'Juni',
- 'Harry',
- 'Juna',
- 'Hauke',
- 'Josephine',
- 'Harun',
- 'Jella',
- 'Hayo',
- 'Jill',
- 'Idil',
- 'Jennifer',
- 'Ian',
- 'Jakobine',
- 'Izzy',
- 'Jessika',
- 'Ibrahim',
- 'Julie',
- 'Igor',
- 'Jasmin',
- 'Jack',
- 'Joana',
- 'Jules',
- 'Jaqueline',
- 'Julian',
- 'Jonna',
- 'Jan',
- 'Jean',
- 'Jakob',
- 'Janis',
- 'Jaap',
- 'Jodi',
- 'Jonathan',
- 'Jen',
- 'Jannik',
- 'Justyna',
- 'Jona',
- 'Jutta',
- 'Jannis',
- 'Kathleen',
- 'Joel',
- 'Kayra',
- 'Jonte',
- 'Klara',
- 'Jarin',
- 'Kiara',
- 'Jörn',
- 'Kathrin',
- 'Jari',
- 'Catrin',
- 'Jannik',
- 'Kiki',
- 'Jukka',
- 'Judith',
- 'Samo',
- 'Celia',
- 'Jaakov',
- 'Kaaria',
- 'Jeremy',
- 'Kerstin',
- 'Jarne',
- 'Kim',
- 'Kilian',
- 'Kader',
- 'Kai',
- 'Kaisa',
- 'Kylan',
- 'Liv',
- 'Kristian',
- 'Livia',
- 'Kasper',
- 'Louisa',
- 'Kadmos',
- 'Lucy',
- 'Klaus',
- 'Lina',
- 'Kaarle',
- 'Lena',
- 'Kevin',
- 'Leonie',
- 'Kadir',
- 'Lea',
- 'Konrad',
- 'Leni',
- 'Lukas',
- 'Lotta',
- 'Leon',
- 'Laura',
- 'Leopold',
- 'Lara',
- 'Luca',
- 'Lia',
- 'Linas',
- 'Lisa',
- 'Roland',
- 'Luna',
- 'Leo',
- 'Linda',
- 'Lennard',
- 'Laureen',
- 'Luke',
- 'Liv',
- 'Lenny',
- 'Liz',
- 'Lasse',
- 'Mona',
- 'Lion',
- 'Mareen',
- 'Luca',
- 'Mathilda',
- 'Lutz',
- 'Marlene',
- 'Levi',
- 'Marianne',
- 'Matthias',
- 'Mara',
- 'Moritz',
- 'Mina',
- 'Meteo',
- 'Magdalena',
- 'Mats',
- 'Miriam',
- 'Matthis',
- 'Marianne',
- 'Mattes',
- 'Martje',
- 'Milo',
- 'Maeve',
- 'Mika',
- 'Mae',
- 'Maxim',
- 'Mädchen',
- 'Jungen',
- 'Nadja',
- 'Marlon',
- 'Nadine',
- 'Mark',
- 'Nele',
- 'Matti',
- 'Nora',
- 'Max',
- 'Nina',
- 'Morris',
- 'Nada',
- 'Miran',
- 'Nadeshda',
- 'Miro',
- 'Nancy',
- 'Niklas',
- 'Nova',
- 'Nika',
- 'Nika',
- 'Niko',
- 'Nike',
- 'Nabil',
- 'Oda',
- 'Noel',
- 'Odilie',
- 'Nils',
- 'Okka',
- 'Nick',
- 'Olea',
- 'Neo',
- 'Odett',
- 'Nadeem',
- 'Olivia',
- 'Namo',
- 'Odilia',
- 'Nepomuk',
- 'Oana',
- 'Oscar',
- 'Pia',
- 'Ole',
- 'Paula',
- 'Oliver',
- 'Phlomena',
- 'Olivier',
- 'Paloma',
- 'Onur',
- 'Paris',
- 'Owen',
- 'Paola',
- 'Obbo',
- 'Poppy',
- 'Idil',
- 'Panja',
- 'Otto',
- 'Pardis',
- 'Oswald',
- 'Quirine',
- 'Paul',
- 'Quinta',
- 'Phil',
- 'Qara',
- 'Patrick',
- 'Ria',
- 'Paavo',
- 'Rita',
- 'Pamir',
- 'Raina',
- 'Pascal',
- 'Rabea',
- 'Peter',
- 'Radost',
- 'Quinn',
- 'Rabi',
- 'Quazim',
- 'Ronina',
- 'Kasimir',
- 'Rae',
- 'René',
- 'Radia',
- 'Riko',
- 'Svea',
- 'Robin',
- 'Smila',
- 'Raphael',
- 'Sofia',
- 'Rudi',
- 'Sonja',
- 'Remigius',
- 'Sophie',
- 'Richard',
- 'Stella',
- 'Radi',
- 'Sarah',
- 'Rainer',
- 'Silvie',
- 'Rasmus',
- 'Silke',
- 'Ruben',
- 'Sila',
- 'Samuel',
- 'Siri',
- 'Stefan',
- 'Sarah',
- 'Sascha',
- 'Saara',
- 'Serkan',
- 'Svenja',
- 'Marco',
- 'Sabine',
- 'Manuel',
- 'Sandra',
- 'Tom',
- 'Tiffanie',
- 'Tim',
- 'Thea',
- 'Theo',
- 'Tilda',
- 'Theodor',
- 'Tardis',
- 'Thilo',
- 'Tamina',
- 'Till',
- 'Tamy',
- 'Timo',
- 'Trudi',
- 'Tino',
- 'Tea',
- 'Tiny',
- 'Tima',
- 'Taylor',
- 'Tabia',
- 'Titus',
- 'Tassja',
- 'Tristan',
- 'Tilla',
- 'Tizian',
- 'Tabita',
- 'Todd',
- 'Tahua',
- 'Thomas',
- 'Uli',
- 'Taavi',
- 'Ulrike',
- 'Tillmann',
- 'Ute',
- 'Uwe',
- 'Uda',
- 'Udo',
- 'Ulla',
- 'Ugor',
- 'Ulrika',
- 'Ulrich',
- 'Ulva',
- 'Uli',
- 'Ulvi',
- 'Ulas',
- 'Uma',
- 'Ulf',
- 'Violeta',
- 'Volker',
- 'Victoria',
- 'Vinzent',
- 'Vanessa',
- 'Valentin',
- 'Valentine',
- 'Vitus',
- 'Valeska',
- 'Volker',
- 'Wandy',
- 'Valentin',
- 'Waris',
- 'Vidu',
- 'Walli',
- 'Valerio',
- 'Waltraud',
- 'Wilhelm',
- 'Wanda',
- 'William',
- 'Xenia',
- 'Will',
- 'Xani',
- 'Walter',
- 'Xanthe',
- 'Wanja',
- 'Yvonne',
- 'Wadi',
- 'Yu',
- 'Walid',
- 'Yla',
- 'Xaver',
- 'Zoe',
- 'Yannis',
- 'Zilla',
- 'Yannik',
- 'Zuri',
- 'Yoshi',
- 'Zamira',
- 'Yunus',
-];
-
-document.querySelector('kol-input-text.vorname')._list = NAMEN;
diff --git a/packages/components/src/assets/simulations/form-simulation.textarea.js b/packages/components/src/assets/simulations/form-simulation.textarea.js
deleted file mode 100644
index 8b8bc45ec4..0000000000
--- a/packages/components/src/assets/simulations/form-simulation.textarea.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const textAreas = document.querySelectorAll('off-kol-textarea');
-let timeout;
-
-if (textAreas) {
- textAreas.forEach((textarea) => {
- window.textarea = textarea;
- textarea._value = '';
- textarea._on = {
- onChange: (event) => {
- clearTimeout(timeout);
- setTimeout(() => {
- console.log(event, textarea);
- textarea._value = '';
- }, 1000);
- },
- };
- });
-}
diff --git a/packages/components/src/assets/simulations/form-simulation.weitere-cases.js b/packages/components/src/assets/simulations/form-simulation.weitere-cases.js
deleted file mode 100644
index 22871b826e..0000000000
--- a/packages/components/src/assets/simulations/form-simulation.weitere-cases.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const CHECKBOX2 = new LeanUpForm.InputControl('checkbox');
-CHECKBOX2.changeListeners.add(console.log);
-
-document.querySelectorAll('#change-checkbox').forEach((checkbox) => {
- checkbox._control = CHECKBOX2;
- checkbox._on = {
- onChange: console.warn,
- };
-});
-
-function outlineLogs(event) {
- event.preventDefault();
- const data = new FormData(event.target);
- console.log([...data.entries()]);
-}
-function onNativeSubmit(event) {
- console.log('native form', event);
- outlineLogs(event);
-}
-function onKoliBriSubmit(event) {
- console.log('kolibri form', event);
- outlineLogs(event);
-}
-
-document.querySelectorAll('form').forEach((form) => {
- form.onsubmit = onNativeSubmit;
-});
-
-document.querySelectorAll('kol-form').forEach((kolForm) => {
- kolForm._on = {
- onSubmit: onKoliBriSubmit,
- };
-});
diff --git a/packages/components/src/assets/simulations/modal-simulation.js b/packages/components/src/assets/simulations/modal-simulation.js
deleted file mode 100644
index ae89b8f7c2..0000000000
--- a/packages/components/src/assets/simulations/modal-simulation.js
+++ /dev/null
@@ -1,31 +0,0 @@
-function openModal(modal, trigger) {
- modal._activeElement = trigger;
-}
-function closeModal(modal) {
- modal._activeElement = null;
-}
-
-function setModalFunctions(triggerSelector, modalSelector, closeSelector) {
- const trigger = document.querySelector(triggerSelector);
- const modal = document.querySelector(modalSelector);
- const close = document.querySelector(closeSelector);
- if (modal) {
- if (trigger) {
- trigger._on = {
- onClick: openModal(modal, trigger),
- };
- }
- modal._on = {
- onClose: closeModal(modal),
- };
- }
- if (close) {
- close._on = {
- onClick: closeModal(modal),
- };
- }
-}
-
-setModalFunctions('#modal-open-1', '#modal-1');
-setModalFunctions('#modal-open-2', '#modal-2');
-setModalFunctions('#tooltip_button', '#overviewModal');
diff --git a/packages/components/src/assets/simulations/nav-simulation.js b/packages/components/src/assets/simulations/nav-simulation.js
deleted file mode 100644
index 1e662deee2..0000000000
--- a/packages/components/src/assets/simulations/nav-simulation.js
+++ /dev/null
@@ -1,163 +0,0 @@
-const navTest = document.querySelector('#nav-test');
-if (navTest) {
- navTest._links = [
- {
- _label: '1 Navigationspunkt mit sehr langem Link-Test',
- _href: '#asdf',
- _icons: 'codicon codicon-flame',
- },
- {
- _label: '2 Navigationspunkt und ich_bin_ein_echt_langes_zusammengesetztes_Worte_und_versuche_das_Layout_zu_brechen',
- _on: {
- onClick: () => {
- alert('hallo');
- },
- },
- _icons: 'codicon codicon-flame',
- },
- {
- _label: '3 Navigationspunkt mit viel Text zu was testen',
- _href: '#abc',
- _icons: 'codicon codicon-flame',
- _children: [
- { _label: '3.1 Navigationspunkt', _href: '#abc', _icons: 'codicon codicon-flame' },
- { _label: '3.2 Navigationspunkt', _href: '#abc', _icons: 'codicon codicon-flame', _target: 'asdasd' },
- {
- _icons: 'codicon codicon-flame',
- _label: '3.3 Navigationspunkt',
- _href: '#abc3.3',
- _children: [
- { _icons: 'codicon codicon-flame', _label: '3.3.1 Navigationspunkt', _href: '#abc' },
- { _icons: 'codicon codicon-flame', _label: '3.3.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- {
- _icons: 'codicon codicon-flame',
- _label: '3.4 Navigationspunkt',
- _href: '#abc3.4',
- _children: [
- { _icons: 'codicon codicon-flame', _label: '3.4.1 Navigationspunkt', _href: '#abc' },
- { _icons: 'codicon codicon-flame', _label: '3.4.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- { _icons: 'codicon codicon-flame', _label: '3.5 Navigationspunkt', _href: '#abc' },
- ],
- },
- {
- _label: '4 Navigationspunkt mit viel Text zu was testen',
- _icons: 'codicon codicon-flame',
- _children: [
- { _label: '4.1 Navigationspunkt', _href: '#abc', _icons: 'codicon codicon-flame' },
- { _label: '4.2 Navigationspunkt', _href: '#abc', _icons: 'codicon codicon-flame', _target: 'asdasd' },
- {
- _icons: 'codicon codicon-flame',
- _label: '4.3 Navigationspunkt',
- _href: '#abc',
- _children: [
- { _icons: 'codicon codicon-flame', _label: '4.3.1 Navigationspunkt', _href: '#abc' },
- { _icons: 'codicon codicon-flame', _label: '4.3.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- {
- _icons: 'codicon codicon-flame',
- _label: '4.4 Navigationspunkt',
- _href: '#abc',
- _children: [
- { _icons: 'codicon codicon-flame', _label: '4.4.1 Navigationspunkt', _href: '#abc' },
- { _icons: 'codicon codicon-flame', _label: '4.4.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- { _icons: 'codicon codicon-flame', _label: '4.5 Navigationspunkt', _href: '#abc' },
- ],
- },
- ];
-}
-
-const clickNav = document.querySelector('#click-nav');
-if (clickNav) {
- clickNav._links = [
- {
- _label: '1 Navigationspunkt mit sehr langem Link-Test',
- _on: {
- onClick: () => {
- alert('hallo');
- },
- },
- _icons: 'icofont-woodpecker',
- },
- {
- _label: '2 Navigationspunkt und ich_bin_ein_echt_langes_zusammengesetztes_Worte_und_versuche_das_Layout_zu_brechen',
- _on: {
- onClick: () => {
- alert('hallo');
- },
- },
- _icons: 'icofont-woodpecker',
- },
- {
- _active: true,
- _label: '3 Navigationspunkt',
- _href: '#abc',
- _icons: 'icofont-woodpecker',
- _children: [
- { _label: '3.1 Navigationspunkt', _href: '#abc', _icons: 'icofont-woodpecker' },
- { _label: '3.2 Navigationspunkt', _href: '#abc', _icons: 'icofont-woodpecker', _target: 'asdasd' },
- {
- _active: true,
- _label: '3.3 Navigationspunkt',
- _href: '#abc',
- _children: [
- { _active: true, _label: '3.3.1 Navigationspunkt (aktiv)', _href: '#abc' },
- { _label: '3.3.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- {
- _label: '3.4 Navigationspunkt',
- _href: '#abc',
- _children: [
- { _label: '3.4.1 Navigationspunkt', _href: '#abc' },
- { _label: '3.4.2 Navigationspunkt', _href: '#abc' },
- ],
- },
- { _label: '3.5 Navigationspunkt', _href: '#abc' },
- ],
- },
- { _label: '4 Navigationspunkt', _href: '#abc' },
- ];
-}
-
-setTimeout(() => {
- const mainNav = document.querySelector('#main-nav');
- const mainNavElements = document.querySelectorAll('main > kol-accordion');
- const numberOfChildren = 6;
- if (mainNav && mainNavElements?.length > 0) {
- populateNavFromElements(mainNav, mainNavElements, numberOfChildren);
- }
-}, 1000);
-
-function createEntry(c) {
- return {
- _label: c.getAttribute('_heading'),
- _href: `#${c.id}`,
- _icons: 'codicon codicon-flame',
- };
-}
-
-function populateNavFromElements(nav, elements, numberOfChildren) {
- const result = [];
- let counter = 0;
- let parentCount = 0;
- let currentParent = null;
- elements.forEach((c) => {
- if (counter >= numberOfChildren) counter = 0;
- if (counter === 0) {
- const n = parentCount * numberOfChildren;
- currentParent = { _label: `Komponente ${n + 1} bis ${n + numberOfChildren}`, _icons: 'codicon codicon-flame', _children: [] };
- result.push(currentParent);
- parentCount++;
- }
- currentParent._children.push(createEntry(c));
- counter++;
- });
- nav._links = result;
-}
diff --git a/packages/components/src/assets/simulations/pagination-simulation.js b/packages/components/src/assets/simulations/pagination-simulation.js
deleted file mode 100644
index cced95e9ea..0000000000
--- a/packages/components/src/assets/simulations/pagination-simulation.js
+++ /dev/null
@@ -1,8 +0,0 @@
-var buttons = document.querySelectorAll('kol-pagination');
-buttons.forEach((button) => {
- button._on = {
- onClick: (event, page) => {
- alert(`Pagination "${page}" wurde geklickt.`);
- },
- };
-});
diff --git a/packages/components/src/assets/simulations/popover-simulation.js b/packages/components/src/assets/simulations/popover-simulation.js
deleted file mode 100644
index 6bbe1bf22d..0000000000
--- a/packages/components/src/assets/simulations/popover-simulation.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const buttonTop = document.querySelector('#popover-button-top');
-const buttonRight = document.querySelector('#popover-button-right');
-const buttonBottom = document.querySelector('#popover-button-bottom');
-const buttonLeft = document.querySelector('#popover-button-left');
-const buttonLogin = document.querySelector('#popover-button-login');
-
-const popoverTop = document.querySelector('#popover-top');
-const popoverRight = document.querySelector('#popover-right');
-const popoverBottom = document.querySelector('#popover-bottom');
-const popoverLeft = document.querySelector('#popover-left');
-const popoverLogin = document.querySelector('#popover-login');
-
-if (buttonTop && popoverTop) {
- buttonTop._on = { onClick: () => popoverTop.setAttribute('_show', '') };
-}
-if (buttonRight && popoverRight) {
- buttonRight._on = { onClick: () => popoverRight.setAttribute('_show', '') };
-}
-if (buttonBottom && popoverBottom) {
- buttonBottom._on = { onClick: () => popoverBottom.setAttribute('_show', '') };
-}
-if (buttonLeft && popoverLeft) {
- buttonLeft._on = { onClick: () => popoverLeft.setAttribute('_show', '') };
-}
-if (buttonLogin && popoverLogin) {
- buttonLogin._on = { onClick: () => popoverLogin.setAttribute('_show', '') };
-}
diff --git a/packages/components/src/assets/simulations/progress-simulation.js b/packages/components/src/assets/simulations/progress-simulation.js
deleted file mode 100644
index 31a1ea653b..0000000000
--- a/packages/components/src/assets/simulations/progress-simulation.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const simButtons = document.querySelectorAll('kol-button[class*="progress"]');
-const progressBars = document.querySelectorAll('kol-progress[class*="progress"]');
-
-function runProcess(index) {
- let percent = 0;
- console.log(simButtons[index], index);
- simButtons[index].setAttribute('_disabled', 'true');
- const interval = setInterval(() => {
- if (percent <= 100) {
- progressBars[index].setAttribute('_value', percent);
- percent += 1;
- } else {
- clearInterval(interval);
- simButtons[index].removeAttribute('_disabled');
- }
- }, 50);
-}
-
-simButtons.forEach((button, index) => {
- button._on = {
- onClick: () => {
- runProcess(index);
- },
- };
-});
-
-const schnitzelWert = document.querySelector('[_id="schnitzelwert"]');
-const progressOut = document.querySelector('[_id="schnitzelfortschritt"]');
-if (schnitzelWert && progressOut) schnitzelWert._on = { onChange: onSchnitzelChange };
-
-function onSchnitzelChange(e, value) {
- progressOut.setAttribute('_value', value);
-}
diff --git a/packages/components/src/assets/simulations/smart-button-simulation.js b/packages/components/src/assets/simulations/smart-button-simulation.js
deleted file mode 100644
index 60557fb144..0000000000
--- a/packages/components/src/assets/simulations/smart-button-simulation.js
+++ /dev/null
@@ -1,35 +0,0 @@
-setTimeout(() => {
- const smartButtons = document.querySelectorAll('.smart-button');
- smartButtons.forEach((smartButton) => {
- smartButton._smartButton = {
- _label: 'Password einblenden',
- _icons: { left: { icon: 'icofont-eye' } },
- _hideLabel: true,
- _tooltipAlign: 'left',
- _on: {
- onClick: () => {
- smartButton._smartButton = {
- ...smartButton._smartButton,
- _icons: {
- left: {
- icon: smartButton._smartButton._icon.left.icon === 'icofont-eye' ? 'icofont-eye-blocked' : 'icofont-eye',
- },
- },
- _label: smartButton._smartButton._icon.left.icon === 'icofont-eye' ? 'Password ausblenden' : 'Password einblenden',
- };
- },
- },
- };
- });
-}, 2500);
-
-document.querySelector('#input-text')._smartButton = {
- _customClass: 'bg-purple',
- _disabled: false,
- _icons: { left: { icon: 'codicon codicon-home' } },
- _id: 'text_smartbutton',
- _label: 'aria-label',
- _on: { onclick: console.log },
- _tooltipAlign: 'top',
- _variant: 'danger',
-};
diff --git a/packages/components/src/assets/simulations/spin-simulation.js b/packages/components/src/assets/simulations/spin-simulation.js
deleted file mode 100644
index 01ece31711..0000000000
--- a/packages/components/src/assets/simulations/spin-simulation.js
+++ /dev/null
@@ -1,21 +0,0 @@
-let button = document.querySelector('kol-button[_label="Aktion ausführen"]');
-
-if (button) {
- button._on = {
- onClick: () => {
- button.setAttribute('_disabled', 'true');
- var spins = document.querySelectorAll('kol-spin');
- spins.forEach((spin) => {
- spin.removeAttribute('style');
- spin.setAttribute('_show', 'true');
- });
- let timeout = setTimeout(() => {
- clearTimeout(timeout);
- spins.forEach((spin) => {
- spin.removeAttribute('_show');
- });
- button.removeAttribute('_disabled');
- }, 7500);
- },
- };
-}
diff --git a/packages/components/src/assets/simulations/table-simulation.js b/packages/components/src/assets/simulations/table-simulation.js
deleted file mode 100644
index bfc7047748..0000000000
--- a/packages/components/src/assets/simulations/table-simulation.js
+++ /dev/null
@@ -1,875 +0,0 @@
-const TABLE_HEADERS_H = {
- horizontal: [
- [
- {
- label: 'Werktage',
- colSpan: 5,
- },
- {
- label: 'Wochenende',
- colSpan: 2,
- },
- ],
- [
- {
- key: 'montag',
- label: 'Montag',
- render: (el, data) => {
- const button = document.createElement('kol-button');
- button.setAttribute('_label', data.label);
- button.setAttribute('data-theme', 'default');
- button.setAttribute('style', 'font-size: 75%');
- button.setAttribute('exportparts', 'button,normal');
- button._on = { onClick: console.log };
- el.innerHTML = '';
- el.appendChild(button);
- },
- compareFn: (first, second) => {
- if (first.montag < second.montag) {
- return -1;
- }
- if (first.montag > second.montag) {
- return 1;
- }
- return 0;
- },
- sort: (data) => {
- return data.sort((first, second) => {
- if (first.montag < second.montag) {
- return -1;
- }
- if (first.montag > second.montag) {
- return 1;
- }
- return 0;
- });
- },
- sortDirection: 'ASC',
- textAlign: 'right',
- },
- {
- key: 'dienstag',
- label: 'Dienstag',
- render: (el, data) => (el.innerHTML = ` `),
- compareFn: (first, second) => {
- if (first.dienstag < second.dienstag) {
- return -1;
- }
- if (first.dienstag > second.dienstag) {
- return 1;
- }
- return 0;
- },
- sortDirection: 'DESC',
- },
- {
- key: 'mittwoch',
- label: 'Mittwoch',
- compareFn: (first, second) => {
- if (first.mittwoch < second.mittwoch) {
- return -1;
- }
- if (first.mittwoch > second.mittwoch) {
- return 1;
- }
- return 0;
- },
- sortDirection: 'NOC',
- render: (el, data) => (el.innerHTML = ` `),
- },
- {
- key: 'donnerstag',
- label: 'Donnerstag',
- render: (el, data) => (el.innerHTML = ` `),
- },
- {
- key: 'freitag',
- label: 'Freitag',
- render: (el, data) => (el.innerHTML = ` `),
- },
- {
- key: 'samstag',
- label: 'Samstag',
- render: (el, data) => (el.innerHTML = ` `),
- },
- {
- key: 'sonntag',
- label: 'Sonntag',
- render: (el, data) => (el.innerHTML = ` `),
- },
- ],
- ],
-};
-const TABLE_HEADERS_V = {
- vertical: [
- [
- {
- label: 'Früh',
- },
- {
- label: 'Mittag',
- },
- {
- label: 'Abend',
- },
- {
- label: 'Nacht',
- },
- ],
- ],
-};
-const TABLE_HEADERS_H_V = {
- horizontal: [
- [
- {
- label: '',
- rowSpan: 2,
- asTd: true,
- },
- ...TABLE_HEADERS_H.horizontal[0],
- ],
- [...TABLE_HEADERS_H.horizontal[1]],
- ],
- ...TABLE_HEADERS_V,
-};
-const TABLE_2_HEADERS = {
- horizontal: [
- [
- {
- asTd: true,
- colSpan: 2,
- },
- ].concat(TABLE_HEADERS_V),
- ],
- vertical: [
- [
- {
- ...TABLE_HEADERS_H.horizontal[0][0],
- rowSpan: TABLE_HEADERS_H.horizontal[0][0].colSpan,
- colSpan: undefined,
- },
- {
- ...TABLE_HEADERS_H.horizontal[0][1],
- rowSpan: TABLE_HEADERS_H.horizontal[0][1].colSpan,
- colSpan: undefined,
- },
- ],
- ].concat([TABLE_HEADERS_H.horizontal[1]]),
-};
-const TABLE_NVDA_HEADERS = {
- horizontal: [
- [
- { label: 'Juni', key: 'juni', sort: (data) => data.sort((a, b) => sortTable(a, b, 'juni', 'number')) },
- { label: 'April', key: 'april', sort: (data) => data.sort((a, b) => sortTable(a, b, 'april', 'number')) },
- { label: 'Mai', key: 'mai', sort: (data) => data.sort((a, b) => sortTable(a, b, 'mai', 'number')) },
- { label: 'Juli', key: 'juli', sort: (data) => data.sort((a, b) => sortTable(a, b, 'juli', 'number')) },
- { label: 'August', key: 'august', sort: (data) => data.sort((a, b) => sortTable(a, b, 'august', 'number')) },
- { label: 'September', key: 'september', sort: (data) => data.sort((a, b) => sortTable(a, b, 'september', 'number')) },
- ],
- ],
-};
-
-const TABLE_DATA = [
- {
- montag: 'Alex',
- dienstag: 'Hong',
- mittwoch: 'Kevin',
- donnerstag: 'Fabian',
- freitag: 'Alex',
- samstag: 'Kevin',
- sonntag: 'Hong',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
-];
-const TABLE_DATA_SHORT = TABLE_DATA.slice(0, -1);
-const TABLE_PAGED_DATA = [
- {
- montag: 'Alex',
- dienstag: 'Anna',
- mittwoch: 'Amalia',
- donnerstag: 'Arthur',
- freitag: 'Alex',
- samstag: 'Andrea',
- sonntag: 'Arnold',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Finn',
- dienstag: 'Roger',
- mittwoch: 'Christian',
- donnerstag: 'Caspar',
- freitag: 'David',
- samstag: 'Bernard',
- sonntag: 'Anna',
- },
- {
- montag: 'Alex',
- dienstag: 'Anna',
- mittwoch: 'Amalia',
- donnerstag: 'Arthur',
- freitag: 'Alex',
- samstag: 'Andrea',
- sonntag: 'Arnold',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Finn',
- dienstag: 'Roger',
- mittwoch: 'Christian',
- donnerstag: 'Caspar',
- freitag: 'David',
- samstag: 'Bernard',
- sonntag: 'Anna',
- },
- {
- montag: 'Alex',
- dienstag: 'Anna',
- mittwoch: 'Amalia',
- donnerstag: 'Arthur',
- freitag: 'Alex',
- samstag: 'Andrea',
- sonntag: 'Arnold',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Finn',
- dienstag: 'Roger',
- mittwoch: 'Christian',
- donnerstag: 'Caspar',
- freitag: 'David',
- samstag: 'Bernard',
- sonntag: 'Anna',
- },
- {
- montag: 'Alex',
- dienstag: 'Anna',
- mittwoch: 'Amalia',
- donnerstag: 'Arthur',
- freitag: 'Alex',
- samstag: 'Andrea',
- sonntag: 'Arnold',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Finn',
- dienstag: 'Roger',
- mittwoch: 'Christian',
- donnerstag: 'Caspar',
- freitag: 'David',
- samstag: 'Bernard',
- sonntag: 'Anna',
- },
- {
- montag: 'Alex',
- dienstag: 'Anna',
- mittwoch: 'Amalia',
- donnerstag: 'Arthur',
- freitag: 'Alex',
- samstag: 'Andrea',
- sonntag: 'Arnold',
- },
- {
- montag: 'Helena',
- dienstag: 'Fabian',
- mittwoch: 'Marie',
- donnerstag: 'Ben',
- freitag: 'Marcus',
- samstag: 'Alex',
- sonntag: 'Marcus',
- },
- {
- montag: 'Fabian',
- dienstag: 'Helena',
- mittwoch: 'Fabian',
- donnerstag: 'Maya',
- freitag: 'Ben',
- samstag: 'Alex',
- sonntag: 'Helena',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Hong',
- dienstag: 'Alex',
- mittwoch: 'Kevin',
- donnerstag: 'Maya',
- freitag: 'Fabian',
- samstag: 'Helena',
- sonntag: 'Alex',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Samuel',
- dienstag: 'Selena',
- mittwoch: 'Sandra',
- donnerstag: 'Salim',
- freitag: 'Robert',
- samstag: 'Richard',
- sonntag: 'Pamela',
- },
- {
- montag: 'Finn',
- dienstag: 'Roger',
- mittwoch: 'Christian',
- donnerstag: 'Caspar',
- freitag: 'David',
- samstag: 'Bernard',
- sonntag: 'Anna',
- },
-];
-const TABLE_2_DATA = [
- { montag: 'Alex', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Helena', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Marcus' },
- { montag: 'Fabian', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
- { montag: 'Hong', dienstag: 'Marie', mittwoch: 'Kevin', donnerstag: 'Maya', freitag: 'Ben' },
-];
-const TABLE_NVDA_DATA = [
- { april: '97', mai: '99', juni: '100', juli: '101', august: '102', september: '105' },
- { april: '11', mai: '13', juni: '13', juli: '13', august: '12', september: '12' },
- { april: '86', mai: '85', juni: '87', juli: '88', august: '87', september: '90' },
- { april: '11', mai: '12', juni: '12', juli: '11', august: '12', september: '12' },
- { april: '42', mai: '41', juni: '42', juli: '43', august: '39', september: '42' },
- { april: '100', mai: '99', juni: '98', juli: '99', august: '102', september: '109' },
-];
-
-const TABLE_FOOT_DATA = [
- {
- montag: '1',
- dienstag: '2',
- mittwoch: '3',
- donnerstag: '4',
- freitag: '5',
- samstag: '6',
- sonntag: '7',
- },
-];
-
-const PAGINATION_1 = {
- _boundaryCount: 0,
- _page: 3,
- _pageSize: 20,
- _pageSizeOptions: [5, 10, 20, 50, 100],
- _on: {
- onClick: console.log,
- onChangePage: console.log,
- onChangePageSize: console.log,
- },
-};
-const PAGINATION_2 = {
- _boundaryCount: 0,
- _page: 3,
- _pageSize: 10,
- _pageSizeOptions: [5, 10, 20, 50, 100],
- _on: {
- onClick: console.log,
- onChangePage: console.log,
- onChangePageSize: console.log,
- },
-};
-
-function setTableData(tableID, caption, data, header, footer) {
- setTimeout(() => {
- const table = document.querySelector(tableID);
- if (table) {
- table._label = caption;
- table._data = data;
- if (header) table._headers = header;
- if (footer) table._dataFoot = footer;
- }
- }, 500);
-}
-function setMultipleTableData(tableClass, caption, data, header, footer) {
- setTimeout(() => {
- const tables = document.querySelectorAll(tableClass);
- tables.forEach((table) => {
- table._label = caption;
- table._data = data;
- if (header) table._headers = header;
- if (footer) table._dataFoot = footer;
- });
- }, 500);
-}
-
-function sortTable(a, b, key, type) {
- if (!type) type = 'string';
- switch (type) {
- case 'number':
- return parseFloat(a[key]) - parseFloat(b[key]);
- case 'string':
- return a[key].localeCompare(b[key]);
- }
-}
-
-setTableData('#table-1a', 'header: h/v, data: short, foot', TABLE_DATA_SHORT, TABLE_HEADERS_H_V, TABLE_FOOT_DATA);
-setTableData('#table-1b', 'header: h, data: short, foot', TABLE_DATA_SHORT, TABLE_HEADERS_H, TABLE_FOOT_DATA);
-setTableData('#table-1c', 'header: h, data: short', TABLE_DATA_SHORT, TABLE_HEADERS_H);
-setTableData('#table-1d', 'header: h/v, data: default', TABLE_DATA, TABLE_HEADERS_H_V);
-
-setTableData('#table-2', '2 Header, Daten Vertikal, Sort and Render', TABLE_2_DATA, TABLE_2_HEADERS);
-
-setTableData('#table-3a', 'header: h, data: paged', TABLE_PAGED_DATA, TABLE_HEADERS_H);
-setTableData('#table-3b', 'header: h, data: paged, pagination-1', TABLE_PAGED_DATA, TABLE_HEADERS_H, undefined, PAGINATION_1);
-
-setTableData('#table-4', 'header: h, data: paged, pagination-2', TABLE_PAGED_DATA, TABLE_HEADERS_H, undefined, PAGINATION_2);
-
-setTableData('#nvda', 'Sortiertest NVDA', TABLE_NVDA_DATA, TABLE_NVDA_HEADERS);
-
-const dayTableHeaders = {
- horizontal: [
- [
- { label: '', colSpan: 1, rowSpan: 1, asTd: true },
- { label: 'Tag', key: 'day' },
- { label: 'Info', key: 'info' },
- ],
- ],
- vertical: [
- [
- { label: '1', key: '1' },
- { label: '2', key: '2' },
- { label: '3', key: '3' },
- { label: '4', key: '4' },
- { label: '5', key: '5' },
- ],
- ],
-};
-const dayTableData = [
- { day: 'Montag', info: 'Herr Mohn' },
- { day: 'Dienstag', info: 'Dienst' },
- { day: 'Mittwoch', info: 'Mitte der Woche' },
- { day: 'Donnerstag', info: 'Donner' },
- { day: 'Freitag', info: 'frei' },
-];
-setTableData('day_table', 'DayTable', dayTableData, dayTableHeaders);
diff --git a/packages/components/src/assets/simulations/tabs-simulation.js b/packages/components/src/assets/simulations/tabs-simulation.js
deleted file mode 100644
index a2f641d855..0000000000
--- a/packages/components/src/assets/simulations/tabs-simulation.js
+++ /dev/null
@@ -1,43 +0,0 @@
-setTimeout(() => {
- const callback = (name) => {
- return (event, index) => {
- console.log(name, event, index);
- };
- };
- let tabs = document.querySelector('#tabs-with-events');
- if (tabs) {
- tabs._on = {
- onCreate: {
- label: 'Neu Text anpassbar',
- callback: callback('onCreate'),
- },
- onSelect: callback('onSelect'),
- };
- tabs._tabs = [
- { _label: 'Tab 1', _icons: 'fa-solid fa-house' },
- { _label: 'Tab 2', _cta: 'primary' },
- { _label: 'Tab 3', _disabled: true },
- {
- _label: 'Tab 4',
- _on: {
- onClose: callback('onClose'),
- },
- },
- {
- _label: 'Tab 5',
- _on: {
- onClose: true,
- },
- },
- { _label: 'Tab 6' },
- { _label: 'Tab 7' },
- { _label: 'Tab 8' },
- ];
- }
- tabs = document.querySelector('#tabs-with-create');
- if (tabs) {
- tabs._on = {
- onCreate: callback('onCreate'),
- };
- }
-}, 2500);
diff --git a/packages/components/src/assets/simulations/toast-simulation.js b/packages/components/src/assets/simulations/toast-simulation.js
deleted file mode 100644
index 89dbf2fa0d..0000000000
--- a/packages/components/src/assets/simulations/toast-simulation.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var toastButtons = document.querySelectorAll('kol-button[_label="Toast starten"]');
-
-toastButtons.forEach((button) => {
- button._on = {
- onClick: createAndShowToast,
- };
-});
-
-function createAndShowToast() {
- const toast = document.createElement('kol-toast');
- toast.setAttribute('_label', 'Ich bin ein Toast!');
- toast.setAttribute('_level', '3');
- toast.setAttribute('_show-duration', '10000');
- toast.setAttribute('_type', 'info');
- toast.innerText = `Ich werde in 10 Sekunden automatisch wieder ausgeblendet.`;
- document.body.appendChild(toast);
-}
diff --git a/packages/components/src/assets/style.css b/packages/components/src/assets/style.css
deleted file mode 100644
index 5466656312..0000000000
--- a/packages/components/src/assets/style.css
+++ /dev/null
@@ -1,139 +0,0 @@
-body,
-* {
- margin: 0;
-}
-
-* {
- box-sizing: border-box;
-}
-
-.container {
- display: grid;
- gap: 1.5rem;
- margin-inline: auto;
- padding-inline: 2rem;
-}
-
-.font-80 {
- font-size: 80%;
-}
-.font-60 {
- font-size: 60%;
-}
-
-.gap {
- gap: 0.5rem;
-}
-
-.grid {
- display: grid;
-}
-
-.kol-accordion p,
-.kol-card p {
- padding: 0;
- text-align: justify;
- margin: 0;
-}
-
-.divide-y > :not([hidden]) ~ :not([hidden]) {
- --tw-divide-y-reverse: 0;
- border: 0;
- border-style: solid;
- border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
- border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
-}
-
-.kol-accordion div[slot='content'],
-.kol-accordion div[slot='header'] {
- padding: 0.5rem;
-}
-
-.kol-logo {
- width: 18%;
-}
-
-.kol-badge[_icon='ui-rating'],
-.kol-badge[_label='Und ich!'] {
- font-weight: 600;
-}
-
-.kol-button.min-width {
- display: inline-block;
- margin-bottom: 0.1rem;
- margin-right: 0.1rem;
- width: 8rem;
-}
-
-.kol-logo {
- display: block;
- width: 175px;
-}
-
-.bordered {
- border: 1px solid var(--kolibri-border-color);
- border-radius: var(--kolibri-border-radius);
-}
-
-.bg-black {
- background-color: black;
-}
-.bg-blueviolet {
- background-color: blueviolet;
-}
-
-.p-b {
- padding-block: 0.5rem;
-}
-.p-i {
- padding-inline: 1rem;
-}
-
-.row {
- background-color: white;
- border: 1px solid #bbb;
- border-radius: 5px;
- box-shadow: 5px 5px 5px #eee;
- padding: 0.5rem 0;
- margin: 0.5rem 0;
-}
-
-.col-12 {
- overflow: hidden;
- padding-block: 0.25rem;
-}
-
-hr {
- background-color: #850550;
- margin: 0;
-}
-div.hr {
- text-align: center;
- font-weight: 600;
- color: white;
- margin: 0;
- padding: 0.5rem;
- background-color: #850550;
-}
-
-.kol-card[_level='5'],
-.kol-card[_level='6'] {
- display: block;
-}
-
-.kol-icon[_icon='codicon codicon-home'],
-.kol-icon[_icon='fa-solid fa-house'],
-.kol-icon[_icon='icofont-home'],
-.kol-icon[_icon='ti ti-home'] {
- color: #00646b;
- font-size: 500%;
-}
-
-.kol-logo {
- margin: 0.25rem;
-}
-
-.kol-nav.max-width {
- display: block;
- max-width: 20em;
-}
diff --git a/packages/components/src/components/@deprecated/input/controller-icon.ts b/packages/components/src/components/@deprecated/input/controller-icon.ts
index 8f25d179d8..8aebe5a217 100644
--- a/packages/components/src/components/@deprecated/input/controller-icon.ts
+++ b/packages/components/src/components/@deprecated/input/controller-icon.ts
@@ -1,7 +1,7 @@
import type { Generic } from 'adopted-style-sheets';
-import type { KoliBriHorizontalIcons, Stringified } from '@public-ui/schema';
-import { isIcon, isString, objectObjectHandler, parseJson, watchValidator } from '@public-ui/schema';
+import type { KoliBriHorizontalIcons, Stringified } from '../../../schema';
+import { isIcon, isString, objectObjectHandler, parseJson, watchValidator } from '../../../schema';
import { InputController } from './controller';
@@ -28,10 +28,6 @@ export class InputIconController extends InputController implements Watches {
this.component = component;
}
- public validateIcon(value?: Stringified): void {
- this.validateIcons(value);
- }
-
public validateIcons(value?: Stringified): void {
objectObjectHandler(value, () => {
try {
@@ -62,6 +58,6 @@ export class InputIconController extends InputController implements Watches {
public componentWillLoad(): void {
super.componentWillLoad();
- this.validateIcons(this.component._icons || this.component._icon);
+ this.validateIcons(this.component._icons);
}
}
diff --git a/packages/components/src/components/@deprecated/input/controller.ts b/packages/components/src/components/@deprecated/input/controller.ts
index 03f9cc7121..a97afdb03e 100644
--- a/packages/components/src/components/@deprecated/input/controller.ts
+++ b/packages/components/src/components/@deprecated/input/controller.ts
@@ -1,14 +1,18 @@
import type { Generic } from 'adopted-style-sheets';
import type {
+ AccessKeyPropType,
AdjustHeightPropType,
ButtonProps,
HideErrorPropType,
InputTypeOnDefault,
LabelWithExpertSlotPropType,
MsgPropType,
+ ShortKeyPropType,
+ StencilUnknown,
+ Stringified,
TooltipAlignPropType,
-} from '@public-ui/schema';
+} from '../../../schema';
import {
a11yHint,
a11yHintDisabled,
@@ -16,24 +20,27 @@ import {
objectObjectHandler,
parseJson,
setState,
+ validateAccessKey,
validateAdjustHeight,
validateHideError,
validateHideLabel,
validateLabelWithExpertSlot,
validateMsg,
+ validateShortKey,
validateTabIndex,
+ validateTooltipAlign,
watchBoolean,
watchString,
- validateTooltipAlign,
-} from '@public-ui/schema';
+} from '../../../schema';
-import { stopPropagation, tryToDispatchKoliBriEvent } from '../../../utils/events';
+import { dispatchDomEvent, KolEvent } from '../../../utils/events';
import { ControlledInputController } from '../../input-adapter-leanup/controller';
import type { Props as AdapterProps } from '../../input-adapter-leanup/types';
import type { Props, Watches } from './types';
+import { validateAccessAndShortKey } from '../../../schema/validators/access-and-short-key';
-type ValueChangeListener = (value: string) => void;
+type ValueChangeListener = (value: StencilUnknown) => void;
export class InputController extends ControlledInputController implements Watches {
protected readonly component: Generic.Element.Component & Props & AdapterProps;
@@ -45,8 +52,9 @@ export class InputController extends ControlledInputController implements Watche
this.component = component;
}
- public validateAccessKey(value?: string): void {
- watchString(this.component, '_accessKey', value);
+ public validateAccessKey(value?: AccessKeyPropType): void {
+ validateAccessKey(this.component, value);
+ validateAccessAndShortKey(value, this.component._shortKey);
}
public validateAdjustHeight(value?: AdjustHeightPropType): void {
@@ -63,19 +71,6 @@ export class InputController extends ControlledInputController implements Watche
validateTooltipAlign(this.component, value);
}
- /**
- * @deprecated
- */
- public validateError(value?: string): void {
- const message: MsgPropType | undefined = value
- ? {
- _description: value,
- _type: 'error',
- }
- : undefined;
- this.validateMsg(message);
- }
-
public validateHideError(value?: HideErrorPropType): void {
validateHideError(this.component, value, {
hooks: {
@@ -105,16 +100,9 @@ export class InputController extends ControlledInputController implements Watche
}
public validateId(value?: string): void {
- watchString(this.component, '_id', value, {
- hooks: {
- afterPatch: () => {
- this.setAttribute('id', this.formAssociated, this.component.state._id as string);
- },
- },
- minLength: 1,
- });
+ watchString(this.component, '_id', value, { minLength: 1 });
if (value === '' || typeof value === 'undefined') {
- devHint(`Eine eindeutige ID an den Eingabefeldern ist nicht zwingend erforderlich, könnte aber für die E2E-Tests relevant sein.`);
+ devHint(`A unique ID on the input fields is not strictly required, but it might be relevant for E2E tests.`);
}
}
@@ -124,7 +112,7 @@ export class InputController extends ControlledInputController implements Watche
});
}
- public validateMsg(value?: MsgPropType): void {
+ public validateMsg(value?: Stringified): void {
validateMsg(this.component, value);
}
@@ -134,6 +122,11 @@ export class InputController extends ControlledInputController implements Watche
}
}
+ public validateShortKey(value?: ShortKeyPropType): void {
+ validateShortKey(this.component, value);
+ validateAccessAndShortKey(this.component._accessKey, value);
+ }
+
public validateSmartButton(value?: ButtonProps | string): void {
objectObjectHandler(value, () => {
try {
@@ -154,7 +147,6 @@ export class InputController extends ControlledInputController implements Watche
super.componentWillLoad();
this.validateAccessKey(this.component._accessKey);
this.validateAdjustHeight(this.component._adjustHeight);
- this.validateError(this.component._error);
this.validateMsg(this.component._msg);
this.validateDisabled(this.component._disabled);
this.validateHideError(this.component._hideError);
@@ -162,18 +154,24 @@ export class InputController extends ControlledInputController implements Watche
this.validateHint(this.component._hint);
this.validateId(this.component._id);
this.validateLabel(this.component._label);
+ this.validateShortKey(this.component._shortKey);
this.validateSmartButton(this.component._smartButton);
this.validateOn(this.component._on);
this.validateTabIndex(this.component._tabIndex);
+ validateAccessAndShortKey(this.component._accessKey, this.component._shortKey);
+ }
+
+ private emitEvent(type: KolEvent, value?: unknown): void {
+ if (this.host) {
+ dispatchDomEvent(this.host, type, value);
+ }
}
protected onBlur(event: Event): void {
- this.component._alert = true;
this.component._touched = true;
// Event handling
- stopPropagation(event);
- tryToDispatchKoliBriEvent('blur', this.host);
+ this.emitEvent(KolEvent.blur);
// Callback
if (typeof this.component._on?.onBlur === 'function') {
@@ -181,11 +179,17 @@ export class InputController extends ControlledInputController implements Watche
}
}
- protected onChange(event: Event): void {
- const value = (event.target as HTMLInputElement).value;
+ /**
+ * @param event - The original event object
+ * @param value - Optional value. Taken from event if not defined.
+ */
+ protected onChange(event: Event, value?: StencilUnknown): void {
+ if (typeof value === 'undefined') {
+ value = (event.target as HTMLInputElement).value;
+ }
// Event handling
- tryToDispatchKoliBriEvent('change', this.host, value);
+ this.emitEvent(KolEvent.change, value);
// Callback
if (typeof this.component._on?.onChange === 'function') {
@@ -205,12 +209,18 @@ export class InputController extends ControlledInputController implements Watche
this.valueChangeListeners.forEach((listener) => listener(value));
}
- protected onInput(event: Event, shouldSetFormAssociatedValue = true): void {
- const value = (event.target as HTMLInputElement).value;
+ /**
+ * @param event - The original event object
+ * @param shouldSetFormAssociatedValue - Set to false when setting form associated value is not desired.
+ * @param value - Optional value. Taken from event if not defined.
+ */
+ protected onInput(event: Event, shouldSetFormAssociatedValue = true, value?: StencilUnknown): void {
+ if (typeof value === 'undefined') {
+ value = (event.target as HTMLInputElement).value;
+ }
// Event handling
- stopPropagation(event);
- tryToDispatchKoliBriEvent('input', this.host, value);
+ this.emitEvent(KolEvent.input, value);
// Static form handling
if (shouldSetFormAssociatedValue) {
@@ -225,8 +235,7 @@ export class InputController extends ControlledInputController implements Watche
protected onClick(event: Event): void {
// Event handling
- stopPropagation(event);
- tryToDispatchKoliBriEvent('click', this.host);
+ this.emitEvent(KolEvent.click);
// Callback
if (typeof this.component._on?.onClick === 'function') {
@@ -235,11 +244,8 @@ export class InputController extends ControlledInputController implements Watche
}
protected onFocus(event: Event): void {
- this.component._alert = true;
-
// Event handling
- stopPropagation(event);
- tryToDispatchKoliBriEvent('focus', this.host);
+ this.emitEvent(KolEvent.focus);
// Callback
if (typeof this.component._on?.onFocus === 'function') {
diff --git a/packages/components/src/components/@deprecated/input/types-icon.ts b/packages/components/src/components/@deprecated/input/types-icon.ts
index 1460170a88..e6c11d5832 100644
--- a/packages/components/src/components/@deprecated/input/types-icon.ts
+++ b/packages/components/src/components/@deprecated/input/types-icon.ts
@@ -1,9 +1,8 @@
-import type { KoliBriHorizontalIcons, PropLabelWithExpertSlot, Stringified } from '@public-ui/schema';
+import type { KoliBriHorizontalIcons, PropLabelWithExpertSlot, Stringified } from '../../../schema';
import type { Generic } from 'adopted-style-sheets';
type RequiredProps = NonNullable;
type OptionalProps = PropLabelWithExpertSlot & {
- icon: Stringified;
icons: Stringified;
};
export type Props = Generic.Element.Members;
diff --git a/packages/components/src/components/@deprecated/input/types.ts b/packages/components/src/components/@deprecated/input/types.ts
index c082dc050f..b43d6f7a43 100644
--- a/packages/components/src/components/@deprecated/input/types.ts
+++ b/packages/components/src/components/@deprecated/input/types.ts
@@ -1,18 +1,18 @@
-import type { ButtonProps, InputTypeOnDefault, MsgPropType, PropLabelWithExpertSlot, Stringified } from '@public-ui/schema';
+import type { AccessKeyPropType, ButtonProps, InputTypeOnDefault, MsgPropType, PropLabelWithExpertSlot, ShortKeyPropType, Stringified } from '../../../schema';
import type { Generic } from 'adopted-style-sheets';
type RequiredProps = NonNullable;
type OptionalProps = PropLabelWithExpertSlot & {
- accessKey: string;
+ accessKey: AccessKeyPropType;
adjustHeight: boolean;
disabled: boolean;
- error: string;
hideError: boolean;
hideLabel: boolean;
hint: string;
id: string;
msg: MsgPropType;
on: InputTypeOnDefault;
+ shortKey: ShortKeyPropType;
smartButton: Stringified;
syncValueBySelector: string;
tabIndex: number;
diff --git a/packages/components/src/components/@else/all/component.tsx b/packages/components/src/components/@else/all/component.tsx
index be8a61cfae..1c84555af6 100644
--- a/packages/components/src/components/@else/all/component.tsx
+++ b/packages/components/src/components/@else/all/component.tsx
@@ -2,8 +2,6 @@ import type { Generic } from 'adopted-style-sheets';
import type { JSX } from '@stencil/core';
import { h, Host, State } from '@stencil/core';
-import { Bundesministerium } from '../../../enums/bund';
-
type RequiredProps = NonNullable;
type OptionalProps = NonNullable;
// type Props = Generic.Element.Members;
@@ -28,7 +26,6 @@ export class KolAll implements Generic.Element.ComponentApi
-
@@ -36,7 +33,6 @@ export class KolAll implements Generic.Element.ComponentApi
-
@@ -47,8 +43,6 @@ export class KolAll implements Generic.Element.ComponentApi
-
-
@@ -56,7 +50,6 @@ export class KolAll implements Generic.Element.ComponentApi
-
diff --git a/packages/components/src/components/@else/all/readme.md b/packages/components/src/components/@else/all/readme.md
index 3f7e4f49c0..7a77e6e641 100644
--- a/packages/components/src/components/@else/all/readme.md
+++ b/packages/components/src/components/@else/all/readme.md
@@ -12,7 +12,6 @@
- [kol-badge](../badge)
- [kol-breadcrumb](../breadcrumb)
- [kol-button](../button)
-- [kol-button-group](../button-group)
- [kol-card](../card)
- [kol-details](../details)
- [kol-form](../form)
@@ -20,7 +19,6 @@
- [kol-icon](../icon)
- [kol-icon-font-awesome](../icon-font-awesome)
- [kol-icon-icofont](../icon-icofont)
-- [kol-indented-text](../indented-text)
- [kol-input-checkbox](../input-checkbox)
- [kol-input-color](../input-color)
- [kol-input-email](../input-email)
@@ -31,8 +29,6 @@
- [kol-input-range](../input-range)
- [kol-input-text](../input-text)
- [kol-link](../link)
-- [kol-link-group](../link-group)
-- [kol-logo](../logo)
- [kol-modal](../modal)
- [kol-nav](../nav)
- [kol-pagination](../pagination)
@@ -40,7 +36,6 @@
- [kol-select](../select)
- [kol-skip-nav](../skip-nav)
- [kol-spin](../spin)
-- [kol-table](../table)
- [kol-tabs](../tabs)
- [kol-textarea](../textarea)
- [kol-tooltip](../tooltip)
@@ -56,7 +51,6 @@ graph TD;
kol-all --> kol-badge
kol-all --> kol-breadcrumb
kol-all --> kol-button
- kol-all --> kol-button-group
kol-all --> kol-card
kol-all --> kol-details
kol-all --> kol-form
@@ -64,7 +58,6 @@ graph TD;
kol-all --> kol-icon
kol-all --> kol-icon-font-awesome
kol-all --> kol-icon-icofont
- kol-all --> kol-indented-text
kol-all --> kol-input-checkbox
kol-all --> kol-input-color
kol-all --> kol-input-email
@@ -75,8 +68,6 @@ graph TD;
kol-all --> kol-input-range
kol-all --> kol-input-text
kol-all --> kol-link
- kol-all --> kol-link-group
- kol-all --> kol-logo
kol-all --> kol-modal
kol-all --> kol-nav
kol-all --> kol-pagination
@@ -84,7 +75,6 @@ graph TD;
kol-all --> kol-select
kol-all --> kol-skip-nav
kol-all --> kol-spin
- kol-all --> kol-table
kol-all --> kol-tabs
kol-all --> kol-textarea
kol-all --> kol-tooltip
@@ -105,8 +95,6 @@ graph TD;
kol-button --> kol-tooltip
kol-card --> kol-heading
kol-details --> kol-icon-icofont
- kol-details --> kol-indented-text
- kol-form --> kol-indented-text
kol-icon-font-awesome --> kol-icon
kol-input-checkbox --> kol-alert
kol-input-color --> kol-alert
@@ -117,17 +105,11 @@ graph TD;
kol-input-radio --> kol-alert
kol-input-range --> kol-alert
kol-input-text --> kol-alert
- kol-link-group --> kol-heading
- kol-link-group --> kol-link
kol-nav --> kol-link
kol-nav --> kol-button
kol-pagination --> kol-button
kol-select --> kol-alert
kol-skip-nav --> kol-link
- kol-table --> kol-button
- kol-table --> kol-button-group
- kol-table --> kol-select
- kol-tabs --> kol-button-group
kol-tabs --> kol-icon-icofont
kol-textarea --> kol-alert
kol-version --> kol-badge
diff --git a/packages/components/src/components/@shared/_kol-alert-mixin.scss b/packages/components/src/components/@shared/_kol-alert-mixin.scss
deleted file mode 100644
index b1d151dc40..0000000000
--- a/packages/components/src/components/@shared/_kol-alert-mixin.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-@import '../style';
-@import '../host-display-block';
-
-@mixin kol-alert-styles {
- @layer kol-component {
- .kol-alert-wc {
- display: grid;
- }
-
- .kol-alert-wc .heading {
- display: flex;
- place-items: center;
- }
-
- .kol-alert-wc .heading > div {
- flex-grow: 1;
- }
-
- .close {
- /* Visible with forced colors */
- outline: transparent solid 1px;
- }
- }
-}
diff --git a/packages/components/src/components/@shared/_kol-button-mixin.scss b/packages/components/src/components/@shared/_kol-button-mixin.scss
new file mode 100644
index 0000000000..f1dda336ea
--- /dev/null
+++ b/packages/components/src/components/@shared/_kol-button-mixin.scss
@@ -0,0 +1,29 @@
+@import 'mixins';
+@import '../tooltip/style';
+
+@mixin kol-button-styles($block-classname) {
+ @layer kol-component {
+ :host {
+ //Needed for custom width
+ display: inline-block;
+ }
+ .#{$block-classname} {
+ font-style: rem(16);
+ display: inline-flex;
+ place-items: center;
+ text-align: center;
+ text-decoration-line: none;
+
+ &::before {
+ /* Render zero-width character as first element to set the baseline correctly. */
+ content: '\200B';
+ }
+
+ &__text {
+ // Needed for custom width
+ margin: auto;
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/packages/components/src/components/@shared/_kol-link-mixin.scss b/packages/components/src/components/@shared/_kol-link-mixin.scss
new file mode 100644
index 0000000000..ed2b8bd2ec
--- /dev/null
+++ b/packages/components/src/components/@shared/_kol-link-mixin.scss
@@ -0,0 +1,37 @@
+@import 'mixins';
+@import '../tooltip/style';
+
+@mixin kol-link-styles($block-classname) {
+ @layer kol-component {
+ :host {
+ // Causing linebreak, when removed
+ display: inline-block;
+ }
+
+ .#{$block-classname} {
+ $root: &;
+
+ font-size: rem(16);
+ align-items: baseline;
+ display: inline-flex;
+ place-items: center;
+ text-align: left;
+ text-decoration-line: none;
+
+ &__text {
+ .kol-span__label {
+ text-decoration-line: underline;
+
+ @at-root #{$root}:is(:focus, :hover):not([aria-disabled], [disabled]) & {
+ text-decoration-thickness: 0.2em;
+ }
+ }
+ }
+
+ &__icon {
+ display: inline-flex;
+ margin-left: rem(8);
+ }
+ }
+ }
+}
diff --git a/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss b/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss
new file mode 100644
index 0000000000..646d203f51
--- /dev/null
+++ b/packages/components/src/components/@shared/_kol-table-stateless-mixin.scss
@@ -0,0 +1,156 @@
+@import '../@shared/mixins';
+@import '../host-display-block';
+@import '../tooltip/style.scss';
+
+@mixin kol-table-stateless-styles {
+ @layer kol-component {
+ .kol-table {
+ display: block;
+ font-size: rem(16);
+
+ max-width: 100%;
+ overflow-x: auto;
+ overflow-y: hidden;
+
+ &__table {
+ width: 100%;
+ }
+
+ &__caption {
+ text-align: start;
+ }
+
+ &__focus-element {
+ font-size: 0;
+
+ &:focus {
+ outline: 0 !important;
+ /* @see https://remysharp.com/til/css/focus-ring-default-styles */
+ outline: rem(5) auto Highlight;
+ outline: rem(5) auto -webkit-focus-ring-color;
+ outline-offset: rem(2);
+ }
+ }
+
+ &__sort-button {
+ .kol-button {
+ color: inherit;
+ }
+ }
+
+ // headings in table body default to text-align left, unless defined otherwise.
+ &__body {
+ text-align: left;
+
+ .kol-button__text {
+ justify-items: start;
+ }
+ }
+
+ &__cell {
+ &--align-left {
+ text-align: left;
+
+ .kol-button__text {
+ justify-items: start;
+ }
+ }
+
+ &--align-center {
+ text-align: center;
+
+ & .kol-button__text {
+ justify-items: center;
+ }
+ }
+
+ &--align-right {
+ text-align: right;
+
+ .kol-button__text {
+ justify-items: end;
+ }
+ }
+ }
+
+ &__cell {
+ &--selection {
+ width: var(--a11y-min-size);
+ height: var(--a11y-min-size);
+ white-space: nowrap;
+ }
+ }
+
+ &__spacer {
+ display: none;
+ }
+
+ &__selection-label {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ height: var(--a11y-min-size);
+ justify-content: center;
+ position: relative;
+ width: var(--a11y-min-size);
+ }
+
+ &__selection-icon {
+ display: block;
+ inset: auto;
+ position: absolute;
+ z-index: 1;
+ }
+
+ &__selection-input {
+ appearance: none;
+ border-style: solid;
+ cursor: pointer;
+ margin: 0;
+
+ &:before {
+ content: '';
+ }
+
+ &--checkbox {
+ position: relative;
+ display: flex;
+ height: calc(var(--a11y-min-size) / 2);
+ width: calc(var(--a11y-min-size) / 2);
+ align-items: center;
+ justify-content: center;
+ background-color: rgb(255, 255, 255);
+ border-width: rem(2);
+ line-height: 1.5;
+ transition: all 0.5s ease 0s;
+ }
+
+ &--radio {
+ display: flex;
+ border-width: rem(2);
+ border-radius: 100%;
+ height: 1.5em;
+ min-height: 1.5em;
+ min-width: 1.5em;
+ padding: 0;
+ width: 1.5em;
+
+ &:before {
+ border-radius: 100%;
+ margin: auto;
+ height: calc(1.5em / 2);
+ width: calc(1.5em / 2);
+ }
+
+ &:checked:before {
+ background-color: #000;
+ @media (forced-colors: active) {
+ /* Give it a visible background in forced colors mode */
+ background-color: selectedItem !important;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/components/src/components/@shared/form-field-msg.tsx b/packages/components/src/components/@shared/form-field-msg.tsx
deleted file mode 100644
index 5eba26ccc8..0000000000
--- a/packages/components/src/components/@shared/form-field-msg.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import type { AlertPropType, HideErrorPropType, IdPropType, MsgPropType } from '@public-ui/schema';
-import type { FunctionalComponent } from '@stencil/core';
-import { h } from '@stencil/core';
-import { KolAlertWcTag } from '../../core/component-names';
-
-type FormFieldMsgProps = {
- _alert?: AlertPropType;
- _msg?: MsgPropType;
- _hideError?: HideErrorPropType;
- _id: IdPropType;
-};
-
-export const FormFieldMsg: FunctionalComponent = ({ _alert, _msg, _hideError, _id }) => (
- aria-describedby
- * attribute. It also does this if aria-hidden=true
- * is set.
- */
- aria-hidden="true"
- id={`${_id}-error`}
- _alert={_alert}
- _type="error"
- class={{
- error: true,
- 'visually-hidden': _hideError === true,
- }}
- {..._msg}
- >
- {_msg?._description || undefined}
-
-);
diff --git a/packages/components/src/components/a11y.scss b/packages/components/src/components/a11y.scss
index 96a5ab7830..19b3a7b078 100644
--- a/packages/components/src/components/a11y.scss
+++ b/packages/components/src/components/a11y.scss
@@ -1,3 +1,5 @@
+@import '@shared/mixins';
+
/*
* This file contains all rules for accessibility.
*/
@@ -6,7 +8,7 @@
/*
* Minimum size of interactive elements.
*/
- --a11y-min-size: 44px;
+ --a11y-min-size: #{rem(44)};
/*
* No element should be used without a background and font color whose contrast ratio has
* not been checked. By initially setting the background color to white and the font color
@@ -40,15 +42,14 @@
}
/*
- * All interactive elements should have a minimum size of 44px.
+ * All interactive elements should have a minimum size of rem(44).
*/
/* input:not([type='checkbox'], [type='radio'], [type='range']), */
/* option, */
/* select, */
/* textarea, */
[role='button'],
- button:not([role='link']),
- .kol-input .input {
+ button:not([role='link']) {
min-height: var(--a11y-min-size);
min-width: var(--a11y-min-size);
}
@@ -88,9 +89,9 @@
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
- height: 1px;
+ height: rem(1);
overflow: hidden;
position: absolute;
white-space: nowrap;
- width: 1px;
+ width: rem(1);
}
diff --git a/packages/components/src/components/abbr/component.tsx b/packages/components/src/components/abbr/component.tsx
deleted file mode 100644
index 76c24a8ca1..0000000000
--- a/packages/components/src/components/abbr/component.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import type { JSX } from '@stencil/core';
-import { validateLabel, validateTooltipAlign } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { KolTooltipWcTag } from '../../core/component-names';
-
-import type { AbbrAPI, AbbrStates, LabelPropType, TooltipAlignPropType } from '@public-ui/schema';
-
-/**
- * @slot - Der Begriff, der erläutert werden soll.
- */
-@Component({
- tag: 'kol-abbr',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolAbbr implements AbbrAPI {
- private readonly nonce = nonce();
-
- public render(): JSX.Element {
- return (
-
- {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
-
-
-
-
-
-
-
- );
- }
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Die State-Parameter repräsentieren den inneren State
- * einer Komponente.
- *
- * @see: https://stenciljs.com/docs/state
- */
- @State() public state: AbbrStates = {
- _label: '', // ⚠ required
- _tooltipAlign: 'top',
- };
-
- /**
- * Die Watch-Methoden dienen der Möglichkeit zur
- * Validierung der Werte eines Properties und
- * dem Mapping dessen auf einen anderen internen
- * State-Typ.
- *
- * @see: https://stenciljs.com/docs/properties#prop-validation
- */
- @Watch('_label')
- public validateLabel(value?: LabelPropType): void {
- validateLabel(this, value, {
- required: true,
- });
- }
-
- @Watch('_tooltipAlign')
- public validateTooltipAlign(value?: TooltipAlignPropType): void {
- validateTooltipAlign(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateLabel(this._label);
- this.validateTooltipAlign(this._tooltipAlign);
- }
-}
diff --git a/packages/components/src/components/abbr/readme.md b/packages/components/src/components/abbr/readme.md
deleted file mode 100644
index feb7da213a..0000000000
--- a/packages/components/src/components/abbr/readme.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# Abbr
-
-Die **Abbr**-Komponente implementiert den HTML-Tag `abbr`, wobei hier jedoch der Tooltip barrierefrei ist.
-Der Tooltip für die Beschreibung wird bei Focus oder Hover der **Abbr**-Komponente angezeigt und vorgelesen.
-
-## Konstruktion
-
-### Code
-
-```html
-Ich bin eine Abbr mit Tooltip oben.
-Ich bin eine Abbr mit Tooltip rechts.
-Ich bin eine Abbr mit Tooltip unten.
-Ich bin eine Abbr mit Tooltip links.
-```
-
-### Beispiel
-
-Ich bin eine Abbr mit Tooltip oben.
-Ich bin eine Abbr mit Tooltip rechts.
-Ich bin eine Abbr mit Tooltip unten.
-Ich bin eine Abbr mit Tooltip links.
-
-## Verwendung
-
-### Angabe der Beschreibung zur Abkürzung
-
-Der Begriff bzw. die Erklärung wird über das Attribut **`_label`** übergeben, die Abkürzung bzw. der erklärungswürdige Begriff kommt zwischen die Tags im HTML.
-
-### Ausrichtung des Tooltip
-
-Über das Attribut **`_tooltip-align`** wird die Positionierung des ToolTip, relativ zur Abkürzung, festgelegt.
-
-## Barrierefreiheit
-
-Die Abbr-Komponente wurde von KoliBri umgesetzt, weil der Standard-Tooltip nicht barrierefrei bzgl. der Skalierung ist.
-Der KoliBri Tooltip kann von Screenreadern vorgelesen werden und verändert seine Größe beim Zoomen korrekt.
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ----------- |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-
-## Slots
-
-| Slot | Description |
-| ---- | --------------------------------------- |
-| | Der Begriff, der erläutert werden soll. |
-
----
diff --git a/packages/components/src/components/abbr/shadow.tsx b/packages/components/src/components/abbr/shadow.tsx
new file mode 100644
index 0000000000..66a792f34e
--- /dev/null
+++ b/packages/components/src/components/abbr/shadow.tsx
@@ -0,0 +1,47 @@
+import type { JSX } from '@stencil/core';
+import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
+import type { AbbrAPI, AbbrStates, LabelPropType } from '../../schema';
+import { validateLabel } from '../../schema';
+
+/**
+ * @slot - The abbreviation (short form).
+ */
+@Component({
+ tag: 'kol-abbr',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolAbbr implements AbbrAPI {
+ public render(): JSX.Element {
+ return (
+
+
+
+
+ {this.state._label ? ` (${this.state._label})` : ''}
+
+ );
+ }
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label?: LabelPropType;
+
+ @State() public state: AbbrStates = {
+ _label: '', // ⚠ required
+ };
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ public componentWillLoad(): void {
+ this.validateLabel(this._label);
+ }
+}
diff --git a/packages/components/src/components/abbr/style.css b/packages/components/src/components/abbr/style.css
deleted file mode 100644
index 132cbbe8d8..0000000000
--- a/packages/components/src/components/abbr/style.css
+++ /dev/null
@@ -1,6 +0,0 @@
-@import '../style';
-@layer kol-component {
- :host > abbr {
- cursor: help;
- }
-}
diff --git a/packages/components/src/components/abbr/style.scss b/packages/components/src/components/abbr/style.scss
index 89e6bf911c..98368bb263 100644
--- a/packages/components/src/components/abbr/style.scss
+++ b/packages/components/src/components/abbr/style.scss
@@ -1,7 +1,9 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../tooltip/style.scss';
@layer kol-component {
- :host > abbr {
- cursor: help;
+ .kol-abbr {
+ font-size: rem(16);
}
}
diff --git a/packages/components/src/components/abbr/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/abbr/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..3d9123da7d
--- /dev/null
+++ b/packages/components/src/components/abbr/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-abbr should render with _label="Text" 1`] = `
+
+
+
+
+
+ (Text)
+
+
+`;
diff --git a/packages/components/src/components/abbr/test/html.mock.ts b/packages/components/src/components/abbr/test/html.mock.ts
deleted file mode 100644
index c7dcdd63b2..0000000000
--- a/packages/components/src/components/abbr/test/html.mock.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import type { AbbrProps } from '@public-ui/schema';
-import { KolTooltipWcTag } from '../../../core/component-names';
-
-export const getAbbrHtml = (props: AbbrProps): string => {
- props = mixMembers(
- {
- _label: '', // ⚠ required
- _tooltipAlign: 'top',
- },
- props,
- );
- return `
-
-
-
-
-
-
-
- <${KolTooltipWcTag} _align=${props._tooltipAlign} _id="nonce" _label=${props._label}>${KolTooltipWcTag}>
-
- `;
-};
diff --git a/packages/components/src/components/abbr/test/snapshot.spec.tsx b/packages/components/src/components/abbr/test/snapshot.spec.tsx
index d8bd7e921e..80c5937ca5 100644
--- a/packages/components/src/components/abbr/test/snapshot.spec.tsx
+++ b/packages/components/src/components/abbr/test/snapshot.spec.tsx
@@ -1,29 +1,7 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolAbbrTag } from '../../../core/component-names';
+import type { AbbrProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolAbbr } from '../shadow';
-import { getAbbrHtml } from './html.mock';
-
-import type { AbbrProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
-import { KolAbbr } from '../component';
-
-executeTests(
- 'Abbr',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolAbbr],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Text'],
- _tooltipAlign: ['left', 'bottom', 'right', 'top'],
- },
- getAbbrHtml,
- {
- execMode: 'default', // ready
- },
-);
+executeSnapshotTests(KolAbbrTag, [KolAbbr], [{ _label: 'Text' }]);
diff --git a/packages/components/src/components/accordion/accordion.e2e.ts b/packages/components/src/components/accordion/accordion.e2e.ts
new file mode 100644
index 0000000000..e20af0affe
--- /dev/null
+++ b/packages/components/src/components/accordion/accordion.e2e.ts
@@ -0,0 +1,66 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-accordion', () => {
+ test.describe('when accordion is enabled', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setContent('Accordion contents ');
+ });
+
+ test('should render the accordion title', async ({ page }) => {
+ const button = page.getByRole('button');
+ await expect(button).toHaveText('Accordion Label');
+ });
+
+ test('should show the accordion content after the title has been clicked', async ({ page }) => {
+ await expect(page.locator('.collapsible__content')).toHaveAttribute('aria-hidden', 'true');
+ await page.getByRole('button', { name: 'Accordion label' }).click();
+ await expect(page.locator('.collapsible__content')).not.toHaveAttribute('aria-hidden', 'true');
+ });
+
+ test('should hide the accordion content after the title has been clicked again', async ({ page }) => {
+ await page.getByRole('button', { name: 'Accordion label' }).click();
+ await expect(page.locator('.collapsible__content')).not.toHaveAttribute('aria-hidden', 'true');
+ await page.getByRole('button', { name: 'Accordion label' }).click();
+ await expect(page.locator('.collapsible__content')).toHaveAttribute('aria-hidden', 'true');
+ });
+
+ test('should emit "click" event when the title is clicked', async ({ page }) => {
+ const eventPromise = page.locator('kol-accordion').evaluate(async (element: HTMLKolAccordionElement, KolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.click, resolve);
+ });
+ }, KolEvent);
+ await page.waitForChanges();
+ await page.getByRole('button', { name: 'Accordion label' }).click();
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+
+ test('should call "onClick" callback when the title is clicked', async ({ page }) => {
+ const callbackPromise = page.locator('kol-accordion').evaluate(async (element: HTMLKolAccordionElement) => {
+ return new Promise((resolve) => {
+ element._on = {
+ onClick: (_event: MouseEvent, value?: boolean) => {
+ resolve(value);
+ },
+ };
+ });
+ });
+ await page.waitForChanges();
+ await page.getByRole('button', { name: 'Accordion label' }).click();
+ await expect(callbackPromise).resolves.toBe(true);
+ });
+ });
+
+ test.describe('when accordion is disabled', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setContent('Accordion contents ');
+ });
+
+ test('should not show the accordion content after the title has been clicked', async ({ page }) => {
+ await page.getByRole('button', { name: 'Accordion label' }).click({ force: true });
+ await expect(page.locator('.collapsible__content')).toHaveAttribute('aria-hidden', 'true');
+ });
+ });
+});
diff --git a/packages/components/src/components/accordion/component.tsx b/packages/components/src/components/accordion/component.tsx
deleted file mode 100644
index 62b3b787f7..0000000000
--- a/packages/components/src/components/accordion/component.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-// https://codepen.io/mbxtr/pen/OJPOYg?html-preprocessor=haml
-
-import { featureHint, propagateFocus, setState, validateDisabled, validateLabel, validateOpen } from '@public-ui/schema';
-import type { JSX } from '@stencil/core';
-import { Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { watchHeadingLevel } from '../heading/validation';
-import { KolHeadingWcTag, KolButtonWcTag } from '../../core/component-names';
-
-import type { AccordionAPI, AccordionStates, DisabledPropType, HeadingLevel, KoliBriAccordionCallbacks, LabelPropType, OpenPropType } from '@public-ui/schema';
-featureHint(`[KolAccordion] Anfrage nach einer KolAccordionGroup bei dem immer nur ein Accordion geöffnet ist.
-
-- onClick auf der KolAccordion anwenden
-- Click-Event prüft den _open-Status der Accordions
-- Logik Öffnet und Schließt entsprechend`);
-featureHint(`[KolAccordion] Tab-Sperre des Inhalts im geschlossenen Zustand.`);
-
-/**
- *
- * @slot - Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich des Accordions.
- */
-@Component({
- tag: 'kol-accordion',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolAccordion implements AccordionAPI {
- @Element() private readonly host?: HTMLKolDetailsElement;
- private readonly nonce = nonce();
-
- private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
- propagateFocus(this.host, ref);
- };
-
- public render(): JSX.Element {
- return (
-
-
-
- );
- }
-
- /**
- * Makes the element not focusable and ignore all events.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: string;
-
- /**
- * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
- */
- @Prop() public _level?: HeadingLevel = 1;
-
- /**
- * Gibt die EventCallback-Funktionen an.
- */
- @Prop() public _on?: KoliBriAccordionCallbacks;
-
- /**
- * If set (to true) opens/expands the element, closes if not set (or set to false).
- * @TODO: Change type back to `OpenPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _open?: boolean = false;
-
- @State() public state: AccordionStates = {
- _label: '', // ⚠ required
- _level: 1,
- };
-
- @Watch('_disabled')
- public validateDisabled(value?: DisabledPropType): void {
- validateDisabled(this, value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelPropType): void {
- validateLabel(this, value, {
- required: true,
- });
- }
-
- @Watch('_level')
- public validateLevel(value?: HeadingLevel): void {
- watchHeadingLevel(this, value);
- }
-
- @Watch('_on')
- public validateOn(value?: KoliBriAccordionCallbacks): void {
- if (typeof value === 'object' && value !== null && typeof value.onClick === 'function') {
- setState(this, '_on', value);
- }
- }
-
- @Watch('_open')
- public validateOpen(value?: OpenPropType): void {
- validateOpen(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateDisabled(this._disabled);
- this.validateLabel(this._label);
- this.validateLevel(this._level);
- this.validateOn(this._on);
- this.validateOpen(this._open);
- }
-
- private onClick = (event: Event) => {
- this._open = !this._open;
-
- /**
- * Der Timeout wird benötigt, damit das Event
- * vom Button- auf das Accordion-Event wechselt.
- * So ist es dem Anwendenden möglich das _open-
- * Attribute abzufragen.
- */
- setTimeout(() => {
- if (typeof this.state._on?.onClick === 'function') {
- this.state._on.onClick(event, this._open === true);
- }
- });
- };
-}
diff --git a/packages/components/src/components/accordion/readme.md b/packages/components/src/components/accordion/readme.md
deleted file mode 100644
index 4877f8ae11..0000000000
--- a/packages/components/src/components/accordion/readme.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# Accordion
-
-Die **Accordion**-Komponente ist ein Aufklapp-Menü. Klickt man auf den Kopfbereich, bestehend aus Icon und Überschrift, klappt der Inhalt mit zusätzlichen Informationen auf. Somit ist es ein interaktives Navigationselement, welches dazu dient, umfangreiche Inhalte platzsparend darzustellen.
-
-Accordions kommen immer dann zum Einsatz, wenn einem thematischen Oberbegriff zugeordnete Inhalte angezeigt oder verborgen werden sollen. Sie erlauben umfangreichere Detailinformationen zu einem Oberbegriff, als es aus Gründen der Übersichtlichkeit eigentlich sinnvoll wäre. Sie überlassen es den Besucher:innen selbst, ob sie sich diese Informationen anzeigen lassen möchten.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-
-```
-
-### Beispiel
-
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
- voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-
-
-## Verwendung
-
-### Überschrift im Accordion-Tab
-
-Der Text, der als Überschrift im Accordion-Tab angezeigt werden soll, wird durch das Attribut **`_label`** übergeben. Der Text kann neben Sonderzeichen auch Umlaute oder Leerzeichen enthalten.
-
-### Überschriftenebene
-
-Die Überschriftenebene wird durch das Attribut **`_level`** übergeben. Möglich sind die Level **1** bis **6**
-
-### Inhalt des Accordion
-
-Der Hauptinhalt des Accordions wird über deb Slot übergeben.
-
-**`Accordion-Inhalt `**
-
-### Accordion geöffnet anzeigen
-
-Standardmäßig wird das Accordion nach dem Laden der Seite im geschlossenen Zustand angezeigt. Soll das Accordion geöffnet angezeigt werden, setzen Sie das Attribut **\_open** zusätzlich ein.
-
-### Best practices
-
-- Verwenden Sie ein Accordion, um lange Textabschnitte unter einem thematischen Oberbegriff zusammenzufassen
-- Verwenden Sie ein Accordion, um weniger wichtige Informationen, als Ergänzung zu Hauptinformationen, zur Verfügung zu stellen.
-- Mit einem Accordion können Sie die Länge Ihrer Webseite deutlich reduzieren und stellen gleichzeitig die Erreichbarkeit aller Informationen für die Nutzer:innen sicher.
-- Verwenden Sie eindeutige Überschriften, um die Nutzer:innen auf die weiteren Informationen des Accordions hinzuweisen.
-- Vermeiden Sie, wichtige `Call-To-Action`-Elemente innerhalb eines Accordions zu verbergen.
-- Lassen Sie Fehlermeldungen nicht innerhalb des Accordions anzeigen, um zu vermeiden, dass Nutzer:innen wichtige Informationen übersehen.
-- Verwenden Sie ein Accordion nicht als Auswahl-Element für Nutzer:innen.
-- Verwenden Sie ein Accordion nicht, um wichtige Informationen zu rechtlichen Angaben oder zum Datenschutz anzuzeigen.
-
-### Anwendungsfälle
-
-- Häufig gestellte Fragen (FAQ)
-
-## Barrierefreiheit
-
-In der **Accordion**-Komponente wird das Öffnen-/Schließen-Icon links ausgerichtet, um Nutzer:innen mit eingeschränktem Sichtfeld eine bessere Bedienbarkeit zu ermöglichen.
-
-Es wurde bewusst auf die Verwendung von Icons, wie z.B. `<` oder `>` verzichtet. Die Verwendung der Icons `+` und `-` gewährleistet eine bessere Sicht- und Erkennbarkeit bezüglich des Geöffnet- und Geschlossen-Status.
-
-Bei der farblichen Gestaltung wurde besonders Wert auf einen höchstmöglichen Kontrast in der
-Standardansicht gelegt.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------- | ---------------------------------------------------- |
-| `Tab` | Springt die einzelnen Accordion-Tabs an. |
-| `Enter` | Öffnet bzw. schließt den fokussierten Accordion-Tab. |
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ----------- |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_level` | `_level` | Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text. | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` |
-| `_on` | -- | Gibt die EventCallback-Funktionen an. | `undefined \| { onClick?: EventValueOrEventCallback \| undefined; }` | `undefined` |
-| `_open` | `_open` | If set (to true) opens/expands the element, closes if not set (or set to false). | `boolean \| undefined` | `false` |
-
-## Slots
-
-| Slot | Description |
-| ---- | ------------------------------------------------------------------------------- |
-| | Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich des Accordions. |
-
----
diff --git a/packages/components/src/components/accordion/shadow.tsx b/packages/components/src/components/accordion/shadow.tsx
new file mode 100644
index 0000000000..7d30d49009
--- /dev/null
+++ b/packages/components/src/components/accordion/shadow.tsx
@@ -0,0 +1,167 @@
+// https://codepen.io/mbxtr/pen/OJPOYg?html-preprocessor=haml
+import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
+import type { JSX } from '@stencil/core';
+import type {
+ AccordionAPI,
+ AccordionStates,
+ AccordionCallbacksPropType,
+ DisabledPropType,
+ FocusableElement,
+ HeadingLevel,
+ LabelPropType,
+ OpenPropType,
+} from '../../schema';
+import { featureHint, validateAccordionCallbacks, validateDisabled, validateLabel, validateOpen } from '../../schema';
+import { nonce } from '../../utils/dev.utils';
+import { watchHeadingLevel } from '../heading/validation';
+import KolCollapsibleFc, { type CollapsibleProps } from '../../functional-components/Collapsible';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+
+featureHint(`[KolAccordion] Anfrage nach einer KolAccordionGroup bei dem immer nur ein Accordion geöffnet ist.
+
+- onClick auf der KolAccordion anwenden
+- Click-Event prüft den _open-Status der Accordions
+- Logik Öffnet und Schließt entsprechend`);
+featureHint(`[KolAccordion] Tab-Sperre des Inhalts im geschlossenen Zustand.`);
+
+/**
+ *
+ * @slot - Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich des Accordions.
+ */
+@Component({
+ tag: 'kol-accordion',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolAccordion implements AccordionAPI, FocusableElement {
+ @Element() private readonly host?: HTMLKolAccordionElement;
+
+ private readonly nonce = nonce();
+ private buttonWcRef?: HTMLKolButtonWcElement;
+
+ private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
+ this.buttonWcRef = ref;
+ };
+
+ @Method()
+ public async kolFocus() {
+ await this.buttonWcRef?.kolFocus();
+ }
+
+ private handleOnClick = (event: MouseEvent) => {
+ this._open = !this._open;
+
+ /**
+ * Der Timeout wird benötigt, damit das Event
+ * vom Button- auf das Accordion-Event wechselt.
+ * So ist es dem Anwendenden möglich das _open-
+ * Attribute abzufragen.
+ */
+ setTimeout(() => {
+ this.state._on?.onClick?.(event, this._open === true);
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.click, this._open === true);
+ }
+ });
+ };
+
+ public render(): JSX.Element {
+ const { _open, _label, _disabled, _level } = this.state;
+ const rootClass = 'kol-accordion';
+
+ const props: CollapsibleProps = {
+ id: this.nonce,
+ label: _label,
+ open: _open,
+ disabled: _disabled,
+ level: _level,
+ onClick: this.handleOnClick,
+ class: rootClass,
+ HeadingProps: { class: `${rootClass}__heading` },
+ HeadingButtonProps: {
+ ref: this.catchRef,
+ class: `${rootClass}__heading-button`,
+ },
+ ContentProps: {
+ class: `${rootClass}__content`,
+ wrapperClass: `${rootClass}__wrapper`,
+ animationClass: `${rootClass}__wrapper-animation`,
+ },
+ };
+
+ return (
+
+
+
+ );
+ }
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: string;
+
+ /**
+ * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
+ */
+ @Prop() public _level?: HeadingLevel = 1;
+
+ /**
+ * Gibt die EventCallback-Funktionen an.
+ */
+ @Prop() public _on?: AccordionCallbacksPropType;
+
+ /**
+ * Opens/expands the element when truthy, closes/collapses when falsy.
+ * @TODO: Change type back to `OpenPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _open?: boolean = false;
+
+ @State() public state: AccordionStates = {
+ _label: '', // ⚠ required
+ _level: 1,
+ _on: {},
+ };
+
+ @Watch('_disabled')
+ public validateDisabled(value?: DisabledPropType): void {
+ validateDisabled(this, value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ @Watch('_level')
+ public validateLevel(value?: HeadingLevel): void {
+ watchHeadingLevel(this, value);
+ }
+
+ @Watch('_on')
+ public validateOn(on?: AccordionCallbacksPropType): void {
+ validateAccordionCallbacks(this, on);
+ }
+
+ @Watch('_open')
+ public validateOpen(value?: OpenPropType): void {
+ validateOpen(this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateDisabled(this._disabled);
+ this.validateLabel(this._label);
+ this.validateLevel(this._level);
+ this.validateOn(this._on);
+ this.validateOpen(this._open);
+ }
+}
diff --git a/packages/components/src/components/accordion/style.scss b/packages/components/src/components/accordion/style.scss
index fef064f4e5..119f9a5162 100644
--- a/packages/components/src/components/accordion/style.scss
+++ b/packages/components/src/components/accordion/style.scss
@@ -1,49 +1,10 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
@import '../host-display-block';
+@import '../../functional-components/Collapsible/collapsible';
@layer kol-component {
- /* For animation technique see https://css-tricks.com/css-grid-can-do-auto-height-transitions/ */
- .wrapper {
- display: grid;
- grid-template-rows: 0fr;
- overflow: hidden;
- transition: grid-template-rows 0.3s;
- }
-
- .accordion.open .wrapper {
- grid-template-rows: 1fr;
- }
-
- .animation-wrapper {
- min-height: 0;
- transition: visibility 0.3s;
- /* This property is important to keep in sync with the visual transition (template-rows). Without it interactive elements within the accordion would stay focusable. */
- visibility: hidden;
- }
-
- .accordion.open .animation-wrapper {
- visibility: visible;
- }
-
- @media (prefers-reduced-motion) {
- .animation-wrapper,
- .wrapper {
- transition-duration: 0s;
- }
- }
-
- /* @see https://github.com/public-ui/kolibri/issues/5952 */
- @media print {
- .accordion:not(.open) .animation-wrapper {
- display: none;
- }
- }
-
- /*
- * Inside a button, the caption text is always centered.
- * So we have to align the text to the left.
- */
- .accordion .kol-heading-wc .kol-button-wc button .kol-span-wc {
- justify-items: start;
+ .kol-accordion {
+ font-size: rem(16);
}
}
diff --git a/packages/components/src/components/accordion/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/accordion/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..d482f6784e
--- /dev/null
+++ b/packages/components/src/components/accordion/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,210 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-accordion should render with _label="Überschrift" _level=1 _open=false _disabled=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=1 _open=false _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=1 _open=true _disabled=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=1 _open=true _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=1 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=2 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=3 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=4 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=5 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" _level=6 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-accordion should render with _label="Überschrift" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/accordion/test/html.mock.ts b/packages/components/src/components/accordion/test/html.mock.ts
deleted file mode 100644
index 0c4bd48b75..0000000000
--- a/packages/components/src/components/accordion/test/html.mock.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import type { AccordionProps } from '@public-ui/schema';
-import { KolButtonWcTag, KolHeadingWcTag } from '../../../core/component-names';
-
-export const getAccordionHtml = (
- props: AccordionProps,
- slots: {
- default?: string;
- footer?: string;
- } = {},
-): string => {
- props = mixMembers(
- {
- _label: '', // ⚠ required
- _level: 1,
- },
- props,
- );
- return `
-
-
- <${KolHeadingWcTag} _label="" _level="${props._level}" class="accordion-heading">
- <${KolButtonWcTag}
- class="accordion-button"
- slot="expert"
- _ariaControls="nonce"
- ${props._open ? '_ariaExpanded=""' : ''}
- ${props._disabled ? '_disabled=""' : ''}
- _icons="codicon codicon-${props._open ? 'remove' : 'add'}"
- _label="${props._label}"
- >${KolButtonWcTag}>
- ${KolHeadingWcTag}>
-
-
-
-
- ${slots.default !== undefined ? slots.default : ''}
- ${slots.footer !== undefined ? slots.footer : ''}
- `;
-};
diff --git a/packages/components/src/components/accordion/test/snapshot.spec.tsx b/packages/components/src/components/accordion/test/snapshot.spec.tsx
index e0e1bfcabd..1f9d899c4a 100644
--- a/packages/components/src/components/accordion/test/snapshot.spec.tsx
+++ b/packages/components/src/components/accordion/test/snapshot.spec.tsx
@@ -1,31 +1,20 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolAccordionTag } from '../../../core/component-names';
+import type { AccordionProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolAccordion } from '../shadow';
-import { getAccordionHtml } from './html.mock';
+const baseObject = { _label: 'Überschrift' };
-import type { AccordionProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
-import { KolAccordion } from '../component';
-
-executeTests(
- 'Accordion',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolAccordion],
- template: () => ,
- });
- return page;
- },
- {
- _disabled: [true, false],
- _label: ['Überschrift'],
- _level: [1, 2, 3, 4, 5, 6],
- _open: [true, false],
- },
- getAccordionHtml,
- {
- execMode: 'default', // ready
- },
+executeSnapshotTests(
+ KolAccordionTag,
+ [KolAccordion],
+ [
+ { ...baseObject },
+ ...([1, 2, 3, 4, 5, 6].map((_level) => ({ ...baseObject, _level })) as AccordionProps[]),
+ { ...baseObject, _level: 1, _open: false, _disabled: false },
+ { ...baseObject, _level: 1, _open: false, _disabled: true },
+ { ...baseObject, _level: 1, _open: true, _disabled: true },
+ { ...baseObject, _level: 1, _open: true, _disabled: false },
+ ],
);
diff --git a/packages/components/src/components/alert/alert.e2e.ts b/packages/components/src/components/alert/alert.e2e.ts
new file mode 100644
index 0000000000..949a3cbf03
--- /dev/null
+++ b/packages/components/src/components/alert/alert.e2e.ts
@@ -0,0 +1,37 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-alert', () => {
+ test.describe('Callbacks', () => {
+ test('should call "onClose" callback when the close button is clicked', async ({ page }) => {
+ await page.setContent(' ');
+ const callbackPromise = page.locator('kol-alert').evaluate(async (element: HTMLKolAlertElement) => {
+ return new Promise((resolve) => {
+ element._on = {
+ onClose: (_event: Event, value?: unknown) => {
+ resolve(value);
+ },
+ };
+ });
+ });
+ await page.waitForChanges();
+ await page.getByTestId('alert-close-button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+
+ test.describe('DOM events', () => {
+ test('should emit "close" when close button is clicked', async ({ page }) => {
+ await page.setContent(' ');
+ const eventPromise = page.locator('kol-alert').evaluate(async (element: HTMLKolAlertElement, KolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.close, resolve);
+ });
+ }, KolEvent);
+ await page.waitForChanges();
+ await page.getByTestId('alert-close-button').click();
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+});
diff --git a/packages/components/src/components/alert/component.tsx b/packages/components/src/components/alert/component.tsx
index 677532b896..4a3b71a914 100644
--- a/packages/components/src/components/alert/component.tsx
+++ b/packages/components/src/components/alert/component.tsx
@@ -1,41 +1,13 @@
import type { JSX } from '@stencil/core';
-import { Log, alertTypeOptions, alertVariantOptions, setState, validateHasCloser, validateLabel, watchBoolean, watchValidator } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import { translate } from '../../i18n';
+import { alertTypeOptions, alertVariantOptions, setState, validateHasCloser, validateLabel, watchBoolean, watchValidator } from '../../schema';
+import { Component, Element, h, Prop, State, Watch } from '@stencil/core';
import { watchHeadingLevel } from '../heading/validation';
-import { KolIconTag, KolHeadingWcTag, KolButtonWcTag } from '../../core/component-names';
-
-import type {
- AlertAPI,
- AlertStates,
- AlertType,
- AlertVariant,
- HasCloserPropType,
- HeadingLevel,
- KoliBriAlertEventCallbacks,
- LabelPropType,
-} from '@public-ui/schema';
-const Icon = (props: { ariaLabel: string; icon: string; label?: string }) => {
- return 0 ? '' : props.ariaLabel} _icons={props.icon} />;
-};
-
-const AlertIcon = (props: { label?: string; type?: AlertType }) => {
- switch (props.type) {
- case 'error':
- return ;
- case 'info':
- return ;
- case 'warning':
- return ;
- case 'success':
- return ;
- default:
- return ;
- }
-};
+import type { AlertAPI, AlertStates, AlertType, AlertVariant, HasCloserPropType, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '../../schema';
+import KolAlertFc, { type KolAlertFcProps } from '../../functional-components/Alert';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
/**
+ * @internal
* @slot - Der Inhalt der Meldung.
*/
@Component({
@@ -43,77 +15,37 @@ const AlertIcon = (props: { label?: string; type?: AlertType }) => {
shadow: false,
})
export class KolAlertWc implements AlertAPI {
+ @Element() private readonly host?: HTMLKolAlertWcElement;
+
private readonly close = () => {
- if (this._on?.onClose !== undefined) {
- this._on.onClose(new Event('Close'));
+ this._on?.onClose?.(new Event('Close'));
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.close);
}
};
- private readonly on = {
- onClick: this.close,
+ private readonly handleAlertTimeout = () => {
+ this.validateAlert(false);
};
public render(): JSX.Element {
- if (this.state._alert) {
- /**
- * - https://developer.mozilla.org/de/docs/Web/API/Navigator/vibrate
- * - https://googlechrome.github.io/samples/vibration/
- */
- try {
- Log.debug(['Navigator should vibrate ...', navigator.vibrate([100, 75, 100, 75, 100])]);
- } catch (e) {
- Log.debug('Navigator does not support vibration.');
- }
-
- setTimeout(() => {
- this.validateAlert(false);
- }, 10000);
- }
+ const { _alert, _hasCloser, _label, _level, _type, _variant } = this.state;
+
+ const props: KolAlertFcProps = {
+ alert: _alert,
+ hasCloser: _hasCloser,
+ label: _label,
+ level: _level,
+ type: _type,
+ variant: _variant,
+ onCloserClick: this.close,
+ onAlertTimeout: this.handleAlertTimeout,
+ };
return (
-
-
-
-
- {typeof this.state._label === 'string' && this.state._label?.length > 0 && (
-
- )}
- {this.state._variant === 'msg' && (
-
-
-
- )}
-
- {this.state._hasCloser && (
-
- )}
-
- {this.state._variant === 'card' && (
-
-
-
- )}
-
+
+
+
);
}
diff --git a/packages/components/src/components/alert/readme.md b/packages/components/src/components/alert/readme.md
deleted file mode 100644
index 413dbc969a..0000000000
--- a/packages/components/src/components/alert/readme.md
+++ /dev/null
@@ -1,98 +0,0 @@
-# Alert
-
-Die **Alert**-Komponente gibt ein optisches Feedback an die Nutzer:innen. Sie besteht aus einem farblich gestalteten Container, einer Überschrift, einem Inhaltstext sowie einem Icon. Das verwendete Icon und die farbliche Gestaltung sind abhängig vom Typ `_type` des Alert.
-
-## Konstruktion
-
-### Code
-
-```html
-Textbereich im Alert
-Textbereich im Alert
-```
-
-### Beispiel
-
-Textbereich im Alert
-Textbereich im Alert
-
-## Verwendung
-
-### Überschrift
-
-Die **Überschrift** der Alert-Komponente wird über das Attribut `_label` bestimmt.
-
-### Überschriftenebene
-
-Die Überschriftenebene wird durch das Attribut **`_level`** übergeben. Möglich sind die Level **1** bis **6**
-
-### Typ des Alert
-
-Die **Alert**-Komponente bietet **vier** unterschiedliche Typen, die sich jeweils auf die farbliche Gestaltung und das verwendetet Icon im Alert beziehen. Zur Wahl stehen:
-
-
-Success
-Error
-Info
-Warning
-
-
-Der Typ eines Alert wird über das Attribut `_type` festgelegt.
-
-### Inhalt des Alert
-
-Der Inhalt des Alert wird zwischen das öffnende Element `` und das schließende ` ` geschrieben. Der Inhalt kann aus beliebigem **HTML-Code**, aber auch aus weiteren **KoliBri**-Komponenten bestehen.
-
-### Variante des Alert
-
-Über das Attribut **`_variant`** kann festgelegt werden, in welcher Darstellungsvariante das Alert angezeigt wird. `msg` lässt die linke, farbig hinterlegte Spalte mit dem Icon über die gesamte Höhe des Alerts gehen, `card` setzt die linke Spalte nur neben die Überchrift.
-
-### Best practices
-
-- Verwenden Sie die **Alert**-Komponente an geeigneten Positionen auf Ihrer Webseite, um Informationen im richtigen Zusammenhang darzustellen.
-- Verwenden Sie immer den richtigen **Type** der **Alert**-Komponente, um bei den Benutzer:innen die gewünschte Reaktion zu erzeugen. Vermeiden Sie bspw. den Typ **_Error_**, wenn Sie auf den erfolgreichen Abschluss eines Speichervorgangs hinweisen möchten.
-- Vermeiden Sie, zu viele **Alert**-Komponenten auf einer Seite zu platzieren, da der Informationsgehalt von den Benutzer:innen dann oft nicht mehr als besonders wichtig wahrgenommen wird.
-
-### Anwendungsfälle
-
-- Verwenden Sie die **Alert**-Komponente, wenn Sie die Benutzer:innen auf Fehler bei der Eingabe in Formularen hinweisen möchten.
-- Verwenden Sie die **Alert**-Komponente, um Nutzer:innen auf die erfolgreiche Ausführung von Funktionen hinzuweisen, z.B. **`Ihre Anfrage wurde erfolgreich gespeichert`**.
-- Verwenden Sie die **Alert**-Komponente, um Nutzer:innen weitere Informationen zu einem Thema zur Verfügung zu stellen.
-
-## Barrierefreiheit
-
-Die **Alert**-Komponente wurde auf die Darstellung mit höchstmöglichen Kontrast optimiert.
-
-Das zusätzliche Icon (je nach gewähltem Typ) gewährleistet, dass die Information vom Nutzer nicht allein über die Farbe klassifiziert werden muss.
-
-Bei der **Alert**-Komponente wurden insbesondere folgende Punkte der Barrierefreiheit betrachtet:
-
-- Die Schriftfarbe ist entweder weiß oder schwarz.
-- Die Schriftfarbe ist abhängig von der Hintergrundfarbe und wechselt immer auf die Schriftfarbe mit dem größeren Farbkontrast zur Hintergrundfarbe.
-- Ist der Farbkontrast für AA nicht ausreichend, wird die Hintergrundfarbe überschrieben.
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| ------------ | ------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | ----------- |
-| `_alert` | `_alert` | Defines whether the screen-readers should read out the notification. | `boolean \| undefined` | `false` |
-| `_hasCloser` | `_has-closer` | Defines whether the element can be closed. | `boolean \| undefined` | `false` |
-| `_label` | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string \| undefined` | `undefined` |
-| `_level` | `_level` | Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text. | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` |
-| `_on` | -- | Gibt die EventCallback-Function für das Schließen des Alerts an. | `undefined \| { onClose?: EventCallback \| undefined; }` | `undefined` |
-| `_type` | `_type` | Defines either the type of the component or of the components interactive element. | `"default" \| "error" \| "info" \| "success" \| "warning" \| undefined` | `'default'` |
-| `_variant` | `_variant` | Defines which variant should be used for presentation. | `"card" \| "msg" \| undefined` | `'msg'` |
-
-## Slots
-
-| Slot | Description |
-| ---- | ----------------------- |
-| | Der Inhalt der Meldung. |
-
----
diff --git a/packages/components/src/components/alert/shadow.tsx b/packages/components/src/components/alert/shadow.tsx
index 0b82fed848..9c2bf48c05 100644
--- a/packages/components/src/components/alert/shadow.tsx
+++ b/packages/components/src/components/alert/shadow.tsx
@@ -1,6 +1,6 @@
-import type { AlertProps, AlertStates, AlertType, AlertVariant, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '@public-ui/schema';
+import type { AlertProps, AlertStates, AlertType, AlertVariant, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '../../schema';
import type { JSX } from '@stencil/core';
-import { Component, h, Host, Prop, State } from '@stencil/core';
+import { Component, h, Prop, State } from '@stencil/core';
import { KolAlertWcTag } from '../../core/component-names';
/**
@@ -16,19 +16,17 @@ import { KolAlertWcTag } from '../../core/component-names';
export class KolAlert implements AlertProps {
public render(): JSX.Element {
return (
-
-
-
-
-
+
+
+
);
}
diff --git a/packages/components/src/components/alert/style.scss b/packages/components/src/components/alert/style.scss
index de58818d78..7b766521a6 100644
--- a/packages/components/src/components/alert/style.scss
+++ b/packages/components/src/components/alert/style.scss
@@ -1,3 +1,11 @@
-@import '../@shared/kol-alert-mixin.scss';
+@import '../../styles/global';
+@import '../../styles/kol-alert-mixin';
+@import '../@shared/mixins';
-@include kol-alert-styles;
+@include kol-alert;
+
+@layer kol-component {
+ .kol-alert {
+ font-size: rem(16);
+ }
+}
diff --git a/packages/components/src/components/alert/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/alert/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..8189c4343d
--- /dev/null
+++ b/packages/components/src/components/alert/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,1381 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=1 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=1 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=1 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=1 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=1 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=2 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=2 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=2 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=2 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=2 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=3 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=3 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=3 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=3 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=3 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=4 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=4 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=4 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=4 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=4 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=5 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=5 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=5 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=5 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=5 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=6 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=6 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=6 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=6 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=false _level=6 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=1 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=1 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=1 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=1 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=1 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=2 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=2 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=2 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=2 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=2 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=3 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=3 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=3 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=3 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=3 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=4 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=4 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=4 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=4 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=4 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=5 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=5 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=5 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=5 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=5 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=6 _type="default" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=6 _type="error" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=6 _type="info" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=6 _type="success" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-alert should render with _label="Überschrift" _alert=true _level=6 _type="warning" 1`] = `
+
+
+
+
+
+
+
+
+
+ Überschrift
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/alert/test/html.mock.ts b/packages/components/src/components/alert/test/html.mock.ts
deleted file mode 100644
index 356c1e18f5..0000000000
--- a/packages/components/src/components/alert/test/html.mock.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import { translate } from '../../../i18n';
-
-import type { AlertProps } from '@public-ui/schema';
-import { KolIconTag, KolHeadingWcTag, KolButtonWcTag } from '../../../core/component-names';
-export const getAlertHtml = (props: AlertProps, innerHTML = '', additionalHTML = ''): string => {
- props = mixMembers(
- {
- _level: 1,
- },
- props,
- );
- const type: string = props._type !== undefined ? props._type : 'default';
- props._type = props._type || 'default';
- props._variant = props._variant || 'msg';
- return `
-
-
-
- <${KolIconTag}
- class="heading-icon"
- _label="${
- props._label !== undefined
- ? ''
- : props._type === 'success'
- ? 'kol-success'
- : props._type === 'error'
- ? 'kol-error'
- : props._type === 'warning'
- ? 'kol-warning'
- : props._type === 'info'
- ? 'kol-info'
- : 'kol-message'
- }"
- _icons="${
- props._type === 'success'
- ? 'codicon codicon-pass'
- : props._type === 'error'
- ? 'codicon codicon-error'
- : props._type === 'warning'
- ? 'codicon codicon-warning'
- : props._type === 'info'
- ? 'codicon codicon-info'
- : 'codicon codicon-comment'
- }"
- >
- ${KolIconTag}>
-
-
-
- ${typeof props._label === 'string' && props._label.length > 0 ? `<${KolHeadingWcTag} _label="${props._label}" _level="${props._level}"> ${KolHeadingWcTag}>` : ''}
-
- ${
- props._variant === 'msg'
- ? `
-
-
`
- : ''
- }
-
- ${
- props._hasCloser
- ? `<${KolButtonWcTag}
- class="close"
- _hideLabel
- _icons={{
- left: {
- icon: 'codicon codicon-close',
- },
- }}
- _label="${translate('kol-close')}"
- _tooltipAlign="left"
- >${KolButtonWcTag}>`
- : ''
- }
-
${
- props._variant === 'card'
- ? `
-
-
`
- : ''
- }
-
-
- ${innerHTML}
- `;
-};
diff --git a/packages/components/src/components/alert/test/snapshot.spec.tsx b/packages/components/src/components/alert/test/snapshot.spec.tsx
index 0290feed2f..65f4de10f6 100644
--- a/packages/components/src/components/alert/test/snapshot.spec.tsx
+++ b/packages/components/src/components/alert/test/snapshot.spec.tsx
@@ -1,32 +1,24 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolAlertTag } from '../../../core/component-names';
+import type { AlertProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getAlertHtml } from './html.mock';
-
-import type { AlertProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
import { KolAlert } from '../shadow';
import { KolAlertWc } from '../component';
-executeTests(
- 'Alert',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolAlert, KolAlertWc],
- template: () => ,
- });
- return page;
- },
- {
- _alert: [false, true],
- _label: ['Überschrift'],
- _level: [1, 2, 3, 4, 5, 6],
- _type: ['default', 'error', 'info', 'success', 'warning'],
- },
- getAlertHtml,
- {
- needTimers: true,
- },
+const baseObject = { _label: 'Überschrift' };
+const baseArray = [true, false].map((_alert) => ({ ...baseObject, _alert }));
+
+function buildByType(_type: 'default' | 'error' | 'info' | 'success' | 'warning') {
+ const nextArray: AlertProps[] = [];
+ [1, 2, 3, 4, 5, 6].forEach((_level) => {
+ nextArray.push(...baseArray.map((o) => ({ ...o, _level, _type }) as AlertProps));
+ });
+
+ return nextArray;
+}
+
+executeSnapshotTests(
+ KolAlertTag,
+ [KolAlert, KolAlertWc],
+ [...buildByType('default'), ...buildByType('error'), ...buildByType('info'), ...buildByType('success'), ...buildByType('warning')],
);
diff --git a/packages/components/src/components/avatar/component.tsx b/packages/components/src/components/avatar/component.tsx
index b9eb6575c2..a893f6a59b 100644
--- a/packages/components/src/components/avatar/component.tsx
+++ b/packages/components/src/components/avatar/component.tsx
@@ -1,11 +1,15 @@
import type { JSX } from '@stencil/core';
-import { validateImageSource, validateLabel } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
+import { validateImageSource, validateLabel } from '../../schema';
+import { Component, h, Prop, State, Watch } from '@stencil/core';
import { translate } from '../../i18n';
import { formatLabelAsInitials } from './controller';
-import type { AvatarAPI, AvatarStates, ImageSourcePropType, LabelPropType } from '@public-ui/schema';
+import type { AvatarAPI, AvatarStates, ImageSourcePropType, LabelPropType } from '../../schema';
+
+/**
+ * @internal
+ */
@Component({
tag: 'kol-avatar-wc',
shadow: false,
@@ -13,17 +17,15 @@ import type { AvatarAPI, AvatarStates, ImageSourcePropType, LabelPropType } from
export class KolAvatarWc implements AvatarAPI {
public render(): JSX.Element {
return (
-
-
- {this.state._src ? (
-
- ) : (
-
- {formatLabelAsInitials(this.state._label.trim())}
-
- )}
-
-
+
+ {this.state._src ? (
+
+ ) : (
+
+ {formatLabelAsInitials(this.state._label.trim())}
+
+ )}
+
);
}
diff --git a/packages/components/src/components/avatar/readme.md b/packages/components/src/components/avatar/readme.md
deleted file mode 100644
index f30dd0d200..0000000000
--- a/packages/components/src/components/avatar/readme.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Avatar
-
-Die **Avatar**-Komponente zeigt entweder ein kleines Bild des Users oder dessen Initialen an, falls kein Bild vorhanden ist.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
-```
-
-### Beispiele
-
-
-
-
-
-## Verwendung
-
-### Mit Bild
-
-In der Standard-Ansicht zeigt die **Avatar**-Komponente ein Avatar-Bild. Hierzu muss das Attribut `_src` mit einer URL zum Bild angegeben werden.
-Zusätzlich ist es notwendig, das `_label`-Attribut mit dem Namen des Benutzers anzugeben, damit ein Alternativtext ausgezeichnet werden kann.
-
-### Ohne Bild
-
-Die **Avatar**-Komponente kann auch ohne `_src`-Attribut verwendet werden und zeigt in diesem Fall die Initialen des Benutzers, basierend auf dem
-`_label`-Attribut.
-
-### Anwendungsfälle
-
-Verwenden Sie die **Avatar**-Komponente, um das Bild eines Users anzuzeigen.
-
-## Barrierefreiheit
-
-Bei der **Avatar**-Komponente wurden insbesondere folgende Punkte der Barrierefreiheit betrachtet:
-
-- Die Komponente ist mit einem Beschreibungstext, der den Namen des Users beinhaltet, als aria-label ausgezeichnet.
-- Die Initialen, die alternativ zum Avatar-Bild gezeigt werden, werden als rein visuelles, semantisch nicht relevantes Element betrachtet und für Screenreader
- entsprechend versteckt.
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ | --------------------- | ----------- |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_src` | `_src` | Sets the image `src` attribute to the given string. | `string \| undefined` | `undefined` |
-
----
diff --git a/packages/components/src/components/avatar/shadow.tsx b/packages/components/src/components/avatar/shadow.tsx
index 812c67e10a..543877bcf3 100644
--- a/packages/components/src/components/avatar/shadow.tsx
+++ b/packages/components/src/components/avatar/shadow.tsx
@@ -1,7 +1,7 @@
import type { JSX } from '@stencil/core';
-import { Component, h, Host, Prop } from '@stencil/core';
+import { Component, h, Prop } from '@stencil/core';
-import type { AvatarProps } from '@public-ui/schema';
+import type { AvatarProps } from '../../schema';
import { KolAvatarWcTag } from '../../core/component-names';
@Component({
@@ -13,11 +13,7 @@ import { KolAvatarWcTag } from '../../core/component-names';
})
export class KolAvatar implements AvatarProps {
public render(): JSX.Element {
- return (
-
-
-
- );
+ return ;
}
/**
diff --git a/packages/components/src/components/avatar/style.scss b/packages/components/src/components/avatar/style.scss
index 8f491ecf01..3ad65cd7b5 100644
--- a/packages/components/src/components/avatar/style.scss
+++ b/packages/components/src/components/avatar/style.scss
@@ -1,31 +1,32 @@
@import '../@shared/mixins';
-@import '../style';
+@import '../../styles/global';
@import '../host-display-block';
@layer kol-component {
- .container {
+ .kol-avatar {
+ font-size: rem(16);
border-radius: 50%;
overflow: hidden;
/* Visible with forced colors */
- outline: transparent solid 1px;
+ outline: transparent solid rem(1);
/*theme?*/
- width: 100px;
- height: 100px;
- }
+ width: rem(100);
+ height: rem(100);
- .image {
- width: 100%;
- height: 100%;
- }
+ &__image {
+ width: 100%;
+ height: 100%;
+ }
- .initials {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- /*theme?*/
- background: #d3d3d3;
- font-size: rem(32);
+ &__initials {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ /*theme?*/
+ background-color: #d3d3d3;
+ font-size: rem(40);
+ }
}
}
diff --git a/packages/components/src/components/avatar/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/avatar/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..797fe40fcd
--- /dev/null
+++ b/packages/components/src/components/avatar/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-avatar should render with _label="Erika Maria Mustermann" _src=undefined 1`] = `
+
+
+
+
+
+ EM
+
+
+
+
+
+`;
+
+exports[`kol-avatar should render with _label="Erika" _src="/image.webp" 1`] = `
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-avatar should render with _label="Erika" _src=undefined 1`] = `
+
+
+
+
+
+ E
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/avatar/test/html.mock.ts b/packages/components/src/components/avatar/test/html.mock.ts
deleted file mode 100644
index 27a2f361b7..0000000000
--- a/packages/components/src/components/avatar/test/html.mock.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import { formatLabelAsInitials } from '../controller';
-
-import type { AvatarProps, AvatarStates } from '@public-ui/schema';
-
-export const getAvatarHtml = (props: AvatarProps): string => {
- const state = mixMembers(
- {
- _src: '',
- _label: '', // ⚠ required
- },
- props,
- );
-
- return `
-
-
-
-
- ${
- state._src
- ? `
`
- : `
- ${formatLabelAsInitials(state._label)}
- `
- }
-
-
-
-
-`;
-};
diff --git a/packages/components/src/components/avatar/test/snapshot.spec.tsx b/packages/components/src/components/avatar/test/snapshot.spec.tsx
index 1619157ada..b5388562d4 100644
--- a/packages/components/src/components/avatar/test/snapshot.spec.tsx
+++ b/packages/components/src/components/avatar/test/snapshot.spec.tsx
@@ -1,27 +1,15 @@
-import { executeTests } from 'stencil-awesome-test';
-
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getAvatarHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { AvatarProps } from '@public-ui/schema';
import { KolAvatar } from '../shadow';
import { KolAvatarWc } from '../component';
-
-executeTests(
- 'Avatar',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolAvatar, KolAvatarWc],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Erika Maria Mustermann', `Erika`],
- _src: [`/example-image.jpg`],
- },
- getAvatarHtml,
+import type { AvatarProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
+import { KolAvatarTag } from '../../../core/component-names';
+
+executeSnapshotTests(
+ KolAvatarTag,
+ [KolAvatar, KolAvatarWc],
+ [
+ { _label: 'Erika Maria Mustermann', _src: undefined },
+ { _label: 'Erika', _src: undefined },
+ { _label: 'Erika', _src: '/image.webp' },
+ ],
);
diff --git a/packages/components/src/components/badge/badge.e2e.ts b/packages/components/src/components/badge/badge.e2e.ts
new file mode 100644
index 0000000000..19a3c7a67d
--- /dev/null
+++ b/packages/components/src/components/badge/badge.e2e.ts
@@ -0,0 +1,48 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-badge', () => {
+ test.describe('Callbacks', () => {
+ ['onClick', 'onMouseDown'].forEach((callbackName) => {
+ test(`should call ${callbackName} callback when smart button emits`, async ({ page }) => {
+ await page.setContent(` `);
+ const kolBadge = page.locator('kol-badge');
+
+ const callbackPromise = kolBadge.evaluate((element: HTMLKolBadgeElement, callbackName) => {
+ return new Promise((resolve) => {
+ element._smartButton = {
+ _label: `Smart Button`,
+ _on: {
+ [callbackName]: () => {
+ resolve();
+ },
+ },
+ };
+ });
+ }, callbackName);
+ await page.waitForChanges();
+
+ await page.locator('button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+ });
+
+ test.describe('DOM events', () => {
+ [KolEvent.click, KolEvent.mousedown].forEach((event) => {
+ test(`should emit ${event} when smart button emits ${event}`, async ({ page }) => {
+ const BADGE_PROPS = { _label: `Smart Button` };
+ await page.setContent(` `);
+ const eventPromise = page.locator('kol-badge').evaluate(async (element, event) => {
+ return new Promise((resolve) => {
+ element.addEventListener(event, resolve);
+ });
+ }, event);
+ await page.waitForChanges();
+ await page.locator('button').dispatchEvent(event);
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/packages/components/src/components/badge/component.tsx b/packages/components/src/components/badge/component.tsx
deleted file mode 100644
index fbab6ca5e7..0000000000
--- a/packages/components/src/components/badge/component.tsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import type { BadgeAPI, BadgeStates, ButtonProps, KoliBriIconsProp, LabelPropType, PropColor, Stringified } from '@public-ui/schema';
-import { featureHint, handleColorChange, objectObjectHandler, parseJson, setState, validateColor } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-import { KolSpanWcTag } from '../../core/component-names';
-
-import { nonce } from '../../utils/dev.utils';
-
-import type { JSX } from '@stencil/core';
-import { KolButtonWcTag } from '../../core/component-names';
-featureHint(`[KolBadge] Optimierung des _color-Properties (rgba, rgb, hex usw.).`);
-
-@Component({
- tag: 'kol-badge',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolBadge implements BadgeAPI {
- private bgColorStr = '#000';
- private colorStr = '#fff';
- private readonly id = nonce();
-
- private renderSmartButton(props: ButtonProps): JSX.Element {
- return (
-
- );
- }
-
- public render(): JSX.Element {
- const hasSmartButton = typeof this.state._smartButton === 'object' && this.state._smartButton !== null;
- return (
-
-
-
- {hasSmartButton && this.renderSmartButton(this.state._smartButton as ButtonProps)}
-
-
- );
- }
-
- /**
- * Defines the backgroundColor and foregroundColor.
- */
- @Prop() public _color?: Stringified = '#000';
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: Stringified;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- /**
- * Allows to add a button with an arbitrary action within the element (_hide-label only).
- */
- @Prop() public _smartButton?: Stringified;
-
- @State() public state: BadgeStates = {
- _color: {
- backgroundColor: '#000',
- foregroundColor: '#fff',
- },
- };
-
- private handleColorChange = (value: unknown) => {
- const colorPair = handleColorChange(value);
- this.bgColorStr = colorPair.backgroundColor;
- this.colorStr = colorPair.foregroundColor as string;
- };
-
- @Watch('_color')
- public validateColor(value?: Stringified): void {
- validateColor(this, value, {
- defaultValue: '#000',
- hooks: {
- beforePatch: this.handleColorChange,
- },
- });
- }
-
- @Watch('_smartButton')
- public validateSmartButton(value?: ButtonProps | string): void {
- objectObjectHandler(value, () => {
- try {
- value = parseJson(value as string);
- // eslint-disable-next-line no-empty
- } catch (e) {
- // value behält den ursprünglichen Wert
- }
- setState(this, '_smartButton', value);
- });
- }
-
- public componentWillLoad(): void {
- this.validateColor(this._color);
- this.validateSmartButton(this._smartButton);
- }
-}
diff --git a/packages/components/src/components/badge/readme.md b/packages/components/src/components/badge/readme.md
deleted file mode 100644
index d59001aa8f..0000000000
--- a/packages/components/src/components/badge/readme.md
+++ /dev/null
@@ -1,109 +0,0 @@
-# Badge
-
-Mit **Badges** können Sie bestimmte Informationen auf Ihrer Webseite optisch hervorheben.
-KoliBri bietet neben der Angabe der Hintergrundfarbe und automatischer Berechnung der Textfarbe auch die Möglichkeit, einem Badge ein Icon und/oder einen anderen Schriftschnitt mitzugeben.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-```
-
-### Beispiel
-
-
-
-
-## Kontext für Badges
-
-Um die Benutzerfreundlichkeit und die Zugänglichkeit zu verbessern, sollten Badges
-immer im Kontext einer aussagekräftigen Überschrift verwendet werden.
-
-Stellen Sie sicher, dass jede Gruppe von Badges durch eine Überschrift ergänzt wird, die den gemeinsamen Kontext oder das Thema beschreibt. Vermeiden Sie es, Badges ohne solche beschreibenden Überschriften zu präsentieren.
-
-### Beispiel
-
-```html
-
-
-
-
-
-```
-
-## Verwendung
-
-### Label im Badge
-
-Der Text, der im Badge angezeigt werden soll, wird über das Attribut **\_label** übergeben. Der Text kann neben Sonderzeichen auch Umlaute oder Leerzeichen enthalten.
-Das Element ` ` beinhaltet selbst keinen Text.
-
-### Hintergrundfarbe des Badge
-
-Ein Badge, ohne weitere Angaben zur Hintergrundfarbe, wird standardmäßig mit hellgrauer Schriftfarbe auf schwarzem Hintergrund angezeigt. Über das Attribut **\_color** können andere Hintergrundfarben gewählt werden.
-
-Die Angabe der gewünschten Hintergrundfarbe erfolgt in hexadezimaler Schreibweise, z.B. **\_color="#000000"** für schwarz.
-
-Die Textfarbe wird automatisch als Kontrastfarbe zur gewählten Hintergrundfarbe errechnet.
-
-### Icons
-
-Ein Icon (**`_icon`**) kann entweder als String angegeben werden, oder als Objekt.
-Als String übergeben Sie die Iconklasse (z.B.: `_icons="codicon codicon-home`), das Icon wird links vom Text angezeigt.
-Das Objekt ist vom Typ `KoliBriAllIcon`, kann also einen oder mehrere der Schlüssel `top`, `right`, `bottom` und `left` besitzen. Diese sind dann entweder String (siehe oben) oder ein Objekt vom Typ `KoliBriCustomIcon`, welches aus `icon` (String, siehe oben) und `style` (optional, Styleobjekt) besteht.
-
-
-
-### Schriftschnitt
-
-Der Schriftschnitt wird vom Host übernommen, kann also via CSS von außen gesetzt werden.
-
-### Best practices
-
-- Verwenden Sie Badges, um wichtige Informationen in unmittelbarer Nähe des jeweiligen Elements anzuzeigen.
-- Verwenden Sie Badges, um auf geänderte Werte oder einen geänderten Status aufmerksam zu machen.
-- Ein Badge weist den Benutzer darauf hin, dass etwas neu erzeugt oder aktualisiert wurde, z. B. ein „ungelesener Bericht“ oder eine Aktivitätsbenachrichtigung.
-- Behalten Sie in gleichen Anwendungsfällen immer die gleiche Position des Badges bei, um ein einheitliches Erscheinungsbild zu gewährleisten.
-
-## Anwendungsfälle
-
-### Badge als Aufzählungszeichen verwenden
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-## Barrierefreiheit
-
-Für die Einhaltung der Regeln zur Barrierefreiheit, ist ein optimaler Kontrast zwischen der Hintergrundfarbe und Textfarbe des Badge zwingend erforderlich. KoliBri bietet daher eine automatische Berechnung der Textfarbe aus der gewählten Hintergrundfarbe heraus. Möglich sind die Textfarben **schwarz** und **weiß**, die in Abhängigkeit zur Hintergrundfarbe ausgegeben werden.
-
-Die zusätzliche Ausgabe eines **Icon** gewährleistet, dass der Nutzer auch hierüber die Art der Information erfassen kann.
-
-Eine explizite Angabe der Textfarbe ist nicht möglich.
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_color` | `_color` | Defines the backgroundColor and foregroundColor. | `string \| undefined \| { backgroundColor: string; foregroundColor: Stringified; }` | `'#000'` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `KoliBriHorizontalIcons & KoliBriVerticalIcons \| string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_smartButton` | `_smart-button` | Allows to add a button with an arbitrary action within the element (\_hide-label only). | `string \| undefined \| { _label: string; } & { _tabIndex?: number \| undefined; _value?: Stringified; _role?: AlternativeButtonLinkRolePropType \| undefined; _ariaControls?: string \| undefined; _ariaExpanded?: boolean \| undefined; _ariaSelected?: boolean \| undefined; _on?: ButtonCallbacksPropType \| undefined; _type?: "button" \| "reset" \| "submit" \| undefined; _variant?: "primary" \| "secondary" \| "normal" \| "tertiary" \| "danger" \| "ghost" \| "custom" \| undefined; _customClass?: string \| undefined; _disabled?: boolean \| undefined; _hideLabel?: boolean \| undefined; _icons?: IconsPropType \| undefined; _id?: string \| undefined; _name?: string \| undefined; _syncValueBySelector?: string \| undefined; _tooltipAlign?: AlignPropType \| undefined; _accessKey?: string \| undefined; }` | `undefined` |
-
----
diff --git a/packages/components/src/components/badge/shadow.tsx b/packages/components/src/components/badge/shadow.tsx
new file mode 100644
index 0000000000..0a1c22d963
--- /dev/null
+++ b/packages/components/src/components/badge/shadow.tsx
@@ -0,0 +1,129 @@
+import type { BadgeAPI, BadgeStates, ButtonProps, KoliBriIconsProp, LabelPropType, PropColor, Stringified } from '../../schema';
+import { featureHint, handleColorChange, objectObjectHandler, parseJson, setState, validateColor, validateIcons } from '../../schema';
+import { Component, h, Prop, State, Watch } from '@stencil/core';
+import { KolSpanFc } from '../../functional-components';
+
+import { nonce } from '../../utils/dev.utils';
+
+import type { JSX } from '@stencil/core';
+import { KolButtonWcTag } from '../../core/component-names';
+import clsx from 'clsx';
+featureHint(`[KolBadge] Optimierung des _color-Properties (rgba, rgb, hex usw.).`);
+
+@Component({
+ tag: 'kol-badge',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolBadge implements BadgeAPI {
+ private bgColorStr = '#000';
+ private colorStr = '#fff';
+ private readonly id = nonce();
+
+ private renderSmartButton(props: ButtonProps): JSX.Element {
+ return (
+
+ );
+ }
+
+ public render(): JSX.Element {
+ const hasSmartButton = typeof this.state._smartButton === 'object' && this.state._smartButton !== null;
+
+ return (
+
+
+ {hasSmartButton && this.renderSmartButton(this.state._smartButton as ButtonProps)}
+
+ );
+ }
+
+ /**
+ * Defines the backgroundColor and foregroundColor.
+ */
+ @Prop() public _color?: Stringified = '#000';
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: Stringified;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ /**
+ * Allows to add a button with an arbitrary action within the element (_hide-label only).
+ */
+ @Prop() public _smartButton?: Stringified;
+
+ @State() public state: BadgeStates = {
+ _color: {
+ backgroundColor: '#000',
+ foregroundColor: '#fff',
+ },
+ _icons: {},
+ };
+
+ private handleColorChange = (value: unknown) => {
+ const colorPair = handleColorChange(value);
+ this.bgColorStr = colorPair.backgroundColor;
+ this.colorStr = colorPair.foregroundColor as string;
+ };
+
+ @Watch('_icons')
+ public validateIcons(value?: KoliBriIconsProp): void {
+ validateIcons(this, value);
+ }
+
+ @Watch('_color')
+ public validateColor(value?: Stringified): void {
+ validateColor(this, value, {
+ defaultValue: '#000',
+ hooks: {
+ beforePatch: this.handleColorChange,
+ },
+ });
+ }
+
+ @Watch('_smartButton')
+ public validateSmartButton(value?: ButtonProps | string): void {
+ objectObjectHandler(value, () => {
+ try {
+ value = parseJson(value as string);
+ // eslint-disable-next-line no-empty
+ } catch (e) {
+ // value behält den ursprünglichen Wert
+ }
+ setState(this, '_smartButton', value);
+ });
+ }
+
+ public componentWillLoad(): void {
+ this.validateIcons(this._icons);
+ this.validateColor(this._color);
+ this.validateSmartButton(this._smartButton);
+ }
+}
diff --git a/packages/components/src/components/badge/style.scss b/packages/components/src/components/badge/style.scss
index cd9c86f118..a9fd1fbf52 100644
--- a/packages/components/src/components/badge/style.scss
+++ b/packages/components/src/components/badge/style.scss
@@ -1,14 +1,19 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../tooltip/style.scss';
@layer kol-component {
- :host > span {
+ .kol-badge {
display: inline-flex;
place-items: center;
/* Visible with forced colors */
- outline: transparent solid 1px;
- }
+ outline: transparent solid rem(1);
+ font-size: rem(16);
- :host > span > .kol-button-wc button {
- color: inherit;
+ .kol-badge__smart-button {
+ .button {
+ color: inherit;
+ }
+ }
}
}
diff --git a/packages/components/src/components/badge/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/badge/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..a5a2839311
--- /dev/null
+++ b/packages/components/src/components/badge/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,91 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-badge should render with _label="**Te**xt" 1`] = `
+
+
+
+
+
+
+
+ Te
+
+ xt
+
+
+
+
+
+
+
+`;
+
+exports[`kol-badge should render with _label="Text" _color="#000000" 1`] = `
+
+
+
+
+
+
+ Text
+
+
+
+
+
+
+
+`;
+
+exports[`kol-badge should render with _label="Text" _icons="codicon codicon-home" _color="#000000" 1`] = `
+
+
+
+
+
+
+
+ Text
+
+
+
+
+
+
+
+`;
+
+exports[`kol-badge should render with _label="Text" _icons="codicon codicon-home" 1`] = `
+
+
+
+
+
+
+
+ Text
+
+
+
+
+
+
+
+`;
+
+exports[`kol-badge should render with _label="Text" 1`] = `
+
+
+
+
+
+
+ Text
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/badge/test/html.mock.ts b/packages/components/src/components/badge/test/html.mock.ts
deleted file mode 100644
index 681615f78d..0000000000
--- a/packages/components/src/components/badge/test/html.mock.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import { handleColorChange } from '@public-ui/schema';
-
-import type { BadgeProps, BadgeStates } from '@public-ui/schema';
-import type { SpanOptions } from '../../span/test/html.mock';
-import { KolSpanWcTag } from '../../../core/component-names';
-
-export const getBadgeHtml = (props: BadgeProps, options?: SpanOptions): string => {
- const state = mixMembers(
- {
- _color: {
- backgroundColor: '#000',
- foregroundColor: '#fff',
- },
- },
- props,
- );
-
- state._color = handleColorChange(props._color || '#000');
-
- return `
-
-
- <${KolSpanWcTag} _allowMarkdown ${props._icons ? `_icons="${props._icons as string}"` : ''} ${props._label ? `_label="${props._label}"` : ''}>${KolSpanWcTag} >
-
-
- `;
-};
diff --git a/packages/components/src/components/badge/test/snapshot.spec.tsx b/packages/components/src/components/badge/test/snapshot.spec.tsx
index 1ad46a466a..1a70646c1b 100644
--- a/packages/components/src/components/badge/test/snapshot.spec.tsx
+++ b/packages/components/src/components/badge/test/snapshot.spec.tsx
@@ -1,30 +1,17 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolBadgeTag } from '../../../core/component-names';
+import type { BadgeProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolBadge } from '../shadow';
-import { getBadgeHtml } from './html.mock';
-
-import type { BadgeProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
-import { KolBadge } from '../component';
-
-executeTests(
- 'Badge',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolBadge],
- template: () => ,
- });
- return page;
- },
- {
- _color: ['#000000'],
- _icons: ['codicon codicon-home'],
- _label: ['Text', '**Te**xt'],
- },
- (props) => getBadgeHtml(props),
- {
- execMode: 'default', // ready
- },
+executeSnapshotTests(
+ KolBadgeTag,
+ [KolBadge],
+ [
+ { _label: 'Text' },
+ { _label: '**Te**xt' },
+ { _label: 'Text', _color: '#000000' },
+ { _label: 'Text', _icons: 'codicon codicon-home' },
+ { _label: 'Text', _icons: 'codicon codicon-home', _color: '#000000' },
+ ],
);
diff --git a/packages/components/src/components/breadcrumb/component.tsx b/packages/components/src/components/breadcrumb/component.tsx
deleted file mode 100644
index a1680c5eed..0000000000
--- a/packages/components/src/components/breadcrumb/component.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import type { BreadcrumbAPI, BreadcrumbLinkProps, BreadcrumbStates, LabelPropType, LinkProps, Stringified } from '@public-ui/schema';
-import { a11yHintLabelingLandmarks, validateLabel } from '@public-ui/schema';
-import { Component, Fragment, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import { addNavLabel, removeNavLabel } from '../../utils/unique-nav-labels';
-import { watchNavLinks } from '../nav/validation';
-
-import type { JSX } from '@stencil/core';
-import { KolIconTag, KolLinkTag } from '../../core/component-names';
-
-@Component({
- tag: 'kol-breadcrumb',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolBreadcrumb implements BreadcrumbAPI {
- private readonly renderLink = (link: BreadcrumbLinkProps, index: number): JSX.Element => {
- const lastIndex = this.state._links.length - 1;
- return (
-
- {index !== 0 && }
- {index === lastIndex ? (
-
- {link._hideLabel ? (
-
- ) : (
- <>{link._label}>
- )}
-
- ) : (
-
- )}
-
- );
- };
-
- public render(): JSX.Element {
- return (
-
-
-
- {this.state._links.length === 0 && (
-
- …
-
- )}
- {this.state._links.map(this.renderLink)}
-
-
-
- );
- }
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- /**
- * Defines the list of links combined with their labels to render.
- */
- @Prop() public _links!: Stringified;
-
- @State() public state: BreadcrumbStates = {
- _label: '', // ⚠ required
- _links: [],
- };
-
- @Watch('_label')
- public validateLabel(value?: LabelPropType, _oldValue?: LabelPropType, initial = false): void {
- if (!initial) {
- removeNavLabel(this.state._label); // remove the current
- }
- validateLabel(this, value, {
- required: true,
- });
- a11yHintLabelingLandmarks(value);
- addNavLabel(this.state._label); // add the state instead of prop, because the prop could be invalid and not set as new label
- }
-
- @Watch('_links')
- public validateLinks(value?: Stringified): void {
- watchNavLinks('KolBreadcrumb', this, value);
- }
-
- public componentWillLoad(): void {
- this.validateLabel(this._label, undefined, true);
- this.validateLinks(this._links);
- }
-
- public disconnectedCallback(): void {
- removeNavLabel(this.state._label);
- }
-}
diff --git a/packages/components/src/components/breadcrumb/readme.md b/packages/components/src/components/breadcrumb/readme.md
deleted file mode 100644
index 33699372bb..0000000000
--- a/packages/components/src/components/breadcrumb/readme.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# Breadcrumb
-
-Mit Hilfe der **Breadcrumb**-Komponente kann der Pfad zur aktuellen Position einer Webseite in einer hierarchischen Struktur dargestellt werden.
-
-## Funktionsweise
-
-Die **Breadcrumb**-Komponente zeigt die aktuelle Position einer Webseite in einer horizontalen Navigationsstruktur an. Das jeweils letzte Element rechts stellt die aktuelle Seite selbst dar.
-Diese ist nicht mit einem link versehen. Alle Elemente links der aktuellen Seite sind mit einem Link auf die verknüpfte Seite versehen.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
-```
-
-### Beispiel
-
-
-
-## Verwendung
-
-### Definition der Links
-
-Das Attribut **\_links** erwartet die Übergabe eines JSON-Objekts, aus dem sich der Aufbau der anzuzeigenden Breadcrumb-Pfade ergibt. Das JSON-Objekt übergibt beliebig viele Elemente, die jeweils eine Anzahl an Eigenschaften und Werten bereitstellen.
-
-Jede Eigenschaft und der zugehörige Wert müssen in doppelten Anführungszeichen gesetzt werden.
-
-Einzelne Elemente werden in geschweiften Klammern und durch **Komma** separiert geschrieben.
-
-Das gesamte JSON-Objekt muss in eckigen Klammern an das Attribut **`_links`** übergeben werden.
-
-Folgende Eigenschaften stehen zur Verfügung:
-
-- **`_href`** übergibt den Link, der für dieses Element verwendet werden soll.
-- **`_icon`** (optional) übergibt den Namen des Icon, wenn zusätzlich zum Text des Elements noch ein Icon angezeigt werden soll. Es stehen die zur Verfügung
-- **`_hide-label`** (optional). Wenn der Wert auf **true** gesetzt wird, erscheint im Link ausschließlich das Icon, ohne weiteren Text. Die Eigenschaft `_icon` muss gesetzt werden.
-- **`_label`** übergibt den Text, der für dieses Element angezeigt werden soll.
-
-Beispiel für ein JSON-Objekt, das an das Attribut **`_links`** übergeben wird:
-
-```JSON
-[
- { '_label': 'Startseite', '_href': '#/', '_icons': 'codicon codicon-home', '_hide-label': true },
- { '_label': '1. Unterseite', '_href': '/unterseite_eins' },
- { '_label': '2. Unterseite', '_href': '/unterseite_zwei' }
-]
-```
-
-
-
-### Best practices
-
-- Die **Breadcrumb**-Komponente ist ein wichtiges Element für eine effektive Suchmaschinenoptimierung Ihrer Webseite.
-- Auch für Benutzer:innen der Webseite bietet eine Breadcrumb-Navigation zusätzliche Übersicht.
-- Positionieren Sie die Breadcrumb möglichst weit oben auf Ihren Inhaltsseiten, um zu gewährleisten, dass Suchmaschinen diese als zusätzliche Informationsquelle zur Struktur Ihrer Webseite nutzen können.
-- Positionieren Sie die Breadcrumb-Komponente auf jeder Inhaltsseite Ihre Webseite. Sie gewährleisten so, dass sich Besucher:innen jederzeit zurecht finden und die aktuelle Position erkennen können.
-- Vermeiden Sie, die Breadcrumb-Navigation auf der Startseite zu positionieren.
-- Verwenden Sie eine Breadcrumb-Navigation nur dann, wenn sie für Benutzer:innen einen wirklichen Mehrwert bieten.
-- Auf mobilen Varianten einer Webseite ist eine Breadcrumb-Navigation möglicherweise nicht sinnvoll.
-
-### Anwendungsfälle
-
-Eine Breadcrumb-Navigation ist auf einer großen Mehrzahl der aktuellen Webseiten zu finden. Somit beschreibt der klassische Anwendungsfall den generellen Einbau dieser Komponente.
-
-## Barrierefreiheit
-
-Achten Sie im Sinne der optimalen Barrierefreiheit darauf, das Attribut `_label` korrekt auszuzeichnen. Beachten Sie diesen Hinweis insbesondere dann, wenn Sie die Option `_hide-label` verwenden und so auf einen beschreibenden Text im Link verzichten würden.
-
-Beachten Sie, dass auch das letzte Element in der Breadcrumb-Komponente per Tab-Taste angesprungen werden kann, obwohl dort kein Link hinterlegt ist. Hierdurch kann auch dieses Element von Screenreader erreicht und vorgelesen werden.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------- | ------------------------------------------------------------ |
-| `Tab` | Springt die einzelnen Elemente der Breadcrumb-Navigation an. |
-| `Enter` | Öffnet den Link des aktuellen Elements. |
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------- | ----------- |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_links` _(required)_ | `_links` | Defines the list of links combined with their labels to render. | `BreadcrumbLinkProps[] \| string` | `undefined` |
-
----
diff --git a/packages/components/src/components/breadcrumb/shadow.tsx b/packages/components/src/components/breadcrumb/shadow.tsx
new file mode 100644
index 0000000000..891d5db58a
--- /dev/null
+++ b/packages/components/src/components/breadcrumb/shadow.tsx
@@ -0,0 +1,98 @@
+import type { BreadcrumbAPI, BreadcrumbLinkProps, BreadcrumbStates, LabelPropType, LinkProps, Stringified } from '../../schema';
+import { a11yHintLabelingLandmarks, validateLabel } from '../../schema';
+import { Component, Fragment, h, Prop, State, Watch } from '@stencil/core';
+
+import { addNavLabel, removeNavLabel } from '../../utils/unique-nav-labels';
+import { watchNavLinks } from '../nav/validation';
+
+import type { JSX } from '@stencil/core';
+import { KolIconTag, KolLinkTag } from '../../core/component-names';
+
+@Component({
+ tag: 'kol-breadcrumb',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolBreadcrumb implements BreadcrumbAPI {
+ private readonly renderLink = (link: BreadcrumbLinkProps, index: number): JSX.Element => {
+ const lastIndex = this.state._links.length - 1;
+ return (
+
+ {index !== 0 && }
+ {index === lastIndex ? (
+
+ {link._hideLabel ? (
+
+ ) : (
+ <>{link._label}>
+ )}
+
+ ) : (
+
+ )}
+
+ );
+ };
+
+ public render(): JSX.Element {
+ return (
+
+
+ {this.state._links.length === 0 && (
+
+ …
+
+ )}
+ {this.state._links.map(this.renderLink)}
+
+
+ );
+ }
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ /**
+ * Defines the list of links combined with their labels to render.
+ */
+ @Prop() public _links!: Stringified;
+
+ @State() public state: BreadcrumbStates = {
+ _label: '', // ⚠ required
+ _links: [],
+ };
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType, _oldValue?: LabelPropType, initial = false): void {
+ if (!initial) {
+ removeNavLabel(this.state._label); // remove the current
+ }
+ validateLabel(this, value, {
+ required: true,
+ });
+ a11yHintLabelingLandmarks(value);
+ addNavLabel(this.state._label); // add the state instead of prop, because the prop could be invalid and not set as new label
+ }
+
+ @Watch('_links')
+ public validateLinks(value?: Stringified): void {
+ watchNavLinks('KolBreadcrumb', this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateLabel(this._label, undefined, true);
+ this.validateLinks(this._links);
+ }
+
+ public disconnectedCallback(): void {
+ removeNavLabel(this.state._label);
+ }
+}
diff --git a/packages/components/src/components/breadcrumb/style.scss b/packages/components/src/components/breadcrumb/style.scss
index 1f84adafdf..d4f4d3fd2a 100644
--- a/packages/components/src/components/breadcrumb/style.scss
+++ b/packages/components/src/components/breadcrumb/style.scss
@@ -1,24 +1,31 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
@layer kol-component {
- li,
- ul {
- margin: 0;
- padding: 0;
- list-style: none;
- display: flex;
- gap: 0.5em;
- flex-wrap: wrap;
- place-items: center;
- }
+ .kol-breadcrumb {
+ font-size: rem(16);
- .kol-icon::part(separator) {
- font-weight: 900;
- font-size: 0.7em;
- }
+ &__list,
+ &__list-element {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ display: flex;
+ gap: 0.5em;
+ flex-wrap: wrap;
+ place-items: center;
+ }
+
+ &__icon {
+ &::part(separator) {
+ font-weight: 900;
+ font-size: 0.7em;
+ }
- .kol-icon::part(separator):before {
- content: '\f054';
- font-family: 'Font Awesome 6 Free';
+ &::part(separator):before {
+ content: '\f054';
+ font-family: 'Font Awesome 6 Free';
+ }
+ }
}
}
diff --git a/packages/components/src/components/breadcrumb/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/breadcrumb/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..2e6fc9510e
--- /dev/null
+++ b/packages/components/src/components/breadcrumb/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,17 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-breadcrumb should render with _label="Aria-Label" _links=[{"_href":"https://example.com","_label":"Label"}] 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/breadcrumb/test/html.mock.ts b/packages/components/src/components/breadcrumb/test/html.mock.ts
deleted file mode 100644
index bd9cb0dd80..0000000000
--- a/packages/components/src/components/breadcrumb/test/html.mock.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import { KolIconTag, KolLinkTag } from '../../../core/component-names';
-
-import type { AnyIconFontClass, BreadcrumbLinkProps, BreadcrumbProps, LabelPropType } from '@public-ui/schema';
-
-export const getBreadcrumbHtml = (props: BreadcrumbProps): string => {
- const state = mixMembers(
- {
- _label: '', // ⚠ required
- _links: [],
- },
- props,
- );
-
- const lastIndex = state._links.length - 1;
- let list = '';
- (state._links as BreadcrumbLinkProps[]).forEach((link, index) => {
- list += `
-
- ${index !== 0 ? `<${KolIconTag} _label="" _icons="codicon codicon-chevron-right" /> ${KolIconTag}>` : ''}
- ${
- lastIndex === index
- ? `${link._hideLabel ? `<${KolIconTag} _label="${link._label}" _icons="${link._icons as AnyIconFontClass}" />${KolIconTag}>` : link._label} `
- : `<${KolLinkTag} {...link}>${KolLinkTag}>`
- }
-
- `;
- });
-
- return `
-
-
-
-
- ${state._links.length === 0 ? ` <${KolIconTag} _label="" _icons="codicon codicon-home" /> ${KolIconTag}>… ` : ''}
- ${list}
-
-
-
- `;
-};
diff --git a/packages/components/src/components/breadcrumb/test/snapshot.spec.tsx b/packages/components/src/components/breadcrumb/test/snapshot.spec.tsx
index cf6d1f80cb..4527076342 100644
--- a/packages/components/src/components/breadcrumb/test/snapshot.spec.tsx
+++ b/packages/components/src/components/breadcrumb/test/snapshot.spec.tsx
@@ -1,29 +1,11 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolBreadcrumbTag } from '../../../core/component-names';
+import type { BreadcrumbProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolBreadcrumb } from '../shadow';
-import { getBreadcrumbHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { BreadcrumbProps } from '@public-ui/schema';
-import { KolBreadcrumb } from '../component';
-
-executeTests(
- 'Breadcrumb',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolBreadcrumb],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Aria-Label'],
- _links: [[], [{ _label: 'Label' }]],
- },
- getBreadcrumbHtml,
- {
- execMode: 'default', // ready
- },
+executeSnapshotTests(
+ KolBreadcrumbTag,
+ [KolBreadcrumb],
+ [{ _label: 'Aria-Label', _links: [{ _href: 'https://example.com', _label: 'Label' }] }],
);
diff --git a/packages/components/src/components/button-group/component.tsx b/packages/components/src/components/button-group/component.tsx
deleted file mode 100644
index 46685ad26e..0000000000
--- a/packages/components/src/components/button-group/component.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { ButtonGroupAPI, ButtonGroupStates } from '@public-ui/schema';
-import type { JSX } from '@stencil/core';
-import { Component, h, Host, State } from '@stencil/core';
-
-@Component({
- tag: 'kol-button-group-wc',
- shadow: false,
-})
-/**
- * @deprecated This component has been deprecated as it does not contribute significantly to accessibility.
- */
-export class KolButtonGroupWc implements ButtonGroupAPI {
- public render(): JSX.Element {
- return (
-
-
-
- );
- }
-
- @State() public state: ButtonGroupStates = {};
-}
diff --git a/packages/components/src/components/button-group/readme.md b/packages/components/src/components/button-group/readme.md
deleted file mode 100644
index 413afc0057..0000000000
--- a/packages/components/src/components/button-group/readme.md
+++ /dev/null
@@ -1,93 +0,0 @@
-# ButtonGroup
-
-**Buttons** dienen dazu, Nutzer:innen Auswahlmöglichkeiten für Aktionen anzuzeigen und diese in einer klaren Hierarchie anzuordnen. Sie helfen den Nutzer:innen, die wichtigsten Aktionen einer Seite oder innerhalb eines Applikation zu finden und ermöglichen es ihm, diese Aktionen auszuführen.
-
-Die **ButtonGroup**-Komponente fasst mehrere Buttons zu einer optischen und funktionalen Einheit zusammen.
-
-## Konstruktion
-
-### Hinweis zur Version 3
-
-Die **ButtonGroup** Komponente wurde für die Version 3 wurde als veraltet markiert (`deprecated`), da sie keinen nennenswerten Beitrag zur Verbesserung der Barrierefreiheit beiträgt.
-
-Die Komponente **ButtonGroup** besteht aus einem Hauptelement ` `. In ihm werden beliebig viele **Button**-Komponenten zu einer Gruppe zusammengefasst. Die einzelnen **Buttons** entsprechen in ihrer Konstruktion der Beschreibung
-zur **Button**-Komponente.
-
-### Code
-
-```html
-
-
-
-
-
-
-
-
-```
-
-### Beispiel
-
-
-
-
-
-
-
-
-
-
-## Verwendung
-
-### Einfache ButtonGroup
-
-Im einfachsten Fall besteht die **ButtonGroup**-Komponente aus einer Liste beschrifteter Schaltflächen. Für die Beschriftung der Buttons wird lediglich das Attribut **`_label="Ihre Beschriftung"`** verwendet.
-
-### ButtonGroup mit Text, Icon und Text mit Icon
-
-Über das Attribut **`_icons="xxx"`** wird festgelegt, ob und welches Icon verwendet werden soll.
-
-Eine Übersicht über die zur Verfügung stehenden Icons in KoliBri finden Sie .
-
-Über das Attribut **`_hide-label`** legen Sie fest, ob nur das Icon angezeigt werden soll. Der Inhalt des Attributs **`_label`** wird nicht mehr angezeigt.
-
-### Ausgabe verschiedener Styles für Buttons in der ButtonGroup
-
-Für die Standardausgabe eines Buttons stehen die Werte **primary**, **secondary**, **normal**, **danger** und **ghost** zur Verfügung. Hierüber wird die farbliche Gestaltung des Buttons festgelegt.
-
-### Optische Ausrichtung
-
-Über das Attribut **`_nestled`** kann eine optische Ausrichtung der ButtonGroup bestimmt werden. An der angegebenen Position werden die abgerundeten Ecken entfernt, so dass der Eindruck einer Button-Leiste entsteht. Möglich sind die Werte `bottom`, `top`, `left`und `right`.
-
-### Best practices
-
-- Verwenden Sie eine primäre Schaltfläche für die nächstbeste Aktion. Verbleibende Calls-to-Actions sollten als sekundäre Schaltfläche dargestellt werden.
-- Verwenden Sie Schaltflächen an einheitlichen Stellen in der Benutzeroberfläche, um die Benutzererfahrung zu verbessern.
-- Verwenden Sie nur eine primäre Schaltfläche je Viewport. Auf der gesamten Seite kann ein Button-Style beliebig oft auftreten.
-- Die Beschriftung des Button muss die Aktion beschreiben, die die Schaltfläche ausführt. Sie sollte ein Verb enthalten (z.B. Speichern). Verwenden Sie prägnante, spezifische, selbsterklärende Beschriftungen.
-- Schaltflächenbeschriftungen sollten immer dann auch ein Nomen enthalten, wenn es Raum für Interpretationen darüber gibt, wofür das Verb zuständig ist. Verwenden Sie keine generischen Bezeichnungen wie "OK", insbesondere nicht im Fehlerfall. Fehler sind nie "OK".
-- Wenn Sie mehrere Buttons kombinieren oder anordnen möchten, verwenden Sie die **ButtonGroup**-Komponente.
-- Verwenden Sie nicht mehrere Buttons im Style "primär" in einer **ButtonGroup**.
-- Verwenden Sie Buttons nicht als Link oder als Navigationselement.
-
-## Barrierefreiheit
-
-Bei Verwendung der **ButtonGroup**-Komponente sind keine besonderen Maßnahmen in Bezug auf die barrierefreiheit zu berücksichtigen. Die innerhalb der ButtonGroup enthaltenen **Button**-Komponenten besitzen jedoch einige wichtige Aspekte in diesem Zusammenhang:
-
-- In der Button-Komponente werden die optionalen **Icons** links ausgerichtet, um Nutzer\*innen mit eingeschränktem Sichtfeld eine bessere Bedienbarkeit zu ermöglichen.
-- Die Farben der **Variant-Typen** `primary`, `secondary`, `normal`, `danger` und `ghost` wurden in Hinblick auf bestmöglichen Kontrast gewählt. Die Schriftfarbe ist per default immer weiß.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------- | ------------------------------------------------------------------------------ |
-| `Tab` | Springt den einzelnen Button der ButtonGroup an und fokussiert ihn. |
-| `Enter` | Öffnet den Link des fokussierten Button oder führt dessen onClick-Methode aus. |
-
-## Links und Referenzen
-
--
-
-
-
----
diff --git a/packages/components/src/components/button-group/shadow.tsx b/packages/components/src/components/button-group/shadow.tsx
deleted file mode 100644
index ef1bb48f65..0000000000
--- a/packages/components/src/components/button-group/shadow.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { ButtonGroupProps } from '@public-ui/schema';
-import type { JSX } from '@stencil/core';
-import { Component, h, Host } from '@stencil/core';
-import { KolButtonGroupWcTag } from '../../core/component-names';
-
-@Component({
- tag: 'kol-button-group',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolButtonGroup implements ButtonGroupProps {
- public render(): JSX.Element {
- return (
-
-
-
-
-
- );
- }
-}
diff --git a/packages/components/src/components/button-group/style.scss b/packages/components/src/components/button-group/style.scss
deleted file mode 100644
index 52c497bc83..0000000000
--- a/packages/components/src/components/button-group/style.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-@import '../style';
-
-@layer kol-component {
- :host > .kol-button-group-wc {
- display: flex;
- flex-wrap: wrap;
- }
-}
diff --git a/packages/components/src/components/button-group/test/html.mock.ts b/packages/components/src/components/button-group/test/html.mock.ts
deleted file mode 100644
index 40e0671f5c..0000000000
--- a/packages/components/src/components/button-group/test/html.mock.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export const getButtonGroupHtml = (): string => {
- return `
-
-
-
-
-
- `;
-};
diff --git a/packages/components/src/components/button-group/test/snapshot.spec.tsx b/packages/components/src/components/button-group/test/snapshot.spec.tsx
deleted file mode 100644
index c344175178..0000000000
--- a/packages/components/src/components/button-group/test/snapshot.spec.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { executeTests } from 'stencil-awesome-test';
-
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getButtonGroupHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { ButtonGroupProps } from '@public-ui/schema';
-import { KolButtonGroup } from '../shadow';
-import { KolButtonGroupWc } from '../component';
-
-executeTests(
- 'ButtonGroup',
- async (props): Promise => {
- return await newSpecPage({
- components: [KolButtonGroup, KolButtonGroupWc],
- template: () => ,
- });
- },
- {},
- getButtonGroupHtml,
- {
- execMode: 'default',
- },
-);
diff --git a/packages/components/src/components/button-link/button-link.e2e.ts b/packages/components/src/components/button-link/button-link.e2e.ts
new file mode 100644
index 0000000000..bff66a6705
--- /dev/null
+++ b/packages/components/src/components/button-link/button-link.e2e.ts
@@ -0,0 +1,50 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-button-link', () => {
+ test('it renders label', async ({ page }) => {
+ await page.setContent(' ');
+ const kolButton = page.locator('kol-button-link');
+ await expect(kolButton).toContainText('Test ButtonLink Element');
+ });
+
+ test.describe('Callbacks', () => {
+ ['onClick', 'onMouseDown'].forEach((callbackName) => {
+ test(`should call ${callbackName} callback when internal button emits`, async ({ page }) => {
+ await page.setContent(' ');
+ const kolButton = page.locator('kol-button-link');
+
+ const callbackPromise = kolButton.evaluate((element: HTMLKolButtonElement, callbackName) => {
+ return new Promise((resolve) => {
+ element._on = {
+ [callbackName]: () => {
+ resolve();
+ },
+ };
+ });
+ }, callbackName);
+ await page.waitForChanges();
+
+ await page.locator('button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+ });
+
+ test.describe('DOM events', () => {
+ [KolEvent.click, KolEvent.mousedown].forEach((event) => {
+ test(`should emit ${event} when internal button emits ${event}`, async ({ page }) => {
+ await page.setContent(' ');
+ const eventPromise = page.locator('kol-button-link').evaluate(async (element, event) => {
+ return new Promise((resolve) => {
+ element.addEventListener(event, resolve);
+ });
+ }, event);
+ await page.waitForChanges();
+ await page.locator('button').dispatchEvent(event);
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/packages/components/src/components/button-link/component.tsx b/packages/components/src/components/button-link/component.tsx
deleted file mode 100644
index 9b9094f170..0000000000
--- a/packages/components/src/components/button-link/component.tsx
+++ /dev/null
@@ -1,160 +0,0 @@
-import type {
- AccessKeyPropType,
- AlternativeButtonLinkRolePropType,
- ButtonCallbacksPropType,
- ButtonLinkProps,
- ButtonTypePropType,
- IconsPropType,
- IdPropType,
- LabelWithExpertSlotPropType,
- NamePropType,
- StencilUnknown,
- Stringified,
- SyncValueBySelectorPropType,
- TooltipAlignPropType,
-} from '@public-ui/schema';
-import { propagateFocus } from '@public-ui/schema';
-import { Component, Element, h, Host, Method, Prop } from '@stencil/core';
-
-import type { JSX } from '@stencil/core';
-import { KolButtonWcTag } from '../../core/component-names';
-@Component({
- tag: 'kol-button-link',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolButtonLink implements ButtonLinkProps {
- @Element() private readonly host?: HTMLKolButtonLinkElement;
-
- private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
- propagateFocus(this.host, ref);
- };
-
- @Method()
- // eslint-disable-next-line @typescript-eslint/require-await
- public async getValue(): Promise | undefined> {
- return this._value;
- }
-
- public render(): JSX.Element {
- return (
-
-
-
-
-
- );
- }
-
- /**
- * Defines the elements access key.
- */
- @Prop() public _accessKey?: AccessKeyPropType;
-
- /**
- * Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
- */
- @Prop() public _ariaControls?: string;
-
- /**
- * Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
- * @TODO: Change type back to `AriaExpandedPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _ariaExpanded?: boolean;
-
- /**
- * Defines whether the interactive element of the component is selected (e.g. role=tab). (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected)
- * @TODO: Change type back to `AriaSelectedPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _ariaSelected?: boolean;
-
- /**
- * Makes the element not focusable and ignore all events.
- * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Hides the caption by default and displays the caption text with a tooltip when the
- * interactive element is focused or the mouse is over it.
- * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hideLabel?: boolean = false;
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: IconsPropType;
-
- /**
- * Defines the internal ID of the primary component element.
- */
- @Prop() public _id?: IdPropType;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines the technical name of an input field.
- */
- @Prop() public _name?: NamePropType;
-
- /**
- * Gibt die EventCallback-Funktionen für die Button-Events an.
- */
- @Prop() public _on?: ButtonCallbacksPropType;
-
- /**
- * Defines the role of the components primary element.
- */
- @Prop() public _role?: AlternativeButtonLinkRolePropType;
-
- /**
- * Selector for synchronizing the value with another input element.
- * @internal
- */
- @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
-
- /**
- * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
- */
- @Prop() public _tabIndex?: number;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Defines either the type of the component or of the components interactive element.
- */
- @Prop() public _type?: ButtonTypePropType = 'button';
-
- /**
- * Defines the value that the button emits on click.
- */
- @Prop() public _value?: Stringified;
-}
diff --git a/packages/components/src/components/button-link/readme.md b/packages/components/src/components/button-link/readme.md
deleted file mode 100644
index ea090aa83d..0000000000
--- a/packages/components/src/components/button-link/readme.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# ButtonLink
-
-Der ButtonLink ist semantisch ein Button und hat das Design eines Links. Hierzu werden alle relevanten Properties der Button-Komponente übernommen und um die Design-bestimmenden Properties des Links erweitert.
-
-Einen Button kann man deaktivieren und daher gibt es bei einem ButtonLink das Property `_disabled`. Wie das optisch ausgestaltet wird, entscheidet die UX-Designer:in.
-
-Statt, wie bei einem Link, `_href` zu verwenden, wird bei einem ButtonLink das Property über den `Click-Callback` gesteuert. Hierzu wird das `_on`-Property verwendet.
-
-Bei einem Link gibt es das Property `target`, welches ggf. den Link in einem neuen Fenster/Tab öffnet. Das Verhalten ist aktuell noch nicht umgesetzt.
-
-Da der Link, nicht wie der Button, in mehrere Varianten (`primary` oder `secondary` usw.) angeboten wird, stehen die Properties `_customClass` und `_variant` nicht zur Verfügung.
-
-## Konstruktion
-
-### Code
-
-```html
-
-```
-
-### Beispiel
-
-
-
-
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
-| `_accessKey` | `_access-key` | Defines the elements access key. | `string \| undefined` | `undefined` |
-| `_ariaControls` | `_aria-controls` | Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls) | `string \| undefined` | `undefined` |
-| `_ariaExpanded` | `_aria-expanded` | Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) | `boolean \| undefined` | `undefined` |
-| `_ariaSelected` | `_aria-selected` | Defines whether the interactive element of the component is selected (e.g. role=tab). (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected) | `boolean \| undefined` | `undefined` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `KoliBriHorizontalIcons & KoliBriVerticalIcons \| string \| undefined` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für die Button-Events an. | `undefined \| { onClick?: EventValueOrEventCallback \| undefined; onMouseDown?: EventCallback \| undefined; }` | `undefined` |
-| `_role` | `_role` | Defines the role of the components primary element. | `"button" \| "link" \| "tab" \| undefined` | `undefined` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_type` | `_type` | Defines either the type of the component or of the components interactive element. | `"button" \| "reset" \| "submit" \| undefined` | `'button'` |
-| `_value` | `_value` | Defines the value that the button emits on click. | `boolean \| null \| number \| object \| string \| undefined` | `undefined` |
-
-## Methods
-
-### `getValue() => Promise | undefined>`
-
-#### Returns
-
-Type: `Promise>`
-
----
diff --git a/packages/components/src/components/button-link/shadow.tsx b/packages/components/src/components/button-link/shadow.tsx
new file mode 100644
index 0000000000..99110012e2
--- /dev/null
+++ b/packages/components/src/components/button-link/shadow.tsx
@@ -0,0 +1,179 @@
+import type {
+ AccessKeyPropType,
+ AlternativeButtonLinkRolePropType,
+ AriaDescriptionPropType,
+ ButtonCallbacksPropType,
+ ButtonLinkProps,
+ ButtonTypePropType,
+ FocusableElement,
+ IconsPropType,
+ IdPropType,
+ LabelWithExpertSlotPropType,
+ NamePropType,
+ ShortKeyPropType,
+ StencilUnknown,
+ Stringified,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+} from '../../schema';
+import type { JSX } from '@stencil/core';
+import { Component, h, Method, Prop } from '@stencil/core';
+import { KolButtonWcTag } from '../../core/component-names';
+
+@Component({
+ tag: 'kol-button-link',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: {
+ delegatesFocus: true,
+ },
+})
+export class KolButtonLink implements ButtonLinkProps, FocusableElement {
+ private buttonWcRef?: HTMLKolButtonWcElement;
+
+ private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
+ this.buttonWcRef = ref;
+ };
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async getValue(): Promise | undefined> {
+ return this._value;
+ }
+
+ @Method()
+ public async kolFocus() {
+ await this.buttonWcRef?.kolFocus();
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+ );
+ }
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: AccessKeyPropType;
+
+ /**
+ * Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
+ */
+ @Prop() public _ariaControls?: string;
+
+ /**
+ * Defines the value for the aria-description attribute.
+ */
+ @Prop() public _ariaDescription?: AriaDescriptionPropType;
+
+ /**
+ * Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
+ * @TODO: Change type back to `AriaExpandedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _ariaExpanded?: boolean;
+
+ /**
+ * Defines whether the interactive element of the component is selected (e.g. role=tab). (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected)
+ * @TODO: Change type back to `AriaSelectedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _ariaSelected?: boolean;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: IconsPropType;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: IdPropType;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: NamePropType;
+
+ /**
+ * Gibt die EventCallback-Funktionen für die Button-Events an.
+ */
+ @Prop() public _on?: ButtonCallbacksPropType;
+
+ /**
+ * Defines the role of the components primary element.
+ */
+ @Prop() public _role?: AlternativeButtonLinkRolePropType;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Defines either the type of the component or of the components interactive element.
+ */
+ @Prop() public _type?: ButtonTypePropType = 'button';
+
+ /**
+ * Defines the value that the button emits on click.
+ */
+ @Prop() public _value?: Stringified;
+}
diff --git a/packages/components/src/components/button-link/style.scss b/packages/components/src/components/button-link/style.scss
index 72c33b7a0f..66eea306b6 100644
--- a/packages/components/src/components/button-link/style.scss
+++ b/packages/components/src/components/button-link/style.scss
@@ -1 +1,5 @@
-@import '../link';
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../@shared/kol-link-mixin';
+
+@include kol-link-styles('kol-button');
diff --git a/packages/components/src/components/button-link/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/button-link/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..1ff3a99142
--- /dev/null
+++ b/packages/components/src/components/button-link/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-button-link should render with _label="Beschreibung" 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/button-link/test/html.mock.ts b/packages/components/src/components/button-link/test/html.mock.ts
deleted file mode 100644
index 6f10a4e0f4..0000000000
--- a/packages/components/src/components/button-link/test/html.mock.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-import type { ButtonLinkProps, ButtonLinkStates } from '@public-ui/schema';
-import { KolButtonWcTag } from '../../../core/component-names';
-
-export const getButtonLinkHtml = (props: ButtonLinkProps): string => {
- const state = mixMembers(
- {
- _icons: {},
- _label: '', // ⚠ required
- _on: {},
- _type: 'button',
- _variant: 'normal',
- },
- props,
- );
-
- return `
-
- <${KolButtonWcTag}
- _role="link"
- _type="button"
- ${state._label ? `_label="${state._label}"` : ''}
- _tooltipalign="top"
- >
-
- ${KolButtonWcTag}>
-
- `;
-};
diff --git a/packages/components/src/components/button-link/test/snapshot.spec.tsx b/packages/components/src/components/button-link/test/snapshot.spec.tsx
index 761dddb784..2aee21bdcd 100644
--- a/packages/components/src/components/button-link/test/snapshot.spec.tsx
+++ b/packages/components/src/components/button-link/test/snapshot.spec.tsx
@@ -1,24 +1,7 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolButtonLinkTag } from '../../../core/component-names';
+import type { ButtonLinkProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolButtonLink } from '../shadow';
-import { getButtonLinkHtml } from './html.mock';
-
-import type { ButtonLinkProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
-import { KolButtonLink } from '../component';
-
-executeTests(
- 'ButtonLink',
- async (props): Promise => {
- return await newSpecPage({
- components: [KolButtonLink],
- template: () => ,
- });
- },
- {
- _label: [`Beschreibung`],
- },
- getButtonLinkHtml,
-);
+executeSnapshotTests(KolButtonLinkTag, [KolButtonLink], [{ _label: 'Beschreibung' }]);
diff --git a/packages/components/src/components/button.scss b/packages/components/src/components/button.scss
deleted file mode 100644
index 8c21561520..0000000000
--- a/packages/components/src/components/button.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-@import 'style';
-
-@layer kol-component {
- :host {
- display: inline-block;
- }
-
- :is(a, button) {
- display: inline-flex;
- place-items: center;
- text-align: center;
- text-decoration-line: none;
-
- &::before {
- /* Render zero-width character as first element to set the baseline correctly. */
- content: '\200B';
- }
- }
-
- /* TODO: Why we need this? */
- :is(a, button) > .kol-span-wc {
- margin: auto;
- width: 100%;
- }
-}
diff --git a/packages/components/src/components/button/button.e2e.ts b/packages/components/src/components/button/button.e2e.ts
new file mode 100644
index 0000000000..203ba89a7d
--- /dev/null
+++ b/packages/components/src/components/button/button.e2e.ts
@@ -0,0 +1,50 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-button', () => {
+ test('it renders label', async ({ page }) => {
+ await page.setContent(' ');
+ const kolButton = page.locator('kol-button');
+ await expect(kolButton).toContainText('Test Button Element');
+ });
+
+ test.describe('Callbacks', () => {
+ ['onClick', 'onMouseDown'].forEach((callbackName) => {
+ test(`should call ${callbackName} callback when internal button emits`, async ({ page }) => {
+ await page.setContent(' ');
+ const kolButton = page.locator('kol-button');
+
+ const callbackPromise = kolButton.evaluate((element: HTMLKolButtonElement, callbackName) => {
+ return new Promise((resolve) => {
+ element._on = {
+ [callbackName]: () => {
+ resolve();
+ },
+ };
+ });
+ }, callbackName);
+ await page.waitForChanges();
+
+ await page.locator('button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+ });
+
+ test.describe('DOM events', () => {
+ [KolEvent.click, KolEvent.mousedown].forEach((event) => {
+ test(`should emit ${event} when internal button emits ${event}`, async ({ page }) => {
+ await page.setContent(' ');
+ const eventPromise = page.locator('kol-button').evaluate(async (element, event) => {
+ return new Promise((resolve) => {
+ element.addEventListener(event, resolve);
+ });
+ }, event);
+ await page.waitForChanges();
+ await page.locator('button').dispatchEvent(event);
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/packages/components/src/components/button/component.tsx b/packages/components/src/components/button/component.tsx
index 4f43e70daf..67aedc72e5 100644
--- a/packages/components/src/components/button/component.tsx
+++ b/packages/components/src/components/button/component.tsx
@@ -1,6 +1,7 @@
import type {
AccessKeyPropType,
AlternativeButtonLinkRolePropType,
+ AriaDescriptionPropType,
ButtonAPI,
ButtonCallbacksPropType,
ButtonStates,
@@ -8,23 +9,25 @@ import type {
ButtonVariantPropType,
CustomClassPropType,
DisabledPropType,
+ FocusableElement,
IconsPropType,
LabelWithExpertSlotPropType,
+ ShortKeyPropType,
StencilUnknown,
Stringified,
SyncValueBySelectorPropType,
TooltipAlignPropType,
-} from '@public-ui/schema';
+} from '../../schema';
import {
mapBoolean2String,
mapStringOrBoolean2String,
- propagateFocus,
setEventTarget,
setState,
showExpertSlot,
validateAccessKey,
validateAlternativeButtonLinkRole,
validateAriaControls,
+ validateAriaDescription,
validateAriaExpanded,
validateAriaSelected,
validateButtonCallbacks,
@@ -35,17 +38,22 @@ import {
validateHideLabel,
validateIcons,
validateLabelWithExpertSlot,
+ validateShortKey,
validateTabIndex,
validateTooltipAlign,
watchString,
-} from '@public-ui/schema';
+} from '../../schema';
import type { JSX } from '@stencil/core';
-import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';
+import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core';
-import { stopPropagation, tryToDispatchKoliBriEvent } from '../../utils/events';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+import { nonce } from '../../utils/dev.utils';
import { propagateResetEventToForm, propagateSubmitEventToForm } from '../form/controller';
import { AssociatedInputController } from '../input-adapter-leanup/associated.controller';
-import { KolSpanWcTag, KolTooltipWcTag } from '../../core/component-names';
+import { KolTooltipWcTag } from '../../core/component-names';
+import { validateAccessAndShortKey } from '../../schema/validators/access-and-short-key';
+import { KolSpanFc } from '../../functional-components';
+import clsx from 'clsx';
/**
* @internal
@@ -54,80 +62,96 @@ import { KolSpanWcTag, KolTooltipWcTag } from '../../core/component-names';
tag: 'kol-button-wc',
shadow: false,
})
-export class KolButtonWc implements ButtonAPI {
+export class KolButtonWc implements ButtonAPI, FocusableElement {
@Element() private readonly host?: HTMLKolButtonWcElement;
- private ref?: HTMLButtonElement;
+ private buttonRef?: HTMLButtonElement;
+
+ private readonly internalDescriptionById = nonce();
private readonly catchRef = (ref?: HTMLButtonElement) => {
- this.ref = ref;
- propagateFocus(this.host, this.ref);
+ this.buttonRef = ref;
};
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ this.buttonRef?.focus();
+ }
+
private readonly onClick = (event: MouseEvent) => {
if (this.state._type === 'submit') {
propagateSubmitEventToForm({
form: this.host,
- ref: this.ref,
+ ref: this.buttonRef,
});
} else if (this.state._type === 'reset') {
propagateResetEventToForm({
form: this.host,
- ref: this.ref,
+ ref: this.buttonRef,
});
} else {
- // Event handling
- stopPropagation(event);
- tryToDispatchKoliBriEvent('click', this.host, this.state._value);
-
// TODO: Static form handling
this.controller.setFormAssociatedValue(this.state._value);
// Callback
if (typeof this.state._on?.onClick === 'function') {
- setEventTarget(event, this.ref);
+ setEventTarget(event, this.buttonRef);
this.state._on?.onClick(event, this.state._value);
}
}
+
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.click, this.state._value);
+ }
+ };
+
+ private readonly onMouseDown = (event: MouseEvent) => {
+ this.state?._on?.onMouseDown?.(event);
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.mousedown);
+ }
};
public render(): JSX.Element {
const hasExpertSlot = showExpertSlot(this.state._label);
+ const hasAriaDescription = Boolean(this.state._ariaDescription?.trim()?.length);
+ const badgeText = this.state._accessKey || this.state._shortKey;
return (
-
+
0,
- 'hide-label': this.state._hideLabel === true,
- }}
+ })}
disabled={this.state._disabled}
id={this.state._id}
name={this.state._name}
- {...this.state._on}
onClick={this.onClick}
+ onMouseDown={this.onMouseDown}
role={this.state._role}
tabIndex={this.state._tabIndex}
type={this.state._type}
>
-
-
+
+ {hasAriaDescription && (
+
+ {this.state._ariaDescription}
+
+ )}
);
}
@@ -147,7 +177,7 @@ export class KolButtonWc implements ButtonAPI {
private readonly controller: AssociatedInputController;
/**
- * Defines the elements access key.
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
*/
@Prop() public _accessKey?: AccessKeyPropType;
@@ -156,6 +186,11 @@ export class KolButtonWc implements ButtonAPI {
*/
@Prop() public _ariaControls?: string;
+ /**
+ * Defines the value for the aria-description attribute.
+ */
+ @Prop() public _ariaDescription?: AriaDescriptionPropType;
+
/**
* Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
*/
@@ -213,6 +248,11 @@ export class KolButtonWc implements ButtonAPI {
*/
@Prop() public _role?: AlternativeButtonLinkRolePropType;
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
/**
* Selector for synchronizing the value with another input element.
* @internal
@@ -259,6 +299,7 @@ export class KolButtonWc implements ButtonAPI {
@Watch('_accessKey')
public validateAccessKey(value?: AccessKeyPropType): void {
validateAccessKey(this, value);
+ validateAccessAndShortKey(value, this._shortKey);
}
@Watch('_ariaControls')
@@ -266,6 +307,11 @@ export class KolButtonWc implements ButtonAPI {
validateAriaControls(this, value);
}
+ @Watch('_ariaDescription')
+ public validateAriaDescription(value?: AriaDescriptionPropType): void {
+ validateAriaDescription(this, value);
+ }
+
@Watch('_ariaExpanded')
public validateAriaExpanded(value?: boolean): void {
validateAriaExpanded(this, value);
@@ -323,6 +369,12 @@ export class KolButtonWc implements ButtonAPI {
validateAlternativeButtonLinkRole(this, value);
}
+ @Watch('_shortKey')
+ public validateShortKey(value?: ShortKeyPropType): void {
+ validateShortKey(this, value);
+ validateAccessAndShortKey(this._accessKey, value);
+ }
+
@Watch('_syncValueBySelector')
public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
this.controller.validateSyncValueBySelector(value);
@@ -357,6 +409,7 @@ export class KolButtonWc implements ButtonAPI {
public componentWillLoad(): void {
this.validateAccessKey(this._accessKey);
this.validateAriaControls(this._ariaControls);
+ this.validateAriaDescription(this._ariaDescription);
this.validateAriaExpanded(this._ariaExpanded);
this.validateAriaSelected(this._ariaSelected);
this.validateCustomClass(this._customClass);
@@ -368,11 +421,13 @@ export class KolButtonWc implements ButtonAPI {
this.validateName(this._name);
this.validateOn(this._on);
this.validateRole(this._role);
+ this.validateShortKey(this._shortKey);
this.validateSyncValueBySelector(this._syncValueBySelector);
this.validateTabIndex(this._tabIndex);
this.validateTooltipAlign(this._tooltipAlign);
this.validateType(this._type);
this.validateValue(this._value);
this.validateVariant(this._variant);
+ validateAccessAndShortKey(this._accessKey, this._shortKey);
}
}
diff --git a/packages/components/src/components/button/readme.md b/packages/components/src/components/button/readme.md
deleted file mode 100644
index f393ec8323..0000000000
--- a/packages/components/src/components/button/readme.md
+++ /dev/null
@@ -1,129 +0,0 @@
-# Button
-
-**Buttons** dienen dazu, Benutzer:innen Auswahlmöglichkeiten für Aktionen anzuzeigen und diese in einer klaren Hierarchie anzuordnen. Sie helfen Nutzer:innen, die wichtigsten Aktionen einer Seite oder innerhalb eines Viewports zu finden und ermöglichen es ihnen, diese Aktionen auszuführen. Die Beschriftung des Buttons wird verwendet, um Nutzer:innen klar anzuzeigen, welche Aktion ausgelöst wird. Buttons ermöglichen es Nutzer:innen, eine Änderung zu bestätigen, Schritte in einer Aufgabe abzuschließen oder Entscheidungen zu treffen.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
-
-
-```
-
-### Beispiel
-
-Default
-
-
-
-
-
-
-
-
-
-Disabled
-
-
-
-
-
-
-
-
-
-## Verwendung
-
-### Beschriftung
-
-Für die eindeutige Beschriftung des Buttons nutzen Sie das Attribut **`_label`**.
-`_label="Schaltflächenbeschriftung"`
-
-### Icons
-
-Icons (**`_icons`**) kann entweder als String angegeben werden, oder als Objekt.
-Als String übergeben Sie die Iconklasse (z.B.: `_icons="codicon codicon-home`), das Icon wird links vom Text angezeigt.
-Das Objekt ist vom Typ `KoliBriAllIcon`, kann also einen oder mehrere der Schlüssel `top`, `right`, `bottom` und `left` besitzen. Diese sind dann entweder String (siehe oben) oder ein Objekt vom Typ `KoliBriCustomIcon`, welches aus `icon` (String, siehe oben) und `style` (optional, Styleobjekt) besteht.
-
-
-
-### Schaltfläche ohne Text
-
-Mittels **`_hide-label`** wird die Schaltfläche nur das icon anzeigen ( )
-
-Beachten Sie, dass das Attribut **`_label`** auch dann gesetzt werden muss, wenn nur ein Icon angezeigt werden soll, dieses wird von Screenreadern vorgelesen und in den Tooltip gesetzt.
-
-### Darstellung angeben
-
-Zur Steuerung der Darstellung verwenden Sie das Attribut **`_variant`**. Der Standardwert ist `primary`, alternativ kann auch `primary`, `secondary`, `normal`, `danger`, `ghost`, oder `custom` gesetzt werden.
-
-Über die Verwendung des Wertes `custom` kann eine eigene Darstellung gewählt werden. Verpflichtend ist in diesem Fall das Setzen des Attribut **`_custom-class`**, damit die Schaltfläche im Shadow-Dom mittels CSS selektiert werden kann.
-
-### Best practices
-
-- Verwenden Sie eine primäre Schaltfläche für die nächstbeste Aktion. Verbleibende Calls-to-Action sollten als sekundäre Schaltfläche dargestellt werden.
-- Verwenden Sie Schaltflächen an einheitlichen Stellen in der Benutzeroberfläche, um die Benutzererfahrung zu verbessern.
-- Verwenden Sie nur eine primäre Schaltfläche je Viewport. Auf der gesamten Seite kann ein Button-Style beliebig oft auftreten.
-- Die Beschriftung des Button muss die Aktion beschreiben, die die Schaltfläche ausführt. Sie sollte ein Verb enthalten (z.B. Speichern). Verwenden Sie prägnante, spezifische, selbsterklärende Beschriftungen.
-- Schaltflächenbeschriftungen sollten immer dann auch ein Nomen enthalten, wenn es Raum für Interpretationen darüber gibt, wofür das Verb zuständig ist. Verwenden Sie keine generischen Bezeichnungen wie "OK", insbesondere nicht im Fehlerfall. Fehler sind nie "OK".
-- Verwenden Sie nicht mehrere Buttons im Style "primär" innerhalb einer Gruppierung.
-- Verwenden Sie Buttons nicht als Link oder als Navigationselement.
-
-## Barrierefreiheit
-
-Für Menschen mit einem eingeschränkten Sichtfeld ist die Positionierung des **Icons** im Button links von der Beschriftung optimal.
-
-Probleme mit Disabled-Status
-
-- Darstellung Kontraste
-- Möglichkeit des Nutzerfeedbacks
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------- | ------------------------------------------------------------ |
-| `Tab` | Springt den einzelnen Button an und fokussiert ihn. |
-| `Enter` | Führt die onClick-Methode der fokussierten Schaltfläche aus. |
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
-| `_accessKey` | `_access-key` | Defines the elements access key. | `string \| undefined` | `undefined` |
-| `_ariaControls` | `_aria-controls` | Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls) | `string \| undefined` | `undefined` |
-| `_ariaExpanded` | `_aria-expanded` | Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) | `boolean \| undefined` | `undefined` |
-| `_ariaSelected` | `_aria-selected` | Defines whether the interactive element of the component is selected (e.g. role=tab). (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected) | `boolean \| undefined` | `undefined` |
-| `_customClass` | `_custom-class` | Defines the custom class attribute if \_variant="custom" is set. | `string \| undefined` | `undefined` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `KoliBriHorizontalIcons & KoliBriVerticalIcons \| string \| undefined` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Defines the callback functions for button events. | `undefined \| { onClick?: EventValueOrEventCallback \| undefined; onMouseDown?: EventCallback \| undefined; }` | `undefined` |
-| `_role` | `_role` | Defines the role of the components primary element. | `"button" \| "link" \| "tab" \| undefined` | `undefined` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_type` | `_type` | Defines either the type of the component or of the components interactive element. | `"button" \| "reset" \| "submit" \| undefined` | `'button'` |
-| `_value` | `_value` | Defines the value that the button emits on click. | `boolean \| null \| number \| object \| string \| undefined` | `undefined` |
-| `_variant` | `_variant` | Defines which variant should be used for presentation. | `"custom" \| "danger" \| "ghost" \| "normal" \| "primary" \| "secondary" \| "tertiary" \| undefined` | `'normal'` |
-
-## Methods
-
-### `getValue() => Promise | undefined>`
-
-#### Returns
-
-Type: `Promise>`
-
----
diff --git a/packages/components/src/components/button/shadow.tsx b/packages/components/src/components/button/shadow.tsx
index fed222ce63..1be0f3879e 100644
--- a/packages/components/src/components/button/shadow.tsx
+++ b/packages/components/src/components/button/shadow.tsx
@@ -1,35 +1,39 @@
import type {
AccessKeyPropType,
AlternativeButtonLinkRolePropType,
+ AriaDescriptionPropType,
ButtonCallbacksPropType,
ButtonProps,
ButtonTypePropType,
ButtonVariantPropType,
CustomClassPropType,
+ FocusableElement,
IconsPropType,
LabelWithExpertSlotPropType,
+ ShortKeyPropType,
StencilUnknown,
Stringified,
SyncValueBySelectorPropType,
TooltipAlignPropType,
-} from '@public-ui/schema';
-import { propagateFocus } from '@public-ui/schema';
-import { Component, Element, h, Host, Method, Prop } from '@stencil/core';
+} from '../../schema';
+import type { JSX } from '@stencil/core';
+import { Component, h, Method, Prop } from '@stencil/core';
import { KolButtonWcTag } from '../../core/component-names';
-import type { JSX } from '@stencil/core';
@Component({
tag: 'kol-button',
styleUrls: {
default: './style.scss',
},
- shadow: true,
+ shadow: {
+ delegatesFocus: true,
+ },
})
-export class KolButton implements ButtonProps {
- @Element() private readonly host?: HTMLKolButtonElement;
+export class KolButton implements ButtonProps, FocusableElement {
+ private buttonWcRef?: HTMLKolButtonWcElement;
private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
- propagateFocus(this.host, ref);
+ this.buttonWcRef = ref;
};
@Method()
@@ -38,44 +42,44 @@ export class KolButton implements ButtonProps {
return this._value;
}
+ @Method()
+ public async kolFocus() {
+ await this.buttonWcRef?.kolFocus();
+ }
+
public render(): JSX.Element {
return (
-
- 0,
- }}
- _accessKey={this._accessKey}
- _ariaControls={this._ariaControls}
- _ariaExpanded={this._ariaExpanded}
- _ariaSelected={this._ariaSelected}
- _customClass={this._customClass}
- _disabled={this._disabled}
- _hideLabel={this._hideLabel}
- _icons={this._icons}
- _id={this._id}
- _label={this._label}
- _name={this._name}
- _on={this._on}
- _role={this._role}
- _syncValueBySelector={this._syncValueBySelector}
- _tabIndex={this._tabIndex}
- _tooltipAlign={this._tooltipAlign}
- _type={this._type}
- _value={this._value}
- _variant={this._variant}
- >
-
-
-
+
+
+
);
}
/**
- * Defines the elements access key.
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
*/
@Prop() public _accessKey?: AccessKeyPropType;
@@ -84,6 +88,11 @@ export class KolButton implements ButtonProps {
*/
@Prop() public _ariaControls?: string;
+ /**
+ * Defines the value for the aria-description attribute.
+ */
+ @Prop() public _ariaDescription?: AriaDescriptionPropType;
+
/**
* Defines whether the interactive element of the component expanded something. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded)
*/
@@ -141,6 +150,11 @@ export class KolButton implements ButtonProps {
*/
@Prop() public _role?: AlternativeButtonLinkRolePropType;
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
/**
* Selector for synchronizing the value with another input element.
* @internal
diff --git a/packages/components/src/components/button/style.scss b/packages/components/src/components/button/style.scss
index e42fd9ae2b..c75ce6606e 100644
--- a/packages/components/src/components/button/style.scss
+++ b/packages/components/src/components/button/style.scss
@@ -1 +1,5 @@
-@import '../button';
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../@shared/kol-button-mixin';
+
+@include kol-button-styles('kol-button');
diff --git a/packages/components/src/components/button/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/button/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..f901a73ef7
--- /dev/null
+++ b/packages/components/src/components/button/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,234 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-button should render with _label="Label" _ariaDescription="Aria Description" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+ Aria Description
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _disabled=false 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _disabled=true 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _value="Hello" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _variant="danger" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _variant="ghost" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _variant="normal" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _variant="primary" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" _variant="secondary" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`kol-button should render with _label="Label" 1`] = `
+
+
+
+
+
+
+
+
+ Label
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/button/test/html.mock.ts b/packages/components/src/components/button/test/html.mock.ts
deleted file mode 100644
index 6372d9f8ca..0000000000
--- a/packages/components/src/components/button/test/html.mock.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import { showExpertSlot } from '@public-ui/schema';
-
-import clsx from 'clsx';
-
-import type { ButtonProps, ButtonStates } from '@public-ui/schema';
-import { KolSpanWcTag, KolTooltipWcTag } from '../../../core/component-names';
-
-export const getButtonWcHtml = (props: ButtonProps, additionalAttrs = ''): string => {
- const state = mixMembers(
- {
- _icons: {},
- _label: '', // ⚠ required
- _on: {},
- _type: 'button',
- _variant: 'normal',
- },
- props,
- );
- const ariaControls = typeof state._ariaControls === 'string' ? state._ariaControls : undefined;
- const ariaExpanded = typeof state._ariaExpanded === 'boolean' ? state._ariaExpanded : undefined;
- const hasExpertSlot = showExpertSlot(state._label);
- const type = typeof state._type === 'string' ? state._type : 'button';
- const variant = typeof state._variant === 'string' ? state._variant : 'normal';
-
- const classNames = clsx({
- button: true,
- disabled: state._disabled,
- 'hide-label': state._hideLabel,
- [variant]: true,
- });
-
- return `
-
-
- <${KolSpanWcTag}
- class="button-inner"
- _label="${hasExpertSlot ? '' : state._label}"
- >
-
- ${KolSpanWcTag}>
-
-
- <${KolTooltipWcTag}
- aria-hidden="true"
- hidden=""
- ${state._tooltipAlign ? `_align=${state._tooltipAlign}` : "_align='top'"}
- _label="${typeof state._label === 'string' ? state._label : ''}"
- >${KolTooltipWcTag}>
- `;
-};
-
-export const getButtonHtml = (props: ButtonProps): string => {
- const state = mixMembers(
- {
- _icons: {},
- _label: '', // ⚠ required
- _type: 'button',
- _variant: 'normal',
- },
- props,
- );
- return `
-
- ${getButtonWcHtml(props, ` class="kol-button-wc button ${state._variant}"`)}
-
- `;
-};
diff --git a/packages/components/src/components/button/test/snapshot.spec.tsx b/packages/components/src/components/button/test/snapshot.spec.tsx
index 074c4a52b9..4f2583f3be 100644
--- a/packages/components/src/components/button/test/snapshot.spec.tsx
+++ b/packages/components/src/components/button/test/snapshot.spec.tsx
@@ -1,28 +1,29 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolButtonTag } from '../../../core/component-names';
+import type { ButtonProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getButtonHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { ButtonProps } from '@public-ui/schema';
import { KolButton } from '../shadow';
import { KolButtonWc } from '../component';
-executeTests(
- 'Button',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolButton, KolButtonWc],
- template: () => ,
- });
- return page;
- },
- {
- _disabled: [true, false],
- _label: ['Label'],
- _variant: ['primary', 'secondary', 'normal', 'danger', 'ghost'],
- },
- getButtonHtml,
+executeSnapshotTests(
+ KolButtonTag,
+ [KolButton, KolButtonWc],
+ [
+ { _label: 'Label' },
+
+ { _label: 'Label', _disabled: false },
+ { _label: 'Label', _disabled: true },
+
+ ...['primary', 'secondary', 'normal', 'danger', 'ghost'].map(
+ (_variant) =>
+ ({
+ _label: 'Label',
+ _variant,
+ }) as ButtonProps,
+ ),
+
+ { _label: 'Label', _value: 'Hello' },
+
+ { _label: 'Label', _ariaDescription: 'Aria Description' },
+ ],
);
diff --git a/packages/components/src/components/card/card.e2e.ts b/packages/components/src/components/card/card.e2e.ts
new file mode 100644
index 0000000000..f4f20d7f74
--- /dev/null
+++ b/packages/components/src/components/card/card.e2e.ts
@@ -0,0 +1,37 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-card', () => {
+ test.describe('Callbacks', () => {
+ test('should call "onClose" callback when the close button is clicked', async ({ page }) => {
+ await page.setContent(' ');
+ const callbackPromise = page.locator('kol-card').evaluate(async (element: HTMLKolCardElement) => {
+ return new Promise((resolve) => {
+ element._on = {
+ onClose: (_event: Event, value?: unknown) => {
+ resolve(value);
+ },
+ };
+ });
+ });
+ await page.waitForChanges();
+ await page.getByTestId('card-close-button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+
+ test.describe('DOM events', () => {
+ test('should emit "close" when close button is clicked', async ({ page }) => {
+ await page.setContent(' ');
+ const eventPromise = page.locator('kol-card').evaluate(async (element: HTMLKolCardElement, KolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.close, resolve);
+ });
+ }, KolEvent);
+ await page.waitForChanges();
+ await page.getByTestId('card-close-button').click();
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+});
diff --git a/packages/components/src/components/card/component.tsx b/packages/components/src/components/card/component.tsx
deleted file mode 100644
index c5c886487c..0000000000
--- a/packages/components/src/components/card/component.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import type {
- CardAPI,
- CardStates,
- HasCloserPropType,
- HeadingLevel,
- KoliBriAlertEventCallbacks,
- KoliBriCardEventCallbacks,
- LabelPropType,
-} from '@public-ui/schema';
-import { setState, validateHasCloser, validateLabel } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import { translate } from '../../i18n';
-import { watchHeadingLevel } from '../heading/validation';
-
-import type { JSX } from '@stencil/core';
-import { KolButtonWcTag, KolHeadingWcTag } from '../../core/component-names';
-/**
- * @slot - Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich der Card.
- */
-@Component({
- tag: 'kol-card',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolCard implements CardAPI {
- private readonly close = () => {
- if (this._on?.onClose !== undefined) {
- this._on.onClose(new Event('Close'));
- }
- };
-
- private readonly on = {
- onClick: this.close,
- };
-
- public render(): JSX.Element {
- return (
-
-
-
-
-
-
- {this.state._hasCloser && (
-
- )}
-
-
- );
- }
-
- /**
- * Defines the event callback functions for the component.
- */
- @Prop() public _on?: KoliBriCardEventCallbacks;
-
- /**
- * Defines whether the element can be closed.
- * @TODO: Change type back to `HasCloserPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hasCloser?: boolean = false;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- /**
- * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
- */
- @Prop() public _level?: HeadingLevel = 1;
-
- @State() public state: CardStates = {
- _label: '', // ⚠ required
- };
-
- private validateOnValue = (value: unknown): boolean =>
- typeof value === 'object' && value !== null && typeof (value as KoliBriCardEventCallbacks).onClose === 'function';
-
- @Watch('_on')
- public validateOn(value?: KoliBriCardEventCallbacks): void {
- if (this.validateOnValue(value)) {
- setState(this, '_on', {
- onClose: (value as KoliBriAlertEventCallbacks).onClose,
- });
- }
- }
-
- @Watch('_hasCloser')
- public validateHasCloser(value?: HasCloserPropType): void {
- validateHasCloser(this, value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelPropType): void {
- validateLabel(this, value, {
- required: true,
- });
- }
-
- @Watch('_level')
- public validateLevel(value?: HeadingLevel): void {
- watchHeadingLevel(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateHasCloser(this._hasCloser);
- this.validateLabel(this._label);
- this.validateLevel(this._level);
- this.validateOn(this._on);
- }
-}
diff --git a/packages/components/src/components/card/readme.md b/packages/components/src/components/card/readme.md
deleted file mode 100644
index 208095981b..0000000000
--- a/packages/components/src/components/card/readme.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# Card
-
-Um einzelne Bereiche Ihrer Webseite optisch hervorzuheben, bietet sich die **Card**-Komponente an. Mit ihrer Hilfe können Sie Ihre Inhalte sehr einfach strukturieren.
-
-Die **Card**-Komponente besteht aus einem **_Titel-Bereich_**, einem **_Inhalts-Bereich_**.
-
-Der **Titel-Bereich** wird in einer größeren Schrift dargestellt. Der **Inhalts-Bereich** ist optisch durch eine horizontale Trennlinie unterhalb des Titel-Bereichs abgetrennt und wird in der Standardschrift ausgegeben.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum
- dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos
- et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-```
-
-### Beispiel
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum
- dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos
- et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-
-
-## Verwendung
-
-### Einfache Standard-Card
-
-In der Standardansicht besteht eine **Card** aus einem Titel-Bereich, und einem leeren Inhalts-Bereich.
-Die horizontale Trennlinie zwischen beiden Bereichen setzt KoliBri automatisch.
-
-### Titel der Card-Komponente
-
-Den Titel der Card bestimmen Sie durch Setzen des Attributs **`_label`**. Hier können Sie beliebigen Text, auch Sonderzeichen und Umlaute, eingeben.
-Beachten Sie, dass **HTML-Code** nicht erlaubt ist. Sofern nicht gesetzt werden drei Punkte dargestellt.
-Die Überschriftenebene des Titels wird durch das Attribut **`_level`** übergeben. Möglich sind die Level **1** bis **6**
-
-### Inhalts-Container
-
-Die Inhalte im Content-Bereich der Card bestimmen Sie durch Einfügen eines **Inhalts-Containers** innerhalb des ` -Elements`. Hier können Sie beliebigen **HTML-Code** einfügen.
-
-Bitte beachten Sie, dass Sie zwar ein beliebiges HTML-Tag als Inhalts-Container verwenden können, es aber empfohlen wird ein `
`-Tag zu verwenden.
-
-```html
-
- Text im Inhalts-Bereich
-
-```
-
-### Best practices
-
-- Verwenden Sie die **Card**-Komponente, um in sich geschlossene Themenbereiche optisch zu kapseln.
-- Verwenden Sie die **Card**-Komponente, um Ihre Inhalte semantisch zu strukturieren.
-- Vermeiden Sie, zu viele Cards auf einer Inhaltsseite zu verwenden.
-- Vermeiden Sie, wichtige Inhalte innerhalb der Card-Komponente zu platzieren, wenn sich die zugehörigen Aktions-Elemente (Buttons, Links, etc.) nicht innerhalb der gleichen Card befinden.
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | ----------- |
-| `_hasCloser` | `_has-closer` | Defines whether the element can be closed. | `boolean \| undefined` | `false` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_level` | `_level` | Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text. | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` |
-| `_on` | -- | Defines the event callback functions for the component. | `undefined \| { onClose?: EventCallback \| undefined; }` | `undefined` |
-
-## Slots
-
-| Slot | Description |
-| ---- | ------------------------------------------------------------------------- |
-| | Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich der Card. |
-
----
diff --git a/packages/components/src/components/card/shadow.tsx b/packages/components/src/components/card/shadow.tsx
new file mode 100644
index 0000000000..ccd2b5d4d9
--- /dev/null
+++ b/packages/components/src/components/card/shadow.tsx
@@ -0,0 +1,129 @@
+import { Component, Element, h, Prop, State, Watch } from '@stencil/core';
+import type { JSX } from '@stencil/core';
+import type { CardAPI, CardStates, HasCloserPropType, HeadingLevel, KoliBriAlertEventCallbacks, KoliBriCardEventCallbacks, LabelPropType } from '../../schema';
+import { setState, validateHasCloser, validateLabel } from '../../schema';
+
+import { translate } from '../../i18n';
+import { watchHeadingLevel } from '../heading/validation';
+
+import { KolButtonWcTag } from '../../core/component-names';
+import { KolHeadingFc } from '../../functional-components';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+
+/**
+ * @slot - Ermöglicht das Einfügen beliebigen HTML's in den Inhaltsbereich der Card.
+ */
+@Component({
+ tag: 'kol-card',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolCard implements CardAPI {
+ @Element() private readonly host?: HTMLKolCardElement;
+
+ private readonly close = () => {
+ if (this._on?.onClose !== undefined) {
+ this._on.onClose(new Event('Close'));
+ }
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.close);
+ }
+ };
+
+ private readonly on = {
+ onClick: this.close,
+ };
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+ {this.state._hasCloser && (
+
+ )}
+
+ );
+ }
+
+ /**
+ * Defines the event callback functions for the component.
+ */
+ @Prop() public _on?: KoliBriCardEventCallbacks;
+
+ /**
+ * Defines whether the element can be closed.
+ * @TODO: Change type back to `HasCloserPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hasCloser?: boolean = false;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ /**
+ * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
+ */
+ @Prop() public _level?: HeadingLevel = 1;
+
+ @State() public state: CardStates = {
+ _label: '', // ⚠ required
+ };
+
+ private validateOnValue = (value: unknown): boolean =>
+ typeof value === 'object' && value !== null && typeof (value as KoliBriCardEventCallbacks).onClose === 'function';
+
+ @Watch('_on')
+ public validateOn(value?: KoliBriCardEventCallbacks): void {
+ if (this.validateOnValue(value)) {
+ setState(this, '_on', {
+ onClose: (value as KoliBriAlertEventCallbacks).onClose,
+ });
+ }
+ }
+
+ @Watch('_hasCloser')
+ public validateHasCloser(value?: HasCloserPropType): void {
+ validateHasCloser(this, value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ @Watch('_level')
+ public validateLevel(value?: HeadingLevel): void {
+ watchHeadingLevel(this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateHasCloser(this._hasCloser);
+ this.validateLabel(this._label);
+ this.validateLevel(this._level);
+ this.validateOn(this._on);
+ }
+}
diff --git a/packages/components/src/components/card/style.scss b/packages/components/src/components/card/style.scss
index 46de579d74..2a401036aa 100644
--- a/packages/components/src/components/card/style.scss
+++ b/packages/components/src/components/card/style.scss
@@ -1,16 +1,20 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../tooltip/style.scss';
@layer kol-component {
- :host > div.card {
+ .kol-card {
+ font-size: rem(16);
+
height: 100%;
position: relative;
/* Visible with forced colors */
- outline: transparent solid 1px;
- }
+ outline: transparent solid rem(1);
- .close {
- position: absolute;
- top: 0;
- right: 0;
+ &__close-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ }
}
}
diff --git a/packages/components/src/components/card/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/card/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..a31feba673
--- /dev/null
+++ b/packages/components/src/components/card/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,382 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-card should render with _label="Überschrift" _level=0 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=0 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=0 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=1 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=1 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=1 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=2 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=2 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=2 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=3 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=3 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=3 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=4 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=4 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=4 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=5 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=5 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=5 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=6 _hasCloser=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=6 _hasCloser=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" _level=6 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-card should render with _label="Überschrift" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/card/test/html.mock.ts b/packages/components/src/components/card/test/html.mock.ts
deleted file mode 100644
index fbdd152dbe..0000000000
--- a/packages/components/src/components/card/test/html.mock.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import type { CardProps } from '@public-ui/schema';
-import { KolHeadingWcTag, KolButtonWcTag } from '../../../core/component-names';
-
-export const getCardHtml = (props: CardProps): string => {
- props = mixMembers(
- {
- _label: '', // ⚠ required
- },
- props,
- );
- return `
-
-
-
-
-
-
- ${
- props._hasCloser
- ? `<${KolButtonWcTag}
- class="close"
- _hideLabel=""
- _label='kol-close'
- _tooltipAlign="left"
- >${KolButtonWcTag}>`
- : ``
- }
-
-
- `;
-};
diff --git a/packages/components/src/components/card/test/snapshot.spec.tsx b/packages/components/src/components/card/test/snapshot.spec.tsx
index e0449a1b5d..1e8dca5fe2 100644
--- a/packages/components/src/components/card/test/snapshot.spec.tsx
+++ b/packages/components/src/components/card/test/snapshot.spec.tsx
@@ -1,30 +1,37 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolCardTag } from '../../../core/component-names';
+import type { CardProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolCard } from '../shadow';
-import { getCardHtml } from './html.mock';
+executeSnapshotTests(
+ KolCardTag,
+ [KolCard],
+ [
+ { _label: 'Überschrift' },
-import type { SpecPage } from '@stencil/core/testing';
-import type { CardProps } from '@public-ui/schema';
-import { KolCard } from '../component';
+ { _label: 'Überschrift', _level: 0 },
+ { _label: 'Überschrift', _level: 1 },
+ { _label: 'Überschrift', _level: 2 },
+ { _label: 'Überschrift', _level: 3 },
+ { _label: 'Überschrift', _level: 4 },
+ { _label: 'Überschrift', _level: 5 },
+ { _label: 'Überschrift', _level: 6 },
-executeTests(
- 'Card',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolCard],
- template: () => ,
- });
- return page;
- },
- {
- _hasCloser: [false, true],
- _label: ['Überschrift'],
- _level: [1, 2, 3, 4, 5, 6],
- },
- getCardHtml,
- {
- execMode: 'default', // ready
- },
+ { _label: 'Überschrift', _level: 0, _hasCloser: false },
+ { _label: 'Überschrift', _level: 1, _hasCloser: false },
+ { _label: 'Überschrift', _level: 2, _hasCloser: false },
+ { _label: 'Überschrift', _level: 3, _hasCloser: false },
+ { _label: 'Überschrift', _level: 4, _hasCloser: false },
+ { _label: 'Überschrift', _level: 5, _hasCloser: false },
+ { _label: 'Überschrift', _level: 6, _hasCloser: false },
+
+ { _label: 'Überschrift', _level: 0, _hasCloser: true },
+ { _label: 'Überschrift', _level: 1, _hasCloser: true },
+ { _label: 'Überschrift', _level: 2, _hasCloser: true },
+ { _label: 'Überschrift', _level: 3, _hasCloser: true },
+ { _label: 'Überschrift', _level: 4, _hasCloser: true },
+ { _label: 'Überschrift', _level: 5, _hasCloser: true },
+ { _label: 'Überschrift', _level: 6, _hasCloser: true },
+ ],
);
diff --git a/packages/components/src/components/combobox/combobox.e2e.ts b/packages/components/src/components/combobox/combobox.e2e.ts
new file mode 100644
index 0000000000..82e46bced5
--- /dev/null
+++ b/packages/components/src/components/combobox/combobox.e2e.ts
@@ -0,0 +1,10 @@
+import { test } from '@stencil/playwright';
+import { testInputCallbacksAndEvents, testInputValueReflection } from '../../e2e';
+
+const COMPONENT_NAME = 'kol-combobox';
+const TEST_VALUE = 'Hello World';
+
+test.describe(COMPONENT_NAME, () => {
+ testInputValueReflection(COMPONENT_NAME, TEST_VALUE);
+ testInputCallbacksAndEvents(COMPONENT_NAME, TEST_VALUE);
+});
diff --git a/packages/components/src/components/combobox/controller.ts b/packages/components/src/components/combobox/controller.ts
new file mode 100644
index 0000000000..d6c5db8caa
--- /dev/null
+++ b/packages/components/src/components/combobox/controller.ts
@@ -0,0 +1,38 @@
+import type { ComboboxWatches, ComboboxProps, SuggestionsPropType } from '../../schema';
+import { watchBoolean, validateSuggestions, watchString } from '../../schema';
+
+import { InputIconController } from '../@deprecated/input/controller-icon';
+
+import type { Generic } from 'adopted-style-sheets';
+
+export class ComboboxController extends InputIconController implements ComboboxWatches {
+ protected readonly component: Generic.Element.Component & ComboboxProps;
+
+ public constructor(component: Generic.Element.Component & ComboboxProps, name: string, host?: HTMLElement) {
+ super(component, name, host);
+ this.component = component;
+ }
+
+ public validatePlaceholder(value?: string): void {
+ watchString(this.component, '_placeholder', value);
+ }
+ public validateRequired(value?: boolean): void {
+ watchBoolean(this.component, '_required', value);
+ }
+
+ public validateSuggestions(value?: SuggestionsPropType): void {
+ validateSuggestions(this.component, value);
+ }
+
+ public validateValue(value?: string): void {
+ watchString(this.component, '_value', value);
+ }
+
+ public componentWillLoad(): void {
+ super.componentWillLoad();
+ this.validatePlaceholder(this.component._placeholder);
+ this.validateRequired(this.component._required);
+ this.validateSuggestions(this.component._suggestions);
+ this.validateValue(this.component._value);
+ }
+}
diff --git a/packages/components/src/components/combobox/shadow.tsx b/packages/components/src/components/combobox/shadow.tsx
new file mode 100644
index 0000000000..15869ebf12
--- /dev/null
+++ b/packages/components/src/components/combobox/shadow.tsx
@@ -0,0 +1,633 @@
+import type {
+ ComboboxAPI,
+ ComboboxStates,
+ HideErrorPropType,
+ IdPropType,
+ InputTypeOnDefault,
+ KoliBriHorizontalIcons,
+ LabelWithExpertSlotPropType,
+ MsgPropType,
+ NamePropType,
+ ShortKeyPropType,
+ Stringified,
+ SuggestionsPropType,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+ W3CInputValue,
+} from '../../schema';
+import { buildBadgeTextString, showExpertSlot } from '../../schema';
+import type { JSX } from '@stencil/core';
+import { Component, Element, Fragment, h, Host, Listen, Method, Prop, State, Watch } from '@stencil/core';
+
+import { nonce } from '../../utils/dev.utils';
+import { ComboboxController } from './controller';
+import { KolIconTag, KolInputTag } from '../../core/component-names';
+import { InternalUnderlinedBadgeText } from '../../functional-components';
+import { getRenderStates } from '../input/controller';
+import { translate } from '../../i18n';
+import clsx from 'clsx';
+
+/**
+ * @slot - Die Beschriftung des Eingabefeldes.
+ */
+@Component({
+ tag: 'kol-combobox',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: {
+ delegatesFocus: true,
+ },
+})
+export class KolCombobox implements ComboboxAPI {
+ @Element() private readonly host?: HTMLKolComboboxElement;
+ private refInput?: HTMLInputElement;
+ private refSuggestions: HTMLLIElement[] = [];
+ private _focusedOptionIndex: number = -1;
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async getValue(): Promise {
+ return this.state._value;
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ this.refInput?.focus();
+ }
+
+ private toggleListbox = () => {
+ if (this.state._disabled === true) {
+ this._isOpen = false;
+ } else {
+ this._isOpen = !this._isOpen;
+ this.refInput?.focus();
+ if (this._isOpen && Array.isArray(this._filteredSuggestions) && this._filteredSuggestions.length > 0) {
+ const selectedIndex = this._filteredSuggestions.findIndex((option) => option === this.state._value);
+ this._focusedOptionIndex = selectedIndex >= 0 ? selectedIndex : 0;
+ this.focusOption(this._focusedOptionIndex);
+ }
+ }
+ };
+ private readonly catchRef = (ref?: HTMLInputElement) => {
+ this.refInput = ref;
+ };
+
+ private selectOption(event: Event, option: string) {
+ this.controller.onFacade.onInput(event, true, option);
+ this.controller.onFacade.onChange(event, option);
+ this.controller.setFormAssociatedValue(option);
+ this.state._value = option;
+ this.refInput?.focus();
+ }
+ private onInput(event: Event) {
+ const target = event.target as HTMLInputElement;
+ this.state._value = target.value;
+ this._value = target.value;
+ this.controller.onFacade.onInput(event);
+ this.setFilteredSuggestionsByQuery(target.value);
+ this._focusedOptionIndex = -1;
+ }
+
+ private handleKeyDownDropdown(event: KeyboardEvent) {
+ if (event.key.length === 1 && /[a-z0-9]/i.test(event.key)) {
+ this._isOpen = true;
+ this.focusSuggestionStartingWith(event.key);
+ }
+ }
+
+ private setFilteredSuggestionsByQuery(query: string) {
+ if (query.trim() === '') {
+ this._filteredSuggestions = [...this._suggestions];
+ } else {
+ this._filteredSuggestions = Array.isArray(this._suggestions)
+ ? this._suggestions.filter((option: W3CInputValue) => {
+ return (option as string).toLowerCase().includes(query.toLowerCase());
+ })
+ : this._filteredSuggestions;
+
+ this._isOpen = this._filteredSuggestions && this._filteredSuggestions.length > 0 ? true : false;
+ }
+ }
+
+ private moveFocus(delta: number) {
+ if (!this._filteredSuggestions) {
+ return;
+ }
+ let newIndex = this._focusedOptionIndex + delta;
+
+ if (newIndex >= this._filteredSuggestions.length) {
+ newIndex = 0;
+ }
+
+ if (newIndex < 0) {
+ newIndex = this._filteredSuggestions.length - 1;
+ }
+ this.focusOption(newIndex);
+ }
+
+ private focusOption(index: number) {
+ this._focusedOptionIndex = index;
+ if (this.refSuggestions) {
+ const optionElement = this.refSuggestions[index];
+ optionElement?.focus();
+ }
+ }
+
+ private focusSuggestionStartingWith(char: string) {
+ const charLowerCase = char.toLowerCase();
+
+ const index =
+ Array.isArray(this._filteredSuggestions) &&
+ this._filteredSuggestions.length > 0 &&
+ this._filteredSuggestions.findIndex((option: W3CInputValue) => (option as string).toLowerCase().startsWith(charLowerCase));
+
+ if (typeof index === 'number') {
+ this.focusOption(index);
+ }
+ }
+
+ public render(): JSX.Element {
+ const hasExpertSlot = showExpertSlot(this.state._label);
+ const { ariaDescribedBy } = getRenderStates(this.state);
+
+ return (
+
+
+
this.refInput?.focus()}
+ role={`presentation` /* Avoid element being read as 'clickable' in NVDA */}
+ >
+
+ {hasExpertSlot ? (
+
+ ) : typeof this.state._accessKey === 'string' || typeof this.state._shortKey === 'string' ? (
+ <>
+ {' '}
+
+ {buildBadgeTextString(this.state._accessKey, this.state._shortKey)}
+
+ >
+ ) : (
+ {this.state._label}
+ )}
+
+
+
+ 0 ? ariaDescribedBy.join(' ') : undefined}
+ aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
+ aria-labelledby={this.state._id}
+ aria-activedescendant={this._isOpen && this._focusedOptionIndex >= 0 ? `option-${this._focusedOptionIndex}` : undefined}
+ autoCapitalize="off"
+ autoCorrect="off"
+ disabled={this.state._disabled}
+ id={this.state._id}
+ name={this.state._name}
+ required={this.state._required}
+ {...this.controller.onFacade}
+ onFocus={(event) => {
+ this.controller.onFacade.onFocus(event);
+ this.inputHasFocus = true;
+ }}
+ onBlur={(event) => {
+ this.controller.onFacade.onBlur(event);
+ this.inputHasFocus = false;
+ }}
+ onChange={this.onChange.bind(this)}
+ onInput={this.onInput.bind(this)}
+ placeholder={this.state._placeholder}
+ />
+
+
+
+
+ {this._isOpen && !(this.state._disabled === true) && (
+
+ {Array.isArray(this._filteredSuggestions) &&
+ this._filteredSuggestions.length > 0 &&
+ this._filteredSuggestions.map((option, index) => (
+ {
+ if (el) this.refSuggestions[index] = el;
+ }}
+ data-index={index}
+ tabIndex={-1}
+ role="option"
+ aria-selected={this.state._value === option ? 'true' : undefined}
+ onClick={(e) => {
+ this.selectOption(e, option as string);
+ this.toggleListbox();
+ }}
+ onMouseOver={() => {
+ if (!this.blockSuggestionMouseOver) {
+ this.focusOption(index);
+ }
+ }}
+ onFocus={() => {
+ this.focusOption(index);
+ }}
+ class="combobox__item"
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === 'NumpadEnter') {
+ this.selectOption(e, option as string);
+ this.toggleListbox();
+ e.preventDefault();
+ }
+ }}
+ >
+ {option}
+
+ ))}
+
+ )}
+
+
+
+
+ );
+ }
+
+ @Listen('keydown')
+ public handleKeyDown(event: KeyboardEvent) {
+ const handleEvent = (isOpen?: boolean, callback?: () => void): void => {
+ event.preventDefault();
+ if (isOpen !== undefined) {
+ this._isOpen = isOpen;
+ if (!isOpen) {
+ this.refInput?.focus();
+ }
+ }
+ callback?.();
+ };
+ switch (event.key) {
+ case 'Down':
+ case 'ArrowDown': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(true, () => this.moveFocus(1));
+ break;
+ }
+ case 'Up':
+ case 'ArrowUp': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(true, () => this.moveFocus(-1));
+ break;
+ }
+ case 'Tab':
+ if (this._isOpen) {
+ this._isOpen = !this._isOpen;
+ this.refInput?.focus();
+ }
+ break;
+ case 'Esc':
+ case 'Escape': {
+ handleEvent(false);
+ this.refInput?.focus();
+ break;
+ }
+ case 'NumpadEnter':
+ case 'Enter': {
+ this.toggleListbox();
+ break;
+ }
+ case 'Home': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(undefined, () => {
+ if (this._isOpen) {
+ this.focusOption(0);
+ }
+ });
+ break;
+ }
+ case 'End': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(undefined, () => {
+ if (this._isOpen) {
+ this.focusOption(this._filteredSuggestions ? this._filteredSuggestions.length - 1 : 0);
+ }
+ });
+ break;
+ }
+ case 'PageUp': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(undefined, () => this._isOpen && this.moveFocus(-10));
+ break;
+ }
+ case 'PageDown': {
+ this.blockSuggestionMouseOver = true;
+ handleEvent(undefined, () => this._isOpen && this.moveFocus(10));
+ break;
+ }
+ }
+ }
+
+ private readonly controller: ComboboxController;
+ @State()
+ private blockSuggestionMouseOver: boolean = false;
+ @State()
+ private _isOpen: boolean = false;
+ @State()
+ private _filteredSuggestions?: SuggestionsPropType;
+
+ @Listen('click', { target: 'window' })
+ handleWindowClick(event: MouseEvent) {
+ if (this.host != undefined && !this.host.contains(event.target as Node)) {
+ this._isOpen = false;
+ }
+ }
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: string;
+
+ /**
+ * Defines the placeholder for input field. To be shown when there's no value.
+ */
+ @Prop() public _placeholder?: string;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the error message but leaves it in the DOM for the input's aria-describedby.
+ * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the hint text.
+ */
+ @Prop() public _hint?: string = '';
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: Stringified;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: IdPropType;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines the properties for a message rendered as Alert component.
+ */
+ @Prop() public _msg?: Stringified;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: NamePropType;
+
+ /**
+ * Gibt die EventCallback-Funktionen für das Input-Event an.
+ */
+ @Prop() public _on?: InputTypeOnDefault;
+
+ /**
+ * Suggestions to provide for the input.
+ */
+ @Prop() public _suggestions!: SuggestionsPropType;
+
+ /**
+ * Makes the input element required.
+ * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _required?: boolean = false;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Shows if the input was touched by a user.
+ * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
+
+ /**
+ * Defines the value of the input.
+ */
+ @Prop({ mutable: true, reflect: true }) public _value?: string;
+
+ @State() public state: ComboboxStates = {
+ _hasValue: false,
+ _hideError: false,
+ _id: `id-${nonce()}`,
+ _label: '', // ⚠ required
+ _suggestions: [],
+ _value: '',
+ };
+
+ @State() private inputHasFocus = false;
+
+ public constructor() {
+ this.controller = new ComboboxController(this, 'combobox', this.host);
+ this.onInput = this.onInput.bind(this);
+ }
+
+ private showAsAlert(): boolean {
+ return Boolean(this.state._touched) && !this.inputHasFocus;
+ }
+
+ @Watch('_placeholder')
+ public validatePlaceholder(value?: string): void {
+ this.controller.validatePlaceholder(value);
+ }
+
+ @Watch('_accessKey')
+ public validateAccessKey(value?: string): void {
+ this.controller.validateAccessKey(value);
+ }
+
+ @Watch('_disabled')
+ public validateDisabled(value?: boolean): void {
+ this.controller.validateDisabled(value);
+ }
+
+ @Watch('_hideError')
+ public validateHideError(value?: HideErrorPropType): void {
+ this.controller.validateHideError(value);
+ }
+
+ @Watch('_hideLabel')
+ public validateHideLabel(value?: boolean): void {
+ this.controller.validateHideLabel(value);
+ }
+
+ @Watch('_hint')
+ public validateHint(value?: string): void {
+ this.controller.validateHint(value);
+ }
+
+ @Watch('_icons')
+ public validateIcons(value?: Stringified): void {
+ this.controller.validateIcons(value);
+ }
+
+ @Watch('_id')
+ public validateId(value?: string): void {
+ this.controller.validateId(value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelWithExpertSlotPropType): void {
+ this.controller.validateLabel(value);
+ }
+
+ @Watch('_msg')
+ public validateMsg(value?: Stringified): void {
+ this.controller.validateMsg(value);
+ }
+
+ @Watch('_name')
+ public validateName(value?: string): void {
+ this.controller.validateName(value);
+ }
+
+ @Watch('_on')
+ public validateOn(value?: InputTypeOnDefault): void {
+ this.controller.validateOn(value);
+ }
+
+ @Watch('_shortKey')
+ public validateShortKey(value?: ShortKeyPropType): void {
+ this.controller.validateShortKey(value);
+ }
+
+ @Watch('_suggestions')
+ public validateSuggestions(value?: SuggestionsPropType): void {
+ this.controller.validateSuggestions(value);
+ this._filteredSuggestions = value;
+ }
+
+ @Watch('_required')
+ public validateRequired(value?: boolean): void {
+ this.controller.validateRequired(value);
+ }
+
+ @Watch('_syncValueBySelector')
+ public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
+ this.controller.validateSyncValueBySelector(value);
+ }
+
+ @Watch('_tabIndex')
+ public validateTabIndex(value?: number): void {
+ this.controller.validateTabIndex(value);
+ }
+
+ @Watch('_touched')
+ public validateTouched(value?: boolean): void {
+ this.controller.validateTouched(value);
+ }
+
+ @Watch('_value')
+ public validateValue(value?: string): void {
+ this.controller.validateValue(value);
+ this.controller.setFormAssociatedValue(value);
+ }
+
+ public componentWillLoad(): void {
+ this.refSuggestions = [];
+ this._touched = this._touched === true;
+ this.controller.componentWillLoad();
+
+ this.state._hasValue = !!this.state._value;
+ this.controller.addValueChangeListener((v) => (this.state._hasValue = !!v));
+ this._filteredSuggestions = this.state._suggestions;
+ }
+
+ @Listen('mousemove')
+ public handleMouseEvent() {
+ this.blockSuggestionMouseOver = false;
+ }
+
+ @Listen('focusout', { target: 'window' })
+ public handleFocusOut() {
+ setTimeout(() => {
+ if (!this.host?.contains(document.activeElement)) {
+ this.onBlur();
+ }
+ }, 0);
+ }
+ @Listen('blur', { target: 'window' })
+ public handleWindowBlur() {
+ this.onBlur();
+ }
+
+ private onBlur() {
+ if (this._isOpen) {
+ this._isOpen = !this._isOpen;
+ this.refInput?.focus();
+ }
+ }
+
+ private onChange(event: Event): void {
+ this.controller.onFacade.onChange(event);
+
+ // Static form handling
+ this.controller.setFormAssociatedValue(this.state._value as unknown as string);
+ }
+}
diff --git a/packages/components/src/components/combobox/style.scss b/packages/components/src/components/combobox/style.scss
new file mode 100644
index 0000000000..03d7fbc79a
--- /dev/null
+++ b/packages/components/src/components/combobox/style.scss
@@ -0,0 +1,71 @@
+@import '../../styles/global';
+@import '../@shared/mixins';
+@import '../host-display-block';
+@import '../tooltip/style';
+
+@layer kol-component {
+ :host {
+ font-size: rem(16);
+ }
+
+ .combobox {
+ position: relative;
+
+ &--disabled,
+ &--disabled * {
+ cursor: not-allowed !important;
+ }
+
+ &--disabled {
+ opacity: 0.5;
+ outline: none;
+ }
+
+ &__group {
+ display: inline-flex;
+ align-items: center;
+ cursor: pointer;
+ }
+
+ &__input {
+ flex-grow: 1;
+
+ &:focus {
+ outline: none;
+ }
+ }
+
+ &__icon {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ height: var(--a11y-min-size);
+ width: var(--a11y-min-size);
+ }
+
+ &__listbox {
+ display: block;
+ position: absolute;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ overflow-y: auto;
+ overflow-x: hidden;
+ z-index: 2;
+ background-color: white;
+ max-height: rem(250);
+ }
+
+ &__item {
+ cursor: pointer;
+
+ .combobox__listbox--cursor-hidden & {
+ cursor: none !important;
+ }
+ }
+ }
+
+ .kol-input {
+ display: grid;
+ }
+}
diff --git a/packages/components/src/components/combobox/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/combobox/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..f45ea2acdc
--- /dev/null
+++ b/packages/components/src/components/combobox/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,315 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _accessKey="V" 1`] = `
+
+
+
+
+
+ Label
+
+ V
+
+
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _shortKey="S" 1`] = `
+
+
+
+
+
+ Label
+
+ S
+
+
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-combobox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="Herr" _suggestions=["Frau","Herr","Divers"] 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/combobox/test/snapshot.spec.tsx b/packages/components/src/components/combobox/test/snapshot.spec.tsx
new file mode 100644
index 0000000000..2df1608bc4
--- /dev/null
+++ b/packages/components/src/components/combobox/test/snapshot.spec.tsx
@@ -0,0 +1,10 @@
+import { KolComboboxTag } from '../../../core/component-names';
+import type { ComboboxProps } from '../../../schema';
+import { executeInputSnapshotTests } from '../../../utils/testing';
+
+import { KolCombobox } from '../shadow';
+
+executeInputSnapshotTests(KolComboboxTag, [KolCombobox], {
+ _value: 'Herr',
+ _suggestions: ['Frau', 'Herr', 'Divers'],
+});
diff --git a/packages/components/src/components/component-list.ts b/packages/components/src/components/component-list.ts
index 497f4d375a..3f8f98025b 100644
--- a/packages/components/src/components/component-list.ts
+++ b/packages/components/src/components/component-list.ts
@@ -1,64 +1,59 @@
-import { KolAbbr } from './abbr/component';
-import { KolAccordion } from './accordion/component';
+import { KolAbbr } from './abbr/shadow';
+import { KolAccordion } from './accordion/shadow';
import { KolAlertWc } from './alert/component';
import { KolAlert } from './alert/shadow';
import { KolAvatarWc } from './avatar/component';
import { KolAvatar } from './avatar/shadow';
-import { KolBadge } from './badge/component';
-import { KolBreadcrumb } from './breadcrumb/component';
-import { KolButtonGroupWc } from './button-group/component';
-import { KolButtonGroup } from './button-group/shadow';
-import { KolButtonLink } from './button-link/component';
+import { KolBadge } from './badge/shadow';
+import { KolBreadcrumb } from './breadcrumb/shadow';
+import { KolButtonLink } from './button-link/shadow';
import { KolButtonWc } from './button/component';
import { KolButton } from './button/shadow';
-import { KolCard } from './card/component';
-import { KolDetails } from './details/component';
-import { KolForm } from './form/component';
-import { KolHeadingWc } from './heading/component';
+import { KolCard } from './card/shadow';
+import { KolDetails } from './details/shadow';
+import { KolDrawer } from './drawer/shadow';
+import { KolForm } from './form/shadow';
import { KolHeading } from './heading/shadow';
-import { KolIcon } from './icon/component';
+import { KolIcon } from './icon/shadow';
import { KolImage } from './image/shadow';
-import { KolIndentedText } from './indented-text/component';
-import { KolInputCheckbox } from './input-checkbox/component';
-import { KolInputColor } from './input-color/component';
-import { KolInputDate } from './input-date/component';
-import { KolInputEmail } from './input-email/component';
-import { KolInputFile } from './input-file/component';
-import { KolInputNumber } from './input-number/component';
-import { KolInputPassword } from './input-password/component';
-import { KolInputRadio } from './input-radio/component';
-import { KolInputRange } from './input-range/component';
-import { KolInputText } from './input-text/component';
-import { KolInput } from './input/component';
-import { KolKolibri } from './kolibri/component';
-import { KolLinkButton } from './link-button/component';
-import { KolLinkGroup } from './link-group/component';
+import { KolInputCheckbox } from './input-checkbox/shadow';
+import { KolInputColor } from './input-color/shadow';
+import { KolInputDate } from './input-date/shadow';
+import { KolInputEmail } from './input-email/shadow';
+import { KolInputFile } from './input-file/shadow';
+import { KolInputNumber } from './input-number/shadow';
+import { KolInputPassword } from './input-password/shadow';
+import { KolInputRadio } from './input-radio/shadow';
+import { KolInputRange } from './input-range/shadow';
+import { KolInputText } from './input-text/shadow';
+import { KolInputWc } from './input/component';
+import { KolKolibri } from './kolibri/shadow';
+import { KolLinkButton } from './link-button/shadow';
import { KolLinkWc } from './link/component';
import { KolLink } from './link/shadow';
-import { KolLogo } from './logo/component';
-import { KolModal } from './modal/component';
-import { KolNav } from './nav/component';
-import { KolPagination } from './pagination/component';
+import { KolModal } from './modal/shadow';
+import { KolNav } from './nav/shadow';
+import { KolPagination } from './pagination/shadow';
import { KolPopover } from './popover/component';
-import { KolProcess } from './progress/component';
+import { KolProcess } from './progress/shadow';
import { KolQuote } from './quote/shadow';
-import { KolSelect } from './select/component';
-import { KolSkipNav } from './skip-nav/component';
-import { KolSpan } from './span/shadow';
-import { KolSpanWc } from './span/component';
-import { KolSpin } from './spin/component';
-import { KolSplitButton } from './split-button/component';
+import { KolSelect } from './select/shadow';
+import { KolSkipNav } from './skip-nav/shadow';
+import { KolSpin } from './spin/shadow';
+import { KolSingleSelect } from './single-select/shadow';
+import { KolSplitButton } from './split-button/shadow';
import { KolSymbol } from './symbol/component';
-import { KolTable } from './table/component';
-import { KolTabs } from './tabs/component';
-import { KolTextarea } from './textarea/component';
-import { KolToastContainer } from './toaster/component';
-import { KolTooltip } from './tooltip/component';
-import { KolVersion } from './version/component';
+import { KolTabs } from './tabs/shadow';
+import { KolTextarea } from './textarea/shadow';
+import { KolToastContainer } from './toaster/shadow';
+import { KolToolbar } from './toolbar/shadow';
+import { KolTooltipWc } from './tooltip/component';
+import { KolVersion } from './version/shadow';
import { KolTree } from './tree/shadow';
import { KolTreeItem } from './tree-item/shadow';
import { KolTreeItemWc } from './tree-item/component';
import { KolTreeWc } from './tree/component';
+import { KolCombobox } from './combobox/shadow';
export const COMPONENTS = [
KolAbbr,
@@ -70,19 +65,17 @@ export const COMPONENTS = [
KolBadge,
KolBreadcrumb,
KolButton,
- KolButtonGroup,
- KolButtonGroupWc,
KolButtonLink,
KolButtonWc,
KolCard,
+ KolCombobox,
KolDetails,
+ KolDrawer,
KolForm,
KolHeading,
- KolHeadingWc,
KolIcon,
KolImage,
- KolIndentedText,
- KolInput,
+ KolInputWc,
KolInputCheckbox,
KolInputColor,
KolInputDate,
@@ -96,9 +89,7 @@ export const COMPONENTS = [
KolKolibri,
KolLink,
KolLinkButton,
- KolLinkGroup,
KolLinkWc,
- KolLogo,
KolModal,
KolNav,
KolPagination,
@@ -107,16 +98,15 @@ export const COMPONENTS = [
KolQuote,
KolSelect,
KolSkipNav,
- KolSpan,
- KolSpanWc,
KolSpin,
+ KolSingleSelect,
KolSplitButton,
KolSymbol,
- KolTable,
KolTabs,
KolTextarea,
KolToastContainer,
- KolTooltip,
+ KolToolbar,
+ KolTooltipWc,
KolTree,
KolTreeItem,
KolTreeItemWc,
diff --git a/packages/components/src/components/details/DetailsAnimationController.ts b/packages/components/src/components/details/DetailsAnimationController.ts
deleted file mode 100644
index 6a5b8a3742..0000000000
--- a/packages/components/src/components/details/DetailsAnimationController.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Heavily inspired by: https://codepen.io/Mamboleoo/pen/QWEpLqm */
-
-export class DetailsAnimationController {
- private animation?: Animation;
- private isClosing = false;
- private isExpanding = false;
-
- constructor(
- private detailsElement: HTMLDetailsElement,
- private summaryElement: HTMLElement,
- private contentElement: HTMLElement,
- ) {
- this.summaryElement.addEventListener('click', this.handleSummaryClick.bind(this));
- }
-
- private handleSummaryClick(event: MouseEvent) {
- event.preventDefault();
-
- if (this.isClosing || !this.detailsElement.open) {
- this.open();
- } else if (this.isExpanding || this.detailsElement.open) {
- this.collapse();
- }
- }
-
- public open() {
- this.detailsElement.open = true;
- window.requestAnimationFrame(this.expand.bind(this));
- }
-
- private expand() {
- this.isExpanding = true;
- this.animateContentHeight('expand');
- }
-
- private collapse() {
- this.isClosing = true;
- this.animateContentHeight('collapse');
- }
-
- private animateContentHeight(direction: 'expand' | 'collapse') {
- let startHeight = direction === 'expand' ? 0 : this.contentElement.offsetHeight;
- let endHeight = direction === 'expand' ? this.contentElement.offsetHeight : 0;
-
- /**
- * Override start and end height, when an animation is ongoing. During the animation, offsetHeight reflects the actual current height as it's being animated.
- * After canceling the animation, it reverts to the full height of the content container.
- */
- if (this.animation) {
- startHeight = this.contentElement.offsetHeight;
- this.animation.cancel();
- if (direction === 'expand') {
- endHeight = this.contentElement.offsetHeight;
- }
- }
-
- this.animation = this.contentElement.animate(
- {
- height: [`${startHeight}px`, `${endHeight}px`],
- },
- {
- duration: matchMedia('(prefers-reduced-motion)').matches ? 0 : 250,
- easing: 'ease-out',
- },
- );
-
- this.animation.addEventListener(
- 'finish',
- () => {
- this.onAnimationFinish();
- },
- { once: true },
- );
- this.animation.addEventListener(
- 'cancel',
- () => {
- if (direction === 'expand') {
- this.isExpanding = false;
- } else {
- this.isClosing = false;
- }
- },
- { once: true },
- );
- }
-
- private onAnimationFinish() {
- this.detailsElement.open = this.isExpanding;
- this.animation = undefined;
- this.isClosing = false;
- this.isExpanding = false;
- }
-}
diff --git a/packages/components/src/components/details/component.tsx b/packages/components/src/components/details/component.tsx
deleted file mode 100644
index 7cae1b08f9..0000000000
--- a/packages/components/src/components/details/component.tsx
+++ /dev/null
@@ -1,166 +0,0 @@
-import type { DetailsAPI, DetailsStates, EventCallbacks, LabelPropType } from '@public-ui/schema';
-import { propagateFocus, setState, validateLabel, validateOpen } from '@public-ui/schema';
-import { Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';
-
-import { tryToDispatchKoliBriEvent } from '../../utils/events';
-import { DetailsAnimationController } from './DetailsAnimationController';
-
-import type { DisabledPropType } from '@public-ui/schema';
-import { validateDisabled } from '@public-ui/schema';
-import type { JSX } from '@stencil/core';
-import { preventDefaultAndStopPropagation } from '../../utils/events';
-import { KolIconTag, KolIndentedTextTag } from '../../core/component-names';
-
-/**
- * @slot - Der Inhalt, der in der Detailbeschreibung angezeigt wird.
- */
-@Component({
- tag: 'kol-details',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolDetails implements DetailsAPI {
- @Element() private readonly host?: HTMLKolDetailsElement;
- private detailsElement?: HTMLDetailsElement;
- private summaryElement?: HTMLElement;
- private contentElement?: HTMLElement;
-
- private readonly catchDetails = (ref?: HTMLElement) => {
- this.detailsElement = ref as HTMLDetailsElement;
- };
-
- private readonly catchSummary = (ref?: HTMLElement) => {
- this.summaryElement = ref;
- propagateFocus(this.host, this.summaryElement);
- };
-
- /**
- * Handle disabled, because the toggle event is to late.
- */
- private readonly preventToggleIfDisabled = (event: Event) => {
- if (this.state._disabled === true) {
- preventDefaultAndStopPropagation(event);
- }
- };
-
- public render(): JSX.Element {
- return (
-
-
- {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
-
-
- {this.state._label}
-
- (this.contentElement = element)}>
-
-
-
-
-
-
- );
- }
-
- /**
- * Makes the element not focusable and ignore all events.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- /**
- * Defines the callback functions for details.
- */
- @Prop() public _on?: EventCallbacks;
-
- /**
- * If set (to true) opens/expands the element, closes if not set (or set to false).
- * @TODO: Change type back to `OpenPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _open?: boolean = false;
-
- @State() public state: DetailsStates = {
- _label: '', // ⚠ required
- _on: {},
- };
-
- @Watch('_disabled')
- public validateDisabled(value?: DisabledPropType): void {
- validateDisabled(this, value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelPropType): void {
- validateLabel(this, value, {
- required: true,
- });
- }
-
- @Watch('_on')
- public validateOn(on?: EventCallbacks) {
- if (typeof on === 'object' && on !== null && typeof on.onToggle === 'function') {
- setState(this, '_on', on);
- }
- }
-
- @Watch('_open')
- public validateOpen(value?: boolean): void {
- validateOpen(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateDisabled(this._disabled);
- this.validateLabel(this._label);
- this.validateOn(this._on);
- this.validateOpen(this._open);
- }
-
- public componentDidLoad() {
- if (this.detailsElement && this.summaryElement && this.contentElement) {
- const animationController = new DetailsAnimationController(this.detailsElement, this.summaryElement, this.contentElement);
- if (this.state._open) {
- animationController.open();
- }
- }
- }
-
- private toggleTimeout?: ReturnType;
-
- private handleToggle = (event: Event) => {
- clearTimeout(this.toggleTimeout);
- this.toggleTimeout = setTimeout(() => {
- const open = Boolean(this.detailsElement?.open);
- if (open !== this.state._open) {
- // Update state
- this._open = Boolean(this.detailsElement?.open);
-
- // Event handling
- tryToDispatchKoliBriEvent('toggle', this.host, this._open);
-
- // Callback
- if (typeof this.state._on?.onToggle === 'function') {
- this.state._on?.onToggle(event, this._open);
- }
- }
- }, 25);
- };
-}
diff --git a/packages/components/src/components/details/details.e2e.ts b/packages/components/src/components/details/details.e2e.ts
new file mode 100644
index 0000000000..9eda331f80
--- /dev/null
+++ b/packages/components/src/components/details/details.e2e.ts
@@ -0,0 +1,43 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-details', () => {
+ test.describe('Callbacks', () => {
+ test(`should call 'onToggle' callback when title is clicked`, async ({ page }) => {
+ await page.setContent(' ');
+ const kolDetails = page.locator('kol-details');
+
+ const callbackPromise = kolDetails.evaluate((element: HTMLKolDetailsElement) => {
+ return new Promise((resolve) => {
+ element._on = {
+ onToggle: () => {
+ resolve();
+ },
+ };
+ });
+ });
+ await page.waitForChanges();
+
+ await page.locator('button').click();
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+
+ test.describe('DOM events', () => {
+ test(`should emit 'toggle' when title is clicked`, async ({ page }) => {
+ await page.setContent(' ');
+ const kolDetails = page.locator('kol-details');
+
+ const eventPromise = kolDetails.evaluate(async (element: HTMLKolDetailsElement, KolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.toggle, resolve);
+ });
+ }, KolEvent);
+ await page.waitForChanges();
+
+ await page.locator('button').click();
+ await expect(eventPromise).resolves.toBeTruthy();
+ });
+ });
+});
diff --git a/packages/components/src/components/details/readme.md b/packages/components/src/components/details/readme.md
deleted file mode 100644
index ea9376f9b8..0000000000
--- a/packages/components/src/components/details/readme.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# Details
-
-Mit Hilfe der **Detail**-Komponente können weiterführende Informationen zunächst mit einem kurzen Einleitungstext angezeigt werden, die erst nach Klick
-durch die Nutzer:innen auf ein Pfeil-Icon in voller Größe aufgeklappt werden.
-
-Die **Detail**-Komponente stellt sich standardmäßig als einzeiliges Layout-Element dar, das aus einem Pfeil-Icon und einem nachfolgenden,
-kurzen Einleitungstext gebildet wird. Der eigentliche Inhalt der Komponente wird erst nach Klick auf den Kopfbereich nach unten hin geöffnet. Das Pfeil-Icon ändert dabei
-seine Ausrichtung von **_rechts_** nach **_unten_**.
-Analog lässt sich die Komponente auch wieder schließen und der Inhalt damit verbergen.
-
-## Konstruktion
-
-### Code
-
-```html
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
- vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit
- amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-```
-
-### Beispiel
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
- dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
- kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
- sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-
-## Verwendung
-
-### Geöffnet anzeigen
-
-Verwenden Sie das Attribut **`_open`**, um die Komponente geöffnet darzustellen.
-
-### Einleitungstext
-
-Verwenden Sie das Attribut **`_label`**, um den Text zu definieren, der als Überschrift angezeigt werden soll.
-
-### Best practices
-
-- Verwenden Sie die **Detail**-Komponente, um ergänzende Inhalte zu einem Hauptthema platzsparend anzuordnen.
-- Die **Detail**-Komponente eignet sich gut für die Realisierung einer FAQ-Seite, wobei die Frage über das Attribut **`_label`** und die Antwort im Inhaltsbereich ausgegeben werden kann.
-- Vermeiden Sie es, wichtige Informationen, die z.B. rechtliche Aspekte betreffen, in einem verborgenen Bereich auszugeben. Es kann nicht sichergestellt werden, dass der Benutzer diese Informationen auch sicher liest.
-- Vermeiden Sie es, zu viele **Detail**-Komponenten zu verwenden, da die Übersichtlichkeit der Seite hierunter leiden kann.
-
-### Anwendungsfälle
-
-#### Details-Komponente innerhalb eines Fließtextes
-
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
- dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
- kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
- sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
- dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
- kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
- sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
- dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
- kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
- sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-
-
-## Barrierefreiheit
-
-- Die **Details**-Komponente bietet sich an, um eine Kontext-sensitive Hilfe für die Barrierefreiheit umzusetzen.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------- | ----------------------------------------------- |
-| `Tab` | Fokussiert die Details-Komponente. |
-| `Enter` | Öffnet bzw. schließt den Inhalt der Komponente. |
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ----------- |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-| `_on` | -- | Defines the callback functions for details. | `undefined \| { onToggle?: EventValueOrEventCallback \| undefined; }` | `undefined` |
-| `_open` | `_open` | If set (to true) opens/expands the element, closes if not set (or set to false). | `boolean \| undefined` | `false` |
-
-## Slots
-
-| Slot | Description |
-| ---- | --------------------------------------------------------- |
-| | Der Inhalt, der in der Detailbeschreibung angezeigt wird. |
-
----
diff --git a/packages/components/src/components/details/shadow.tsx b/packages/components/src/components/details/shadow.tsx
new file mode 100644
index 0000000000..e24fc6fc1f
--- /dev/null
+++ b/packages/components/src/components/details/shadow.tsx
@@ -0,0 +1,157 @@
+import { Component, Element, h, type JSX, Method, Prop, State, Watch } from '@stencil/core';
+import type { DetailsAPI, DetailsCallbacksPropType, DetailsStates, DisabledPropType, FocusableElement, HeadingLevel, LabelPropType } from '../../schema';
+import { validateDetailsCallbacks, validateDisabled, validateLabel, validateOpen } from '../../schema';
+import KolCollapsibleFc, { type CollapsibleProps } from '../../functional-components/Collapsible';
+import { nonce } from '../../utils/dev.utils';
+import { watchHeadingLevel } from '../heading/validation';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+
+/**
+ * @slot - Der Inhalt, der in der Detailbeschreibung angezeigt wird.
+ */
+@Component({
+ tag: 'kol-details',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolDetails implements DetailsAPI, FocusableElement {
+ @Element() private readonly host?: HTMLKolDetailsElement;
+
+ private readonly nonce = nonce();
+ private buttonWcRef?: HTMLKolButtonWcElement;
+
+ private readonly catchRef = (ref?: HTMLKolButtonWcElement) => {
+ this.buttonWcRef = ref;
+ };
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ await this.buttonWcRef?.kolFocus();
+ }
+
+ private toggleTimeout?: ReturnType;
+
+ private handleOnClick = (event: MouseEvent) => {
+ this._open = !this._open;
+
+ /**
+ * Der Timeout wird benötigt, damit das Event
+ * vom Button- auf das Accordion-Event wechselt.
+ * So ist es dem Anwendenden möglich das _open-
+ * Attribute abzufragen.
+ */
+
+ clearTimeout(this.toggleTimeout);
+
+ this.toggleTimeout = setTimeout(() => {
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.toggle, Boolean(this._open));
+ }
+ this.state._on?.onToggle?.(event, Boolean(this._open));
+ }, 25);
+ };
+
+ public render(): JSX.Element {
+ const { _open, _label, _disabled } = this.state;
+ const _level = 1;
+
+ const rootClass = 'kol-details';
+
+ const props: CollapsibleProps = {
+ id: this.nonce,
+ label: _label,
+ open: _open,
+ disabled: _disabled,
+ level: _level,
+ onClick: this.handleOnClick,
+ class: rootClass,
+ HeadingProps: { class: `${rootClass}__heading` },
+ HeadingButtonProps: {
+ ref: this.catchRef,
+ class: `${rootClass}__heading-button`,
+ _icons: 'codicon codicon-chevron-right',
+ },
+ ContentProps: {
+ class: `${rootClass}__content indented-text`,
+ wrapperClass: `${rootClass}__wrapper`,
+ animationClass: `${rootClass}__wrapper-animation`,
+ },
+ };
+
+ return (
+
+
+
+ );
+ }
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ /**
+ * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
+ */
+ @Prop() public _level?: HeadingLevel = 1;
+
+ /**
+ * Defines the callback functions for details.
+ */
+ @Prop() public _on?: DetailsCallbacksPropType;
+
+ /**
+ * Opens/expands the element when truthy, closes/collapses when falsy.
+ * @TODO: Change type back to `OpenPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _open?: boolean = false;
+
+ @State() public state: DetailsStates = {
+ _label: '', // ⚠ required
+ _level: 1,
+ _on: {},
+ };
+
+ @Watch('_disabled')
+ public validateDisabled(value?: DisabledPropType): void {
+ validateDisabled(this, value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ @Watch('_level')
+ public validateLevel(value?: HeadingLevel): void {
+ watchHeadingLevel(this, value);
+ }
+
+ @Watch('_on')
+ public validateOn(on?: DetailsCallbacksPropType) {
+ validateDetailsCallbacks(this, on);
+ }
+
+ @Watch('_open')
+ public validateOpen(value?: boolean): void {
+ validateOpen(this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateDisabled(this._disabled);
+ this.validateLabel(this._label);
+ this.validateLevel(this._level);
+ this.validateOn(this._on);
+ this.validateOpen(this._open);
+ }
+}
diff --git a/packages/components/src/components/details/style.scss b/packages/components/src/components/details/style.scss
index b6d02858cf..2d4be8bf0c 100644
--- a/packages/components/src/components/details/style.scss
+++ b/packages/components/src/components/details/style.scss
@@ -1,37 +1,31 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
@import '../host-display-block';
+@import '../../functional-components/Collapsible/collapsible';
@layer kol-component {
- details {
- display: grid;
- }
-
- details > summary {
- cursor: pointer;
- display: flex;
- place-items: center;
- }
-
- details > summary > span {
- border-bottom-color: grey;
- border-bottom-style: solid;
- }
+ .kol-details {
+ font-size: rem(16);
- details > summary:focus > span,
- details > summary:hover > span,
- details[open] > summary > span {
- border-bottom-color: #000;
- }
+ &__heading-button {
+ display: flex;
- .content {
- overflow: hidden;
- }
+ .kol-button {
+ min-height: auto;
- details > .kol-indented-text {
- margin: 0.25em 0 0 0.5em;
- }
+ .kol-span {
+ &__label {
+ border-bottom-color: grey;
+ border-bottom-style: solid;
+ }
+ }
+ }
+ }
- .icon.is-open::part(icon) {
- transform: rotate(90deg);
+ .collapsible--open &__heading-button {
+ .kol-icon::part(icon) {
+ transform: rotate(90deg);
+ }
+ }
}
}
diff --git a/packages/components/src/components/details/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/details/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..5c10115b17
--- /dev/null
+++ b/packages/components/src/components/details/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,229 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-details should render with _label="Zusammenfassung" _disabled=false _open=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _disabled=false _open=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _disabled=true _open=false 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _disabled=true _open=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=0 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=1 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=2 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=3 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=4 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=5 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" _level=6 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-details should render with _label="Zusammenfassung" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/details/test/html.mock.ts b/packages/components/src/components/details/test/html.mock.ts
deleted file mode 100644
index 770677f9b1..0000000000
--- a/packages/components/src/components/details/test/html.mock.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import type { DetailsProps } from '@public-ui/schema';
-import clsx from 'clsx';
-import { KolIconTag, KolIndentedTextTag } from '../../../core/component-names';
-
-export const getDetailsHtml = (props: DetailsProps): string => {
- props = mixMembers(
- {
- _label: '', // ⚠ required
- },
- props,
- );
-
- const classNames = clsx({
- disabled: props._disabled,
- open: props._open,
- });
-
- return `
-
-
-
- <${KolIconTag} _label="" _icons="codicon codicon-chevron-right" class="icon${props._open ? ' is-open' : ''}" > ${KolIconTag}>
-
- ${props._label}
-
-
-
- <${KolIndentedTextTag}>
-
- ${KolIndentedTextTag}>
-
-
-
- `;
-};
diff --git a/packages/components/src/components/details/test/snapshot.spec.tsx b/packages/components/src/components/details/test/snapshot.spec.tsx
index 5ff7bcbc44..023f396b66 100644
--- a/packages/components/src/components/details/test/snapshot.spec.tsx
+++ b/packages/components/src/components/details/test/snapshot.spec.tsx
@@ -1,30 +1,20 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolDetailsTag } from '../../../core/component-names';
+import type { DetailsProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolDetails } from '../shadow';
-import { getDetailsHtml } from './html.mock';
+executeSnapshotTests(
+ KolDetailsTag,
+ [KolDetails],
+ [
+ { _label: 'Zusammenfassung' },
-import type { SpecPage } from '@stencil/core/testing';
-import type { DetailsProps } from '@public-ui/schema';
-import { KolDetails } from '../component';
+ { _label: 'Zusammenfassung', _disabled: true, _open: false },
+ { _label: 'Zusammenfassung', _disabled: true, _open: true },
+ { _label: 'Zusammenfassung', _disabled: false, _open: false },
+ { _label: 'Zusammenfassung', _disabled: false, _open: true },
-executeTests(
- 'Details',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolDetails],
- template: () => ,
- });
- return page;
- },
- {
- _disabled: [true, false],
- _label: ['Zusammenfassung'],
- _open: [false, true],
- },
- getDetailsHtml,
- {
- execMode: 'default', // ready
- },
+ ...[0, 1, 2, 3, 4, 5, 6].map((_level) => ({ _label: 'Zusammenfassung', _level }) as DetailsProps),
+ ],
);
diff --git a/packages/components/src/components/drawer/drawer.e2e.ts b/packages/components/src/components/drawer/drawer.e2e.ts
new file mode 100644
index 0000000000..fa6499db3f
--- /dev/null
+++ b/packages/components/src/components/drawer/drawer.e2e.ts
@@ -0,0 +1,71 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-drawer', () => {
+ test.describe('Callbacks', () => {
+ test(`should call 'onClose' callback when drawer is closed`, async ({ page }) => {
+ await page.setContent('Drawer content ');
+ const kolDrawer = page.locator('kol-drawer');
+
+ const callbackPromise = kolDrawer.evaluate((element: HTMLKolDrawerElement) => {
+ return new Promise((resolve) => {
+ element._on = {
+ onClose: () => {
+ resolve();
+ },
+ };
+ });
+ });
+ await page.waitForChanges();
+ await page.keyboard.press('Escape');
+
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+
+ test.describe('_open property', () => {
+ test(`should open initially when _open property is true`, async ({ page }) => {
+ await page.setContent('Drawer content
');
+ await expect(page.getByTestId('drawer-content')).toBeVisible();
+ });
+
+ test(`should open when _open property becomes true`, async ({ page }) => {
+ await page.setContent('Drawer content
');
+ const kolDrawer = page.locator('kol-drawer');
+ await kolDrawer.evaluate((element: HTMLKolDrawerElement) => {
+ element._open = true;
+ });
+ await expect(page.getByTestId('drawer-content')).toBeVisible();
+ });
+
+ test(`should close when _open property becomes false`, async ({ page }) => {
+ await page.setContent('Drawer content
');
+ const kolDrawer = page.locator('kol-drawer');
+ await kolDrawer.evaluate((element: HTMLKolDrawerElement) => {
+ element._open = false;
+ });
+ await expect(page.getByTestId('drawer-content')).not.toBeVisible();
+ });
+ });
+
+ test.describe('DOM events', () => {
+ test(`should emit 'close' when drawer is closed`, async ({ page }) => {
+ await page.setContent('Drawer content ');
+ const kolDrawer = page.locator('kol-drawer');
+
+ const eventPromise = kolDrawer.evaluate((element: HTMLKolDrawerElement, KolEvent) => {
+ element._open = true; // see #7165
+ return new Promise((resolve) => {
+ element.addEventListener(KolEvent.close, () => {
+ resolve();
+ });
+ });
+ }, KolEvent);
+ await page.waitForChanges();
+ await page.keyboard.press('Escape');
+
+ await expect(eventPromise).resolves.toBeUndefined();
+ });
+ });
+});
diff --git a/packages/components/src/components/drawer/shadow.tsx b/packages/components/src/components/drawer/shadow.tsx
new file mode 100644
index 0000000000..948e1e27dc
--- /dev/null
+++ b/packages/components/src/components/drawer/shadow.tsx
@@ -0,0 +1,191 @@
+/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+import type { AlignPropType, DrawerAPI, DrawerStates, KoliBriModalEventCallbacks, LabelPropType, OpenPropType } from '../../schema';
+import { setState, validateAlign, validateLabel, validateOpen } from '../../schema';
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+import clsx from 'clsx';
+
+/**
+ * @slot - The Content of drawer.
+ */
+@Component({
+ tag: 'kol-drawer',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolDrawer implements DrawerAPI {
+ @Element() private readonly host?: HTMLKolDetailsElement;
+ private dialogElement?: HTMLDialogElement;
+ private dialogWrapperElement?: HTMLDivElement;
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ async open() {
+ this.state = {
+ ...this.state,
+ _open: true,
+ };
+ this.dialogElement?.showModal();
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ async close() {
+ this.state = {
+ ...this.state,
+ _open: false,
+ };
+ const wrapper = this.dialogWrapperElement;
+ if (!wrapper) return;
+ const computedStyle = window.getComputedStyle(wrapper);
+ if (computedStyle.animationName === 'none') {
+ this.handleCloseDialog();
+ }
+ }
+
+ private getWrapperRef = (el: HTMLDivElement | undefined) => (this.dialogWrapperElement = el as HTMLDivElement);
+ private renderDialogContent() {
+ const align = this.state._align as string;
+ return (
+
+ );
+ }
+
+ private getRef = (el: HTMLDialogElement | undefined) => {
+ this.dialogElement = el as HTMLDialogElement;
+ setTimeout(() => {
+ void this.openOrCloseBasedOnState(); // handle initial state as soon as element is ready
+ });
+ };
+ public render(): JSX.Element {
+ return (
+
+
+ {this.renderDialogContent()}
+
+
+ );
+ }
+
+ /**
+ * Opens/expands the element when truthy, closes/collapses when falsy.
+ */
+ @Prop() public _open?: OpenPropType;
+
+ /**
+ * Defines the visual orientation of the component.
+ */
+ @Prop() public _align?: AlignPropType;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ /**
+ * Specifies the EventCallback function to be called when the drawer is closing.
+ */
+ @Prop() public _on?: KoliBriModalEventCallbacks;
+
+ @State() public state: DrawerStates = {
+ _label: '', // ⚠ required
+ _open: false,
+ _align: 'left',
+ };
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ @Watch('_align')
+ public validateAlign(value?: AlignPropType): void {
+ validateAlign(this, value);
+ }
+
+ @Watch('_open')
+ public validateOpen(value?: OpenPropType) {
+ if (typeof value === 'boolean') {
+ validateOpen(this, value);
+
+ if (this.dialogElement) {
+ // handle property changes but not the initial validateOpen call
+ void this.openOrCloseBasedOnState();
+ }
+ }
+ }
+
+ private async openOrCloseBasedOnState() {
+ if (this.state._open) {
+ await this.open();
+ } else {
+ await this.close();
+ }
+ }
+
+ @Watch('_on')
+ public validateOn(value?: KoliBriModalEventCallbacks): void {
+ if (typeof value === 'object' && value !== null) {
+ const callbacks: KoliBriModalEventCallbacks = {};
+ if (typeof value.onClose === 'function') {
+ callbacks.onClose = value.onClose;
+ }
+ setState(this, '_on', callbacks);
+ }
+ }
+
+ private handleCloseDialog() {
+ this.dialogElement?.close();
+ this._on?.onClose?.();
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.close);
+ }
+ }
+
+ private handleClose() {
+ void (async () => {
+ await this.close();
+ this.handleCloseDialog();
+ })();
+ }
+
+ private handleAnimationEnd(e: Event): void {
+ const animationEvent = e as AnimationEvent;
+ if (animationEvent.animationName.includes('slideOut')) {
+ this.handleCloseDialog();
+ }
+ }
+
+ public componentDidLoad(): void {
+ this.dialogElement?.addEventListener('animationend', this.handleAnimationEnd.bind(this));
+ this.dialogElement?.addEventListener('close', this.handleClose.bind(this));
+ }
+
+ public disconnectedCallback(): void {
+ this.dialogElement?.removeEventListener('animationend', this.handleAnimationEnd.bind(this));
+ this.dialogElement?.removeEventListener('close', this.handleClose.bind(this));
+ }
+
+ public componentWillLoad() {
+ this.validateLabel(this._label);
+ this.validateOpen(this._open);
+ this.validateAlign(this._align);
+ this.validateOn(this._on);
+ }
+}
diff --git a/packages/components/src/components/drawer/style.scss b/packages/components/src/components/drawer/style.scss
new file mode 100644
index 0000000000..d5935d8370
--- /dev/null
+++ b/packages/components/src/components/drawer/style.scss
@@ -0,0 +1,53 @@
+@import '../@shared/mixins';
+@import '../../styles/global';
+
+@layer kol-component {
+ .kol-drawer {
+ font-size: rem(16);
+
+ &__dialog {
+ padding: 0;
+ border: none;
+ }
+
+ &__wrapper {
+ position: fixed;
+ width: auto;
+ overflow: auto;
+ background-color: white;
+
+ &--left {
+ top: 0;
+ left: 0;
+ height: 100vh;
+ max-height: 100%;
+ }
+
+ &--right {
+ top: 0;
+ right: 0;
+ height: 100vh;
+ max-height: 100%;
+ }
+
+ &--top {
+ left: 0;
+ top: 0;
+ width: 100vw;
+ max-width: 100%;
+ }
+
+ &--bottom {
+ left: 0;
+ bottom: 0;
+ width: 100vw;
+ max-width: 100%;
+ }
+ }
+
+ &__content {
+ position: relative;
+ padding: rem(16);
+ }
+ }
+}
diff --git a/packages/components/src/components/drawer/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/drawer/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..f1bc8efbbe
--- /dev/null
+++ b/packages/components/src/components/drawer/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,85 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-drawer should render with _label="Label" _open=false 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`kol-drawer should render with _label="Label" _open=true _variant="bottom" 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`kol-drawer should render with _label="Label" _open=true _variant="left" 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`kol-drawer should render with _label="Label" _open=true _variant="right" 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`kol-drawer should render with _label="Label" _open=true _variant="top" 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`kol-drawer should render with _label="Label" 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/drawer/test/snapshot.spec.tsx b/packages/components/src/components/drawer/test/snapshot.spec.tsx
new file mode 100644
index 0000000000..1f4aec4b54
--- /dev/null
+++ b/packages/components/src/components/drawer/test/snapshot.spec.tsx
@@ -0,0 +1,19 @@
+import { KolDrawerTag } from '../../../core/component-names';
+import type { DrawerProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
+
+import { KolDrawer } from '../shadow';
+
+const variants = ['top', 'right', 'bottom', 'left'];
+
+const testCases: DrawerProps[] = [
+ ...variants.map((variant) => ({
+ _label: 'Label',
+ _open: true,
+ _variant: variant,
+ })),
+ { _label: 'Label' },
+ { _label: 'Label', _open: false },
+];
+
+executeSnapshotTests(KolDrawerTag, [KolDrawer], testCases);
diff --git a/packages/components/src/components/form/component.tsx b/packages/components/src/components/form/component.tsx
deleted file mode 100644
index 67df164bea..0000000000
--- a/packages/components/src/components/form/component.tsx
+++ /dev/null
@@ -1,145 +0,0 @@
-import type { JSX } from '@stencil/core';
-import { validateErrorList, watchBoolean, watchString } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch, Method } from '@stencil/core';
-
-import { translate } from '../../i18n';
-
-import type { ErrorListPropType, FormAPI, FormStates, KoliBriFormCallbacks, Stringified } from '@public-ui/schema';
-import { KolAlertTag, KolIndentedTextTag, KolLinkTag } from '../../core/component-names';
-/**
- * @slot - Inhalt der Form.
- */
-@Component({
- tag: 'kol-form',
- shadow: true,
-})
-export class KolForm implements FormAPI {
- errorListElement?: HTMLElement;
-
- /* Hint: This method may not be used at all while events are handled in form/controller#propagateSubmitEventToForm */
- private readonly onSubmit = (event: Event) => {
- event.preventDefault();
- event.stopPropagation();
- if (typeof this.state._on?.onSubmit === 'function') {
- this.state._on?.onSubmit(event as SubmitEvent);
- }
- };
-
- private readonly onReset = (event: Event) => {
- event.preventDefault();
- event.stopPropagation();
- if (typeof this.state._on?.onReset === 'function') {
- this.state._on?.onReset(event);
- }
- };
-
- private readonly handleLinkClick = (event: Event) => {
- const href = (event.target as HTMLAnchorElement | undefined)?.href;
- if (href) {
- const hrefUrl = new URL(href);
-
- const targetElement = document.querySelector(hrefUrl.hash);
- if (targetElement && typeof targetElement.focus === 'function') {
- targetElement.scrollIntoView({ behavior: 'smooth' });
- targetElement.focus();
- }
- }
- };
-
- public render(): JSX.Element {
- return (
-
- {this._errorList && this._errorList.length > 0 && (
-
- {translate('kol-error-list-message')}
-
-
- {this._errorList.map((error, index) => (
-
- {
- if (index === 0) this.errorListElement = el;
- }}
- />
-
- ))}
-
-
-
- )}
-
-
- );
- }
-
- @Method()
- async focusErrorList(): Promise {
- setTimeout(() => {
- if (this._errorList && this._errorList.length > 0) {
- this.errorListElement?.focus();
- }
- }, 300);
- return Promise.resolve();
- }
-
- /**
- * Gibt die EventCallback-Funktionen für die Form-Events an.
- */
- @Prop() public _on?: KoliBriFormCallbacks;
-
- /**
- * Defines whether the mandatory-fields-hint should be shown. A string overrides the default text.
- */
- @Prop() public _requiredText?: Stringified = true;
- /**
- * A list of error objects that each describe an issue encountered in the form.
- * Each error object contains a message and a selector for identifying the form element related to the error.
- */
- @Prop() public _errorList?: ErrorListPropType[];
-
- @State() public state: FormStates = {};
-
- @Watch('_on')
- public validateOn(value?: KoliBriFormCallbacks): void {
- if (typeof value === 'object' && value !== null) {
- this.state = {
- ...this.state,
- _on: value,
- };
- }
- }
-
- @Watch('_requiredText')
- public validateRequiredText(value?: Stringified): void {
- if (typeof value === 'boolean') {
- watchBoolean(this, '_requiredText', value);
- } else {
- watchString(this, '_requiredText', value);
- }
- }
-
- @Watch('_errorList')
- public validateErrorList(value?: ErrorListPropType[]): void {
- validateErrorList(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateOn(this._on);
- this.validateRequiredText(this._requiredText);
- this.validateErrorList(this._errorList);
- }
-}
diff --git a/packages/components/src/components/form/controller.ts b/packages/components/src/components/form/controller.ts
index cc04cc6f1f..f4c7c238ea 100644
--- a/packages/components/src/components/form/controller.ts
+++ b/packages/components/src/components/form/controller.ts
@@ -1,12 +1,14 @@
-import type { FormProps } from '@public-ui/schema';
-import { devHint, getExperimentalMode, KoliBriDevHelper, setEventTarget } from '@public-ui/schema';
+import type { FormProps } from '../../schema';
+import { Log } from '../../schema';
+import { devHint, getExperimentalMode, KoliBriDevHelper, setEventTarget } from '../../schema';
+import { KolFormTag } from '../../core/component-names';
const searchFormElement = (el?: HTMLElement | ParentNode | null): HTMLElement | ParentNode | null | undefined => {
if (getExperimentalMode()) {
devHint(`↓ Search form element start.`);
- console.log(el);
+ Log.debug(el);
}
- while (el instanceof HTMLElement && el.tagName !== 'FORM' && el.tagName !== 'KOL-FORM') {
+ while (el instanceof HTMLElement && el.tagName !== 'FORM' && el.tagName !== KolFormTag.toUpperCase()) {
try {
if (el.parentElement instanceof HTMLElement) {
el = el.parentElement;
@@ -23,7 +25,7 @@ const searchFormElement = (el?: HTMLElement | ParentNode | null): HTMLElement |
*/
}
if (getExperimentalMode()) {
- console.log(el);
+ Log.debug(el);
devHint(`↑ Search form element finished.`);
}
}
@@ -45,7 +47,7 @@ export const propagateResetEventToForm = (
if (form.tagName === 'FORM') {
setEventTarget(event, form);
form.dispatchEvent(event);
- } else if (form.tagName === 'KOL-FORM') {
+ } else if (form.tagName === KolFormTag.toUpperCase()) {
setEventTarget(event, KoliBriDevHelper.querySelector('form', form) as HTMLFormElement);
const kolForm = form as FormProps;
if (typeof kolForm._on?.onReset === 'function') {
@@ -95,7 +97,7 @@ export const propagateSubmitEventToForm = (
form.dispatchEvent(event);
}
});
- } else if (form.tagName === 'KOL-FORM') {
+ } else if (form.tagName === KolFormTag.toUpperCase()) {
setEventTarget(event, KoliBriDevHelper.querySelector('form', form) as HTMLFormElement);
const kolForm = form as FormProps;
// Use setTimeout to ensure onChange has been called first
diff --git a/packages/components/src/components/form/form.e2e.ts b/packages/components/src/components/form/form.e2e.ts
new file mode 100644
index 0000000000..698b5d9fbe
--- /dev/null
+++ b/packages/components/src/components/form/form.e2e.ts
@@ -0,0 +1,54 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import { KolEvent } from '../../utils/events';
+
+test.describe('kol-form', () => {
+ test.describe('Callbacks', () => {
+ const EVENTS: [string, string, unknown?][] = [
+ ['submit', 'onSubmit'],
+ ['reset', 'onReset'],
+ ];
+ EVENTS.forEach(([eventName, callbackName]) => {
+ test(`should call ${callbackName} callback when internal form emits`, async ({ page }) => {
+ await page.setContent(' ');
+ const kolForm = page.locator('kol-form');
+
+ const callbackPromise = kolForm.evaluate((element: HTMLKolFormElement, callbackName) => {
+ return new Promise((resolve) => {
+ element._on = {
+ [callbackName]: () => {
+ resolve();
+ },
+ };
+ });
+ }, callbackName);
+ await page.waitForChanges();
+
+ await page.locator('form').dispatchEvent(eventName);
+ await expect(callbackPromise).resolves.toBeUndefined();
+ });
+ });
+ });
+
+ test.describe('DOM events', () => {
+ const EVENTS: [string, KolEvent][] = [
+ ['submit', KolEvent.submit],
+ ['reset', KolEvent.reset],
+ ];
+ EVENTS.forEach(([nativeEvent, kolEvent]) => {
+ test(`should emit ${kolEvent} when internal form emits ${nativeEvent}`, async ({ page }) => {
+ await page.setContent(' ');
+ const eventPromise = page.locator('kol-form').evaluate(async (element: HTMLKolFormElement, kolEvent) => {
+ return new Promise((resolve) => {
+ element.addEventListener(kolEvent, () => {
+ resolve();
+ });
+ });
+ }, kolEvent);
+ await page.waitForChanges();
+ await page.locator('form').dispatchEvent(nativeEvent);
+ await expect(eventPromise).resolves.toBeUndefined();
+ });
+ });
+ });
+});
diff --git a/packages/components/src/components/form/readme.md b/packages/components/src/components/form/readme.md
deleted file mode 100644
index 0a1a9f018c..0000000000
--- a/packages/components/src/components/form/readme.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Form
-
-Die **Form**-Komponente dient dazu alle Eingabefelder zu umschließen, den Hinweistext für Pflichtfelder korrekt zu positionieren und die Events `submit` und `reset` weiterzuleiten.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
-
-```
-
-### Beispiel
-
-
-
-
-
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_errorList` | -- | A list of error objects that each describe an issue encountered in the form. Each error object contains a message and a selector for identifying the form element related to the error. | `ErrorListPropType[] \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für die Form-Events an. | `undefined \| { onSubmit?: EventCallback \| undefined; onReset?: EventCallback \| undefined; }` | `undefined` |
-| `_requiredText` | `_required-text` | Defines whether the mandatory-fields-hint should be shown. A string overrides the default text. | `boolean \| string \| undefined` | `true` |
-
-## Methods
-
-### `focusErrorList() => Promise`
-
-#### Returns
-
-Type: `Promise`
-
-## Slots
-
-| Slot | Description |
-| ---- | ---------------- |
-| | Inhalt der Form. |
-
----
diff --git a/packages/components/src/components/form/shadow.tsx b/packages/components/src/components/form/shadow.tsx
new file mode 100644
index 0000000000..b749b47956
--- /dev/null
+++ b/packages/components/src/components/form/shadow.tsx
@@ -0,0 +1,182 @@
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core';
+import { validateErrorList, watchBoolean, watchString } from '../../schema';
+
+import { translate } from '../../i18n';
+
+import { KolLinkWcTag } from '../../core/component-names';
+import KolAlertFc from '../../functional-components/Alert';
+import type { ErrorListPropType, FormAPI, FormStates, KoliBriFormCallbacks, Stringified } from '../../schema';
+import { dispatchDomEvent, KolEvent } from '../../utils/events';
+
+/**
+ * @slot - Inhalt der Form.
+ */
+@Component({
+ tag: 'kol-form',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolForm implements FormAPI {
+ @Element() private readonly host?: HTMLKolTextareaElement;
+ errorListBlock?: HTMLElement;
+ errorListFirstLink?: HTMLElement;
+
+ /* Hint: This method may not be used at all while events are handled in form/controller#propagateSubmitEventToForm */
+ private readonly onSubmit = (event: Event) => {
+ event.preventDefault();
+
+ if (typeof this.state._on?.onSubmit === 'function') {
+ this.state._on?.onSubmit(event as SubmitEvent);
+ }
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.submit);
+ }
+ };
+
+ private readonly onReset = (event: Event) => {
+ event.preventDefault();
+ if (typeof this.state._on?.onReset === 'function') {
+ this.state._on?.onReset(event);
+ }
+ if (this.host) {
+ dispatchDomEvent(this.host, KolEvent.reset);
+ }
+ };
+
+ private readonly handleLinkClick = (selector: string) => {
+ const targetElement = document.querySelector(selector);
+ if (targetElement && typeof targetElement.focus === 'function') {
+ targetElement.scrollIntoView({ behavior: 'smooth' });
+ targetElement.focus();
+ }
+ };
+
+ private renderErrorList(errorList?: ErrorListPropType[]): JSX.Element {
+ return (
+ {
+ this.errorListBlock = el;
+ }}
+ type="error"
+ variant="card"
+ label={translate('kol-error-list-message')}
+ >
+
+
+ {errorList?.map((error, index) => (
+
+ this.handleLinkClick(String(error.selector)) : error.selector }}
+ ref={(el) => {
+ if (index === 0) {
+ this.errorListFirstLink = el;
+ this.scrollToErrorList();
+ }
+ }}
+ />
+
+ ))}
+
+
+
+ );
+ }
+
+ private renderFormElement(): JSX.Element {
+ return (
+
+ );
+ }
+
+ public render(): JSX.Element {
+ const hasErrorList = Array.isArray(this._errorList) && this._errorList.length > 0;
+
+ return (
+
+ {hasErrorList && this.renderErrorList(this._errorList)}
+ {this.renderFormElement()}
+
+ );
+ }
+
+ private scrollToErrorList(): void {
+ this.errorListBlock?.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start',
+ });
+ setTimeout(() => {
+ this.errorListFirstLink?.querySelector('a')?.focus();
+ }, 250);
+ }
+
+ @Method()
+ async focusErrorList(): Promise {
+ this.scrollToErrorList();
+ return Promise.resolve();
+ }
+
+ /**
+ * Gibt die EventCallback-Funktionen für die Form-Events an.
+ */
+ @Prop() public _on?: KoliBriFormCallbacks;
+
+ /**
+ * Defines whether the mandatory-fields-hint should be shown. A string overrides the default text.
+ */
+ @Prop() public _requiredText?: Stringified = true;
+ /**
+ * A list of error objects that each describe an issue encountered in the form.
+ * Each error object contains a message and a selector for identifying the form element related to the error.
+ */
+ @Prop() public _errorList?: ErrorListPropType[];
+
+ @State() public state: FormStates = {};
+
+ @Watch('_on')
+ public validateOn(value?: KoliBriFormCallbacks): void {
+ if (typeof value === 'object' && value !== null) {
+ this.state = {
+ ...this.state,
+ _on: value,
+ };
+ }
+ }
+
+ @Watch('_requiredText')
+ public validateRequiredText(value?: Stringified): void {
+ if (typeof value === 'boolean') {
+ watchBoolean(this, '_requiredText', value);
+ } else {
+ watchString(this, '_requiredText', value);
+ }
+ }
+
+ @Watch('_errorList')
+ public validateErrorList(value?: ErrorListPropType[]): void {
+ validateErrorList(this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateOn(this._on);
+ this.validateRequiredText(this._requiredText);
+ this.validateErrorList(this._errorList);
+ }
+}
diff --git a/packages/components/src/components/form/style.scss b/packages/components/src/components/form/style.scss
new file mode 100644
index 0000000000..5593860642
--- /dev/null
+++ b/packages/components/src/components/form/style.scss
@@ -0,0 +1,14 @@
+@import '../@shared/mixins';
+@import '../../styles/global';
+@import '../host-display-block';
+@import '../@shared/kol-link-mixin';
+@import '../../styles/kol-alert-mixin';
+
+@layer kol-component {
+ @include kol-link-styles('kol-link');
+ @include kol-alert;
+
+ .kol-form {
+ font-size: rem(16);
+ }
+}
diff --git a/packages/components/src/components/form/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/form/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..6177e5b169
--- /dev/null
+++ b/packages/components/src/components/form/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-form should render with _requiredText="Pflichtfeld" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/form/test/html.mock.ts b/packages/components/src/components/form/test/html.mock.ts
deleted file mode 100644
index 1130cae757..0000000000
--- a/packages/components/src/components/form/test/html.mock.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { mixMembers } from 'stencil-awesome-test';
-
-import type { FormProps } from '@public-ui/schema';
-import { KolIndentedTextTag } from '../../../core/component-names';
-export const getFormHtml = (props: FormProps): string => {
- props = mixMembers({ ...props }, props);
- return `
-
-
-
- `;
-};
diff --git a/packages/components/src/components/form/test/snapshot.spec.tsx b/packages/components/src/components/form/test/snapshot.spec.tsx
index 6dadeef9a4..add8452881 100644
--- a/packages/components/src/components/form/test/snapshot.spec.tsx
+++ b/packages/components/src/components/form/test/snapshot.spec.tsx
@@ -1,28 +1,7 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolFormTag } from '../../../core/component-names';
+import type { FormProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolForm } from '../shadow';
-import { getFormHtml } from './html.mock';
-
-import type { FormProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
-import { KolForm } from '../component';
-
-executeTests(
- 'Form',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolForm],
- template: () => ,
- });
- return page;
- },
- {
- _requiredText: ['Pflichtfeld'],
- },
- getFormHtml,
- {
- execMode: 'skip',
- },
-);
+executeSnapshotTests(KolFormTag, [KolForm], [{ _requiredText: 'Pflichtfeld' }]);
diff --git a/packages/components/src/components/heading/component.tsx b/packages/components/src/components/heading/component.tsx
deleted file mode 100644
index e4cf26fac0..0000000000
--- a/packages/components/src/components/heading/component.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import type { HeadingAPI, HeadingLevel, HeadingStates, HeadingVariantPropType, LabelWithExpertSlotPropType } from '@public-ui/schema';
-import { validateHeadingVariant, validateLabelWithExpertSlot, watchString } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import { watchHeadingLevel } from './validation';
-
-import type { JSX } from '@stencil/core';
-/**
- * @slot - Inhalt der Überschrift.
- */
-@Component({
- tag: 'kol-heading-wc',
- shadow: false,
-})
-export class KolHeadingWc implements HeadingAPI {
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
- */
- @Prop() public _level?: HeadingLevel = 1;
-
- /**
- * Setzt den Text einer weiteren Überschrift, einen Level kleiner, unter der Ersten.
- */
- @Prop() public _secondaryHeadline?: string;
-
- /**
- * Defines which variant should be used for presentation.
- */
- @Prop() public _variant?: HeadingVariantPropType;
-
- @State() public state: HeadingStates = {
- _label: '', // ⚠ required
- _level: 1,
- };
-
- @Watch('_label')
- public validateLabel(value?: LabelWithExpertSlotPropType): void {
- validateLabelWithExpertSlot(this, value);
- }
-
- @Watch('_level')
- public validateLevel(value?: HeadingLevel): void {
- watchHeadingLevel(this, value);
- }
-
- @Watch('_secondaryHeadline')
- public validateSecondaryHeadline(value?: string): void {
- watchString(this, '_secondaryHeadline', value);
- }
-
- @Watch('_variant')
- public validateVariant(value?: HeadingVariantPropType): void {
- validateHeadingVariant(this, value);
- }
-
- public componentWillLoad(): void {
- this.validateLabel(this._label);
- this.validateLevel(this._level);
- this.validateSecondaryHeadline(this._secondaryHeadline);
- this.validateVariant(this._variant);
- }
-
- private readonly renderHeadline = (headline: LabelWithExpertSlotPropType, level?: number): JSX.Element => {
- const validHeadline = typeof level === 'number' && level > 0 && level <= 6;
- const HeadlineTag = validHeadline ? `h${level}` : 'strong';
- const variant = this._variant || HeadlineTag;
-
- return (
-
- {headline}
-
-
- );
- };
-
- private readonly renderSecondaryHeadline = (headline: string, level?: number): JSX.Element => {
- switch (level) {
- case 1: // if the headline is only strong
- return {headline} ;
- case 2: // if the headline is h1
- return {headline} ;
- case 3: // if the headline is h2
- return {headline} ;
- case 4: // if the headline is h3
- return {headline} ;
- case 5: // if the headline is h4
- return {headline} ;
- case 6: // if the headline is h5
- return {headline} ;
- default: // if the headline is h6
- return {headline} ;
- }
- };
-
- public render(): JSX.Element {
- return (
-
- {typeof this.state._secondaryHeadline === 'string' && this.state._secondaryHeadline.length > 0 ? (
-
- {this.renderHeadline(this.state._label, this.state._level)}
- {this.state._secondaryHeadline && this.renderSecondaryHeadline(this.state._secondaryHeadline, this.state._level + 1)}
-
- ) : (
- this.renderHeadline(this.state._label, this.state._level)
- )}
-
- );
- }
-}
diff --git a/packages/components/src/components/heading/readme.md b/packages/components/src/components/heading/readme.md
deleted file mode 100644
index 53e3fe231a..0000000000
--- a/packages/components/src/components/heading/readme.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Heading
-
-Die **Heading**-Komponente kann überall dort verwendet werden, wo eine Überschrift angezeigt werden soll. Durch die Verwendung der unterschiedlichen Größen, lassen sich Inhalte klar strukturieren und Seiten wirkungsvoll und abwechslungsreich präsentieren. Sie trennt Styling von Semantik und ermöglicht Flexibilität.
-
-## Konstruktion
-
-### Code
-
-```html
-
-
-
-
-
-
-```
-
-### Beispiel
-
-
-
-
-
-
-
-
-## Verwendung
-
-Die Überschriftenebene wird durch das Attribut **`_level`** übergeben. Möglich sind die Level **1** bis **6**
-
-### Best practices
-
-- Achten Sie bei der Verwendung von Headings auf die empfohlene Semantik für die Suchmaschinenoptimierung.
-- Setzen Sie Headings in verschiedenen Größen ein, um eine sinnvolle Struktur Ihrer Inhalte zu erzeugen.
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | ----------- |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_level` | `_level` | Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text. | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` |
-| `_secondaryHeadline` | `_secondary-headline` | Setzt den Text einer weiteren Überschrift, einen Level kleiner, unter der Ersten. | `string \| undefined` | `undefined` |
-| `_variant` | `_variant` | Defines which variant should be used for presentation. | `"h1" \| "h2" \| "h3" \| "h4" \| "h5" \| "h6" \| "strong" \| undefined` | `undefined` |
-
-## Slots
-
-| Slot | Description |
-| ---- | ----------------------- |
-| | Inhalt der Überschrift. |
-
----
diff --git a/packages/components/src/components/heading/shadow.tsx b/packages/components/src/components/heading/shadow.tsx
index a70f96e461..4dd1eea3f9 100644
--- a/packages/components/src/components/heading/shadow.tsx
+++ b/packages/components/src/components/heading/shadow.tsx
@@ -1,10 +1,13 @@
-import type { HeadingLevel, HeadingProps, HeadingVariantPropType, LabelWithExpertSlotPropType } from '@public-ui/schema';
+import { Component, h, Prop, State, Watch } from '@stencil/core';
import type { JSX } from '@stencil/core';
-import { Component, h, Prop } from '@stencil/core';
-import { KolHeadingWcTag } from '../../core/component-names';
+import type { HeadingAPI, HeadingLevel, HeadingStates, HeadingVariantPropType, LabelWithExpertSlotPropType } from '../../schema';
+import { validateHeadingVariant, validateLabelWithExpertSlot, watchString } from '../../schema';
+import { KolHeadingFc } from '../../functional-components';
+import { watchHeadingLevel } from './validation';
/**
- * @slot headline - Content of the headline.
+ *
+ * @slot - Inhalt der Überschrift.
*/
@Component({
tag: 'kol-heading',
@@ -13,15 +16,7 @@ import { KolHeadingWcTag } from '../../core/component-names';
},
shadow: true,
})
-export class KolHeading implements HeadingProps {
- public render(): JSX.Element {
- return (
-
-
-
- );
- }
-
+export class KolHeading implements HeadingAPI {
/**
* Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
*/
@@ -30,7 +25,7 @@ export class KolHeading implements HeadingProps {
/**
* Defines which H-level from 1-6 the heading has. 0 specifies no heading and is shown as bold text.
*/
- @Prop() public _level?: HeadingLevel;
+ @Prop() public _level?: HeadingLevel = 1;
/**
* Defines the text of the secondary headline.
@@ -41,4 +36,47 @@ export class KolHeading implements HeadingProps {
* Defines which variant should be used for presentation.
*/
@Prop() public _variant?: HeadingVariantPropType;
+
+ @State() public state: HeadingStates = {
+ _label: '', // ⚠ required
+ _level: 1,
+ };
+
+ @Watch('_label')
+ public validateLabel(value?: LabelWithExpertSlotPropType): void {
+ validateLabelWithExpertSlot(this, value);
+ }
+
+ @Watch('_level')
+ public validateLevel(value?: HeadingLevel): void {
+ watchHeadingLevel(this, value);
+ }
+
+ @Watch('_secondaryHeadline')
+ public validateSecondaryHeadline(value?: string): void {
+ watchString(this, '_secondaryHeadline', value);
+ }
+
+ @Watch('_variant')
+ public validateVariant(value?: HeadingVariantPropType): void {
+ validateHeadingVariant(this, value);
+ }
+
+ public componentWillLoad(): void {
+ this.validateLabel(this._label);
+ this.validateLevel(this._level);
+ this.validateSecondaryHeadline(this._secondaryHeadline);
+ this.validateVariant(this._variant);
+ }
+
+ public render(): JSX.Element {
+ const { _secondaryHeadline, _label, _level, _variant } = this.state;
+
+ return (
+
+ {_label}
+
+
+ );
+ }
}
diff --git a/packages/components/src/components/heading/style.scss b/packages/components/src/components/heading/style.scss
index 8817673840..e0f63d3e40 100644
--- a/packages/components/src/components/heading/style.scss
+++ b/packages/components/src/components/heading/style.scss
@@ -1 +1,8 @@
-@import '../style';
+@import '../@shared/mixins';
+@import '../../styles/global';
+
+@layer kol-component {
+ .kol-headline {
+ font-size: rem(16);
+ }
+}
diff --git a/packages/components/src/components/heading/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/heading/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..b2717f65a3
--- /dev/null
+++ b/packages/components/src/components/heading/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,166 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-heading should render with _label="Headline" _level=0 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=1 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=2 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=3 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=4 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=5 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _level=6 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h1" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h2" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h3" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h4" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h5" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="h6" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" _variant="strong" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
+
+exports[`kol-heading should render with _label="Headline" 1`] = `
+
+
+
+ Headline
+
+
+
+
+`;
diff --git a/packages/components/src/components/heading/test/html.mock.ts b/packages/components/src/components/heading/test/html.mock.ts
deleted file mode 100644
index 02b81c9ed3..0000000000
--- a/packages/components/src/components/heading/test/html.mock.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { HeadingProps, HeadingStates } from '@public-ui/schema';
-import { mixMembers } from 'stencil-awesome-test';
-
-export const getHeadingWcHtml = (
- props: HeadingProps,
- slots: {
- expert?: string;
- } = {},
- additionalAttrs = '',
-): string => {
- const state = mixMembers(
- {
- _label: '', // ⚠ required
- _level: 1,
- },
- props,
- );
- const tag = state._level === 0 ? 'strong' : `h${state._level || 1}`;
-
- return `
-
- <${tag} class="headline headline-${props._variant || tag}">
- ${state._label}
- ${slots.expert !== undefined ? slots.expert : ' '}
- ${tag}>
- `;
-};
-
-export const getHeadingHtml = (
- props: HeadingProps,
- slots: {
- expert?: string;
- } = {},
-): string => {
- return `
-
-
- ${getHeadingWcHtml(props, {}, ` class="kol-heading kol-heading-wc"`)}
-
- ${slots.expert !== undefined ? slots.expert : ''}
- `;
-};
diff --git a/packages/components/src/components/heading/test/snapshot.spec.tsx b/packages/components/src/components/heading/test/snapshot.spec.tsx
index 8a03e5ed13..282b2811ef 100644
--- a/packages/components/src/components/heading/test/snapshot.spec.tsx
+++ b/packages/components/src/components/heading/test/snapshot.spec.tsx
@@ -1,32 +1,15 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolHeadingTag } from '../../../core/component-names';
+import type { HeadingProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getHeadingHtml } from './html.mock';
-
-import type { HeadingProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
import { KolHeading } from '../shadow';
-import { KolHeadingWc } from '../component';
-executeTests(
- 'Heading',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolHeading, KolHeadingWc],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Headline'],
- _level: [1, 2, 3, 4, 5, 6],
- _variant: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong'],
- // _secondaryHeadline: ['Secondary Headline'],
- },
- getHeadingHtml,
- {
- execMode: 'default', // ready
- },
+executeSnapshotTests(
+ KolHeadingTag,
+ [KolHeading],
+ [
+ { _label: 'Headline' },
+ ...[0, 1, 2, 3, 4, 5, 6].map((_level) => ({ _label: 'Headline', _level }) as HeadingProps),
+ ...['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong'].map((_variant) => ({ _label: 'Headline', _variant }) as HeadingProps),
+ ],
);
diff --git a/packages/components/src/components/heading/validation.ts b/packages/components/src/components/heading/validation.ts
index 62a52baca1..9d8746d369 100644
--- a/packages/components/src/components/heading/validation.ts
+++ b/packages/components/src/components/heading/validation.ts
@@ -1,5 +1,5 @@
-import type { HeadingLevel } from '@public-ui/schema';
-import { headingLevelOptions, watchValidator } from '@public-ui/schema';
+import type { HeadingLevel } from '../../schema';
+import { headingLevelOptions, watchValidator } from '../../schema';
import type { Generic } from 'adopted-style-sheets';
diff --git a/packages/components/src/components/icon/component.tsx b/packages/components/src/components/icon/component.tsx
deleted file mode 100644
index 84857478c8..0000000000
--- a/packages/components/src/components/icon/component.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import type { IconAPI, IconStates, LabelPropType } from '@public-ui/schema';
-import { validateLabel, watchString } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
-
-import type { JSX } from '@stencil/core';
-/**
- * @part icon - Ermöglicht das Styling des inneren Icons.
- */
-@Component({
- tag: 'kol-icon',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolIcon implements IconAPI {
- public render(): JSX.Element {
- const ariaShow = this.state._label.length > 0;
- return (
-
-
-
- );
- }
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons!: string;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
- */
- @Prop() public _label!: LabelPropType;
-
- @State() public state: IconStates = {
- _icons: 'codicon codicon-home',
- _label: '', // ⚠ required
- };
-
- @Watch('_icons')
- public validateIcons(value?: string): void {
- watchString(this, '_icons', value, {
- required: true,
- });
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelPropType): void {
- validateLabel(this, value, {
- required: true,
- });
- }
-
- public componentWillLoad(): void {
- this.validateIcons(this._icons);
- this.validateLabel(this._label);
- }
-}
diff --git a/packages/components/src/components/icon/readme.md b/packages/components/src/components/icon/readme.md
deleted file mode 100644
index f6bc52ed89..0000000000
--- a/packages/components/src/components/icon/readme.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# Icon
-
-Mit Hilfe der **Icon**-Komponente können Icons aus eingebundenen Icon-Fonts an beliebigen Positionen dargestellt werden. Die Ausgabe des Icon kann über das Attribut **`_icon`** gesteuert werden und erfolgt durch das Attribut **`_label`** barrierefrei. Die Ausgabe erfolgt standardmäßig als _`inline`_-Element.
-
-Aktuell werden die Icons von unterstützt.
-
-Es ist wichtig, dass in der Rahmenseite (`index.html`) die CSS-Dateie(n) der Icon-Font(s) eingebunden ist/sind.
-
-## Konstruktion
-
-Die Komponente **Icon** wird über das HTML-Tag `kol-icon` erzeugt.
-
-### Code
-
-```html
-
-```
-
-### Beispiel
-
-
-
-### Icons
-
-Die Property `_icons` erwartet einen String mit den Klassennamen der zu zeigenden Icons (z.B.: `_icons="codicon codicon-home`).
-
-
-
-## Barrierefreiheit
-
-Wichtig ist bei Kontext-relevanten Grafiken, dass sie beschriftet werden.
-
--
-
-### Label
-
-Mittels der Property `_label` muss ein Kontext-relevantes Icon beschriftet werden.
-
-## Links und Referenzen
-
--
--
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ | -------- | ----------- |
-| `_icons` _(required)_ | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `string` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). | `string` | `undefined` |
-
-## Shadow Parts
-
-| Part | Description |
-| -------- | ----------------------------------------- |
-| `"icon"` | Ermöglicht das Styling des inneren Icons. |
-
----
diff --git a/packages/components/src/components/icon/shadow.tsx b/packages/components/src/components/icon/shadow.tsx
new file mode 100644
index 0000000000..97512aa7c4
--- /dev/null
+++ b/packages/components/src/components/icon/shadow.tsx
@@ -0,0 +1,72 @@
+import type { IconAPI, IconStates, LabelPropType } from '../../schema';
+import { validateLabel, watchString } from '../../schema';
+import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
+
+import type { JSX } from '@stencil/core';
+import clsx from 'clsx';
+/**
+ * @part icon - Ermöglicht das Styling des inneren Icons.
+ */
+@Component({
+ tag: 'kol-icon',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: true,
+})
+export class KolIcon implements IconAPI {
+ public render(): JSX.Element {
+ const ariaShow = this.state._label.length > 0;
+ return (
+
+
+
+ );
+ }
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons!: string;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.).
+ */
+ @Prop() public _label!: LabelPropType;
+
+ @State() public state: IconStates = {
+ _icons: 'codicon codicon-home',
+ _label: '', // ⚠ required
+ };
+
+ @Watch('_icons')
+ public validateIcons(value?: string): void {
+ watchString(this, '_icons', value, {
+ required: true,
+ });
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelPropType): void {
+ validateLabel(this, value, {
+ required: true,
+ });
+ }
+
+ public componentWillLoad(): void {
+ this.validateIcons(this._icons);
+ this.validateLabel(this._label);
+ }
+}
diff --git a/packages/components/src/components/icon/style.scss b/packages/components/src/components/icon/style.scss
index 9d8fae95e1..2132e954fa 100644
--- a/packages/components/src/components/icon/style.scss
+++ b/packages/components/src/components/icon/style.scss
@@ -1,24 +1,25 @@
+@import '../@shared/mixins';
@import '../../assets/codicons/codicon';
@layer kol-component {
+ /*
+ * Necessary to center icon
+ */
:host {
- color: inherit;
display: contents;
- height: 1em;
- line-height: inherit;
- width: 1em;
}
- :host > i {
- height: 1em;
- width: 1em;
- }
+ .kol-icon {
+ font-size: rem(16);
+ color: inherit;
+ line-height: inherit;
+ &__icon,
+ &__icon:before {
+ font-size: inherit !important;
+ }
- /*
- * The :important
is important, because we should always override the font icon style.
- */
- :host > i,
- :host > i:before {
- font-size: inherit !important;
+ &__icon:before {
+ line-height: normal;
+ }
}
}
diff --git a/packages/components/src/components/icon/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/icon/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..98191b8f7d
--- /dev/null
+++ b/packages/components/src/components/icon/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-icon should render with _label="Aria-Label" _icons="codicon codicon-home" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/icon/test/html.mock.ts b/packages/components/src/components/icon/test/html.mock.ts
deleted file mode 100644
index 379bb9c29c..0000000000
--- a/packages/components/src/components/icon/test/html.mock.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import type { IconProps, IconStates } from '@public-ui/schema';
-import { readFileSync } from 'fs';
-import { render } from 'mustache';
-import path from 'path';
-import pug from 'pug';
-import { mixMembers } from 'stencil-awesome-test';
-import { twig } from 'twig';
-
-const getState = (props: IconProps): IconStates =>
- mixMembers(
- {
- _icons: 'codicon codicon-home',
- _label: '',
- },
- props,
- );
-
-const getIconHtmlTwig = (props: IconProps, additionalAttrs = ''): string => {
- const state = getState(props);
- const context = { additionalAttrs, ...state, mode: 'csr' };
-
- return twig({ path: path.join(__dirname, 'icon.twig'), async: false }).render(context);
-};
-
-/* eslint-disable @typescript-eslint/no-unused-vars,@typescript-eslint/ban-ts-comment */
-// @ts-ignore
-const getIconHtmlMustache = (props: IconProps, additionalAttrs = ''): string => {
- const state = getState(props);
- const template = readFileSync(path.join(__dirname, 'icon.mustache'), { encoding: 'utf-8' });
-
- return render(template, {
- additionalAttrs,
- ...state,
- csrMode: true,
- ssrMode: false,
- });
-};
-
-// @ts-ignore
-const getIconHtmlPug = (props: IconProps, additionalAttrs = ''): string => {
- const compiledFunction = pug.compileFile(path.join(__dirname, 'icon.pug'));
- const state = getState(props);
-
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
- return compiledFunction({
- additionalAttrs,
- mode: 'csr',
- ...state,
- });
-};
-
-/* eslint-enable @typescript-eslint/no-unused-vars,@typescript-eslint/ban-ts-comment */
-
-export const getIconHtml = (props: IconProps, additionalAttrs = ` class="kol-icon" `): string => {
- return getIconHtmlTwig(props, additionalAttrs);
- // return getIconHtmlMustache(props, additionalAttrs);
- // return getIconHtmlPug(props, additionalAttrs);
-};
diff --git a/packages/components/src/components/icon/test/snapshot.spec.tsx b/packages/components/src/components/icon/test/snapshot.spec.tsx
index 608a241f8c..fc16993031 100644
--- a/packages/components/src/components/icon/test/snapshot.spec.tsx
+++ b/packages/components/src/components/icon/test/snapshot.spec.tsx
@@ -1,29 +1,7 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolIconTag } from '../../../core/component-names';
+import type { IconProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolIcon } from '../shadow';
-import { getIconHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { IconProps } from '@public-ui/schema';
-import { KolIcon } from '../component';
-
-executeTests(
- 'Icon',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolIcon],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Aria-Label'],
- _icons: ['codicon codicon-home'],
- },
- getIconHtml,
- {
- execMode: 'default', // ready
- },
-);
+executeSnapshotTests(KolIconTag, [KolIcon], [{ _label: 'Aria-Label', _icons: 'codicon codicon-home' }]);
diff --git a/packages/components/src/components/image/readme.md b/packages/components/src/components/image/readme.md
deleted file mode 100644
index d2baf42241..0000000000
--- a/packages/components/src/components/image/readme.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Image
-
-> Diese neue Komponente wird als ungetestet markiert, da der vollständige Barrierefreiheitstest noch aussteht. Der vollständige Test kann bei neuen Komponenten und Funktionalitäten auch erst nach einem abgeschlossenen Release erfolgen.
-
-Die **Image**-Komponente dient dazu, Bilder darzustellen.
-
-## Konstruktion
-
-Die Komponente **Image** wird über das HTML-Tag `` erzeugt.
-
-### Code
-
-```html
-
-
-
-```
-
-### Beispiele
-
-
-
-## Verwendung
-
-### Bilder in unterschiedlicher Auflösung und/oder Seitenverhältnis
-
-Mittels **`_srcset`** (und **`_sizes`**) können unterschiedliche Bilder für unterschiedliche Auflösungen und Pixeldichten (des Displays) hinterlegt werden, um auf großen Bildschirmen scharfe Bilder zu liefern und auf kleinen Monitoren nicht unnötig Bandbreite zu verbrauchen.
-Des Weiteren können mittels **`_srcset`** auch verschiedene Dateiformate angegeben werden, um für moderne Browser Bandbreite zu sparen, allerdings ältere Geräte weiterhin zu unterstützen.
-Auch bei Verwendung von **`_srcset`** sollte **`_src`** genutzt werden, da dies von den Browsern als letzte Option verwendet wird, sofern a) **`srcset`** nicht unterstützt wird, oder b) dort kein passendes Bild gefunden wurde.
-
-
-Für weitere Infos zu **`_srcset`** siehe [Links und Referenzen](#links-und-referenzen)
-
-### Ladeverhalten
-
-Das Attribut **`_loading`** ist optional. Gesetzt werden kann hier entweder `eager` oder `lazy`, sofern ungesetzt wird `lazy` verwendet.
-`eager` sorgt für ein Laden des Bildes direkt beim Betreten der Seite, bei `lazy` lädt der Browser das Bild erst, kurz bevor es sichtbar wird. In der Regel muss `eager` nicht gesetzt werden, setzen Sie es nur sofern Ladeverzögerungen auftreten, oder das Bild sich sicher im, bei Betreten der Seite, sichtbaren Bereich befindet. (z.B.: Logo im Header oder Hero)
-
-
-## Barrierefreiheit
-
-### Alternativtext
-
-Das Attribut **`_alt`** ist verpflichtend, kann jedoch bei rein dekorativen Bildern leer (`_alt=""`) gelassen werden.
-Diese Beschreibung wird von Screenreadern vorgelesen und von Browsern angezeigt, wenn das Bild nicht geladen werden kann/soll.
-
-## Links und Referenzen
-
-Ausführliche Erklärung zu `_srcset` und `_sizes`:
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| ------------------- | ---------- | ------------------------------------------------------------------------------ | -------------------------------- | ----------- |
-| `_alt` _(required)_ | `_alt` | Setzt den alternativen Text. | `string` | `undefined` |
-| `_loading` | `_loading` | Defines the loading mode for the image. | `"eager" \| "lazy" \| undefined` | `'lazy'` |
-| `_sizes` | `_sizes` | Defines the image sizes for different screen resolutions, supporting \_srcset. | `string \| undefined` | `undefined` |
-| `_src` _(required)_ | `_src` | Sets the image `src` attribute to the given string. | `string` | `undefined` |
-| `_srcset` | `_srcset` | Setzt eine Liste von Quell-URLs mit Breiten der Bilder. | `string \| undefined` | `undefined` |
-
----
diff --git a/packages/components/src/components/image/shadow.tsx b/packages/components/src/components/image/shadow.tsx
index adb7287a43..d52d695289 100644
--- a/packages/components/src/components/image/shadow.tsx
+++ b/packages/components/src/components/image/shadow.tsx
@@ -1,6 +1,6 @@
-import type { ImageAPI, ImageSourcePropType, ImageStates, Loading } from '@public-ui/schema';
-import { validateImageSource, validateLoading, watchString } from '@public-ui/schema';
-import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
+import type { ImageAPI, ImageSourcePropType, ImageStates, Loading } from '../../schema';
+import { validateImageSource, validateLoading, watchString } from '../../schema';
+import { Component, h, Prop, State, Watch } from '@stencil/core';
import type { JSX } from '@stencil/core';
@Component({
@@ -81,9 +81,14 @@ export class KolImage implements ImageAPI {
public render(): JSX.Element {
return (
-
-
-
+
);
}
}
diff --git a/packages/components/src/components/image/style.scss b/packages/components/src/components/image/style.scss
index ee4adecc0a..e0ec8f5377 100644
--- a/packages/components/src/components/image/style.scss
+++ b/packages/components/src/components/image/style.scss
@@ -1,8 +1,10 @@
+@import '../@shared/mixins';
+@import '../../styles/global';
+
@layer kol-component {
- :host {
+ .kol-image {
display: inline-block;
- }
- img {
+ font-size: rem(16);
max-height: 100%;
max-width: 100%;
}
diff --git a/packages/components/src/components/image/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/image/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..d80873e0c9
--- /dev/null
+++ b/packages/components/src/components/image/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,33 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-image should render with _alt="somedescription" _loading="eager" _src="https://some-url.tld/images/awesome.jpg" _sizes="(max-width: 710px) 120px, (max-width: 991px) 193px, 278px" _srcset="https://some-url.tld/images/awesome.avif" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-image should render with _alt="somedescription" _loading="eager" _src="https://some-url.tld/images/awesome.jpg" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-image should render with _alt="somedescription" _loading="lazy" _src="https://some-url.tld/images/awesome.jpg" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-image should render with _alt="somedescription" _src="something" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/image/test/html.mock.ts b/packages/components/src/components/image/test/html.mock.ts
deleted file mode 100644
index ea007376bf..0000000000
--- a/packages/components/src/components/image/test/html.mock.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { ImageProps, ImageStates } from '@public-ui/schema';
-import { mixMembers } from 'stencil-awesome-test';
-
-export const getImageHtml = (props: ImageProps, additionalAttrs = ''): string => {
- const state = mixMembers(
- {
- _alt: '', // ⚠ required
- _loading: 'lazy',
- _src: '', // ⚠ required
- _sizes: '',
- _srcset: '',
- },
- props,
- );
- const sizes = state._sizes ? ` sizes="${state._sizes}"` : '';
- const srcset = state._srcset ? ` srcset="${state._srcset}"` : '';
- return `
-
-
-
- `;
-};
diff --git a/packages/components/src/components/image/test/snapshot.spec.tsx b/packages/components/src/components/image/test/snapshot.spec.tsx
index 1d14689542..14b2506d0c 100644
--- a/packages/components/src/components/image/test/snapshot.spec.tsx
+++ b/packages/components/src/components/image/test/snapshot.spec.tsx
@@ -1,45 +1,22 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolImageTag } from '../../../core/component-names';
+import type { ImageProps } from '../../../schema';
+import { executeSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getImageHtml } from './html.mock';
-
-import type { ImageProps } from '@public-ui/schema';
-import type { SpecPage } from '@stencil/core/testing';
import { KolImage } from '../shadow';
-executeTests(
- 'Image',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolImage],
- template: () => ,
- });
- return page;
- },
- {
- _alt: ['somedescription'],
- _src: ['something'],
- },
- getImageHtml,
-);
-
-executeTests(
- 'Image',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolImage],
- template: () => ,
- });
- return page;
- },
- {
- _alt: ['somedescription'],
- _loading: ['eager'],
- _sizes: ['(max-width: 710px) 120px, (max-width: 991px) 193px, 278px'],
- _src: ['https://some-url.tld/images/awesome.jpg'],
- _srcset: ['https://some-url.tld/images/awesome.avif, https://some-url.tld/images/awesome.webp'],
- },
- getImageHtml,
+executeSnapshotTests(
+ KolImageTag,
+ [KolImage],
+ [
+ { _alt: 'somedescription', _src: 'something' },
+ { _alt: 'somedescription', _loading: 'lazy', _src: 'https://some-url.tld/images/awesome.jpg' },
+ { _alt: 'somedescription', _loading: 'eager', _src: 'https://some-url.tld/images/awesome.jpg' },
+ {
+ _alt: 'somedescription',
+ _loading: 'eager',
+ _src: 'https://some-url.tld/images/awesome.jpg',
+ _sizes: '(max-width: 710px) 120px, (max-width: 991px) 193px, 278px',
+ _srcset: 'https://some-url.tld/images/awesome.avif',
+ },
+ ],
);
diff --git a/packages/components/src/components/indented-text/component.tsx b/packages/components/src/components/indented-text/component.tsx
deleted file mode 100644
index 601df1cf6e..0000000000
--- a/packages/components/src/components/indented-text/component.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { IndentedTextAPI, IndentedTextStates } from '@public-ui/schema';
-import type { JSX } from '@stencil/core';
-import { Component, h, Host, State } from '@stencil/core';
-
-/**
- * @slot - Der Text.
- */
-@Component({
- tag: 'kol-indented-text',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolIndentedText implements IndentedTextAPI {
- @State() public state: IndentedTextStates = {};
-
- public render(): JSX.Element {
- return (
-
-
- {/* TODO: Für was wird dieses div benötigt? */}
-
-
-
- );
- }
-}
diff --git a/packages/components/src/components/indented-text/readme.md b/packages/components/src/components/indented-text/readme.md
deleted file mode 100644
index e456e44891..0000000000
--- a/packages/components/src/components/indented-text/readme.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# IndentedText
-
-Heben Sie einzelne Informationen auf Ihrer Webseite optisch mit der **IndentedText**-Komponente hervor. Die Komponente eignet sich nicht nur für besondere Abschnitte auf der Webseite, sondern auch beispielsweise für Zitate (für verlinkte Zitate kann auch die verwendet werden.).
-
-## Konstruktion
-
-### Code
-
-```html
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
- vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit
- amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
-
-```
-
-### Beispiel
-
-
- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing
- elitr, sed diam nonumy eirmod tempor invidunt.
-
-
-## Verwendung
-
-Die Komponente besitzt keine weiteren Attribute. Der hervorzuhebende Text wird zwischen das öffnende und das schließende Tag geschrieben.
-
-### Best practices
-
-- Verwenden Sie die **IndentedText**-Komponente, um ergänzende Informationen zu einem Hauptthema optisch hervorzuheben.
-- Vermeiden Sie, wichtige Informationen in der Komponente auszugeben, die eine Aktion der Nutzer:innen erfordern.
-- Vermeiden Sie, viele **IndentedText**-Komponenten auf einer Einzelseite zu integrieren, da hierdurch die Übersichtlichkeit sinkt.
-
-### Anwendungsfälle
-
-Verwenden Sie die **IndentedText**-Komponente, um Textpassagen oder Informationen optisch hervorzuheben.
-
-
-
-## Slots
-
-| Slot | Description |
-| ---- | ----------- |
-| | Der Text. |
-
----
diff --git a/packages/components/src/components/indented-text/style.scss b/packages/components/src/components/indented-text/style.scss
deleted file mode 100644
index da3de3a3af..0000000000
--- a/packages/components/src/components/indented-text/style.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-@import '../style';
-@import '../host-display-block';
-
-@layer kol-component {
- :host > div {
- border-left-style: solid;
- padding-left: 0.5em;
- }
-}
diff --git a/packages/components/src/components/indented-text/test/html.mock.ts b/packages/components/src/components/indented-text/test/html.mock.ts
deleted file mode 100644
index 7a31e43036..0000000000
--- a/packages/components/src/components/indented-text/test/html.mock.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { IndentedTextProps } from '@public-ui/schema';
-
-export const getIndentedTextHtml = (
- props: IndentedTextProps,
- slots: {
- default?: string;
- } = {},
-): string => {
- return `
-
-
- ${typeof slots.default === 'undefined' ? ' ' : slots.default}
-
-
- ${typeof slots.default === 'undefined' ? (Object.getOwnPropertyNames(props).length === 0 ? '' : ' ') : slots.default}
- `;
-};
diff --git a/packages/components/src/components/indented-text/test/snapshot.spec.tsx b/packages/components/src/components/indented-text/test/snapshot.spec.tsx
deleted file mode 100644
index 11ee515e5a..0000000000
--- a/packages/components/src/components/indented-text/test/snapshot.spec.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { executeTests } from 'stencil-awesome-test';
-
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getIndentedTextHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { IndentedTextProps } from '@public-ui/schema';
-import { KolIndentedText } from '../component';
-
-executeTests(
- 'Heading',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolIndentedText],
- template: () => ,
- });
- return page;
- },
- {},
- getIndentedTextHtml,
- {
- execMode: 'default', // ready
- },
-);
diff --git a/packages/components/src/components/input-adapter-leanup/associated.controller.ts b/packages/components/src/components/input-adapter-leanup/associated.controller.ts
index bd863bf2a8..72f42577ee 100644
--- a/packages/components/src/components/input-adapter-leanup/associated.controller.ts
+++ b/packages/components/src/components/input-adapter-leanup/associated.controller.ts
@@ -1,5 +1,5 @@
-import type { NamePropType, PropSyncValueBySelector, StencilUnknown, SyncValueBySelectorPropType } from '@public-ui/schema';
-import { devHint, devWarning, getExperimentalMode, validateName } from '@public-ui/schema';
+import type { NamePropType, PropSyncValueBySelector, StencilUnknown, SyncValueBySelectorPropType } from '../../schema';
+import { devHint, devWarning, getExperimentalMode, validateName } from '../../schema';
import type { Generic } from 'adopted-style-sheets';
@@ -16,6 +16,7 @@ type HTMLInputFileElement = HTMLInputElement & {
const isAssociatedTagName = (name?: string): boolean =>
name === 'KOL-BUTTON' ||
+ name === 'KOL-COMBOBOX' ||
name === 'KOL-INPUT-CHECKBOX' ||
name === 'KOL-INPUT-COLOR' ||
name === 'KOL-INPUT-DATE' ||
@@ -27,6 +28,7 @@ const isAssociatedTagName = (name?: string): boolean =>
name === 'KOL-INPUT-RANGE' ||
name === 'KOL-INPUT-TEXT' ||
name === 'KOL-SELECT' ||
+ name === 'KOL-SINGLE-SELECT' ||
name === 'KOL-TEXTAREA';
export class AssociatedInputController implements Watches {
@@ -44,7 +46,7 @@ export class AssociatedInputController implements Watches {
this.host = this.findHostWithShadowRoot(host);
this.type = type;
- if (this.experimentalMode && isAssociatedTagName(this.host?.tagName)) {
+ if (this.experimentalMode && isAssociatedTagName(this.host?.tagName) && component._name) {
this.host?.querySelectorAll('input,select,textarea').forEach((el) => {
this.host?.removeChild(el);
});
@@ -69,12 +71,13 @@ export class AssociatedInputController implements Watches {
case 'textarea':
this.formAssociated = document.createElement('textarea');
break;
- case 'checkbox': // Checkbox use default case
+ case 'checkbox': // Checkbox uses default case
+ case 'single-select': // SingleSelect uses default case
+ case 'combobox': // Combobox uses default case
default:
this.formAssociated = document.createElement('input');
this.formAssociated.setAttribute('type', 'hidden');
}
- this.formAssociated.setAttribute('aria-hidden', 'true');
this.formAssociated.setAttribute('data-form-associated', '');
this.formAssociated.setAttribute('hidden', '');
this.host?.appendChild(this.formAssociated);
@@ -169,6 +172,13 @@ export class AssociatedInputController implements Watches {
});
}
break;
+ case 'radio':
+ if (typeof strValue === 'string') {
+ associatedElement.setAttribute('value', strValue);
+ associatedElement.setAttribute('checked', '');
+ associatedElement.value = strValue;
+ }
+ break;
default:
if (typeof strValue === 'string') {
associatedElement.setAttribute('value', strValue);
@@ -191,7 +201,7 @@ export class AssociatedInputController implements Watches {
});
if (typeof value === 'undefined') {
devHint(
- `Ein Name am Eingabefeldern oder Schalter ist nicht zwingend erforderlich, kann aber für die Autocomplete-Funktion und für das statische Versenden des Eingabefeldes relevant sein.`,
+ `A name on input fields or switches is not strictly required, but it might be relevant for the autocomplete function and for the static submission of the input field.`,
);
}
}
diff --git a/packages/components/src/components/input-adapter-leanup/controller.ts b/packages/components/src/components/input-adapter-leanup/controller.ts
index f2af2f1437..04617f0122 100644
--- a/packages/components/src/components/input-adapter-leanup/controller.ts
+++ b/packages/components/src/components/input-adapter-leanup/controller.ts
@@ -1,10 +1,11 @@
import type { Generic } from 'adopted-style-sheets';
-import { validateTouched, watchBoolean } from '@public-ui/schema';
+import { validateTouched } from '../../schema';
import { AssociatedInputController } from './associated.controller';
import type { Props, Watches } from './types';
+
export class ControlledInputController extends AssociatedInputController implements Watches {
protected readonly component: Generic.Element.Component & Props;
@@ -13,17 +14,12 @@ export class ControlledInputController extends AssociatedInputController impleme
this.component = component;
}
- public validateAlert(value?: boolean): void {
- watchBoolean(this.component, '_alert', value);
- }
-
public validateTouched(value?: boolean): void {
validateTouched(this.component, value);
}
public componentWillLoad(): void {
super.componentWillLoad();
- this.validateAlert(this.component._alert);
this.validateTouched(this.component._touched);
}
}
diff --git a/packages/components/src/components/input-adapter-leanup/types.ts b/packages/components/src/components/input-adapter-leanup/types.ts
index c03f594cda..7778e663e0 100644
--- a/packages/components/src/components/input-adapter-leanup/types.ts
+++ b/packages/components/src/components/input-adapter-leanup/types.ts
@@ -2,7 +2,6 @@ import type { Generic } from 'adopted-style-sheets';
type RequiredProps = NonNullable;
type OptionalProps = {
- alert: boolean;
touched: boolean;
};
export type Props = Generic.Element.Members;
diff --git a/packages/components/src/components/input-checkbox/button.scss b/packages/components/src/components/input-checkbox/button.scss
deleted file mode 100644
index 3823fc5b7f..0000000000
--- a/packages/components/src/components/input-checkbox/button.scss
+++ /dev/null
@@ -1,37 +0,0 @@
-@layer kol-component {
- .button {
- display: grid;
- grid-template-columns: var(--a11y-min-size) auto;
- grid-template-areas: 'error error' 'input label' 'hint hint';
- }
- .button:focus-within {
- /* override global `[tabindex]:focus` style */
- cursor: inherit;
- outline-color: black;
- outline-style: solid;
- }
-
- .button > .error {
- grid-area: error;
- }
-
- .button > label {
- grid-area: label;
- }
-
- .button > .input {
- grid-area: input;
- }
-
- .button > .hint {
- grid-area: hint;
- }
-
- .button .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: var(--a11y-min-size);
- height: var(--a11y-min-size);
- }
-}
diff --git a/packages/components/src/components/input-checkbox/checkbox.scss b/packages/components/src/components/input-checkbox/checkbox.scss
deleted file mode 100644
index a5e4de8065..0000000000
--- a/packages/components/src/components/input-checkbox/checkbox.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-@layer kol-component {
- .default {
- & .checkbox-container {
- align-items: center;
- display: flex;
- height: var(--a11y-min-size);
- justify-content: center;
- position: relative;
- width: var(--a11y-min-size);
- }
-
- & .icon {
- display: block;
- inset: auto;
- position: absolute;
- z-index: 1;
- }
-
- &:not(.checked):not(.indeterminate) .icon::part(icon) {
- display: none;
- }
-
- & .checkbox-input-element {
- width: 22px;
- height: 22px;
- }
- }
-}
diff --git a/packages/components/src/components/input-checkbox/common.scss b/packages/components/src/components/input-checkbox/common.scss
deleted file mode 100644
index 7208d071f6..0000000000
--- a/packages/components/src/components/input-checkbox/common.scss
+++ /dev/null
@@ -1,73 +0,0 @@
-@layer kol-component {
- label {
- cursor: pointer;
- }
-
- .kol-input {
- align-items: center;
- display: grid;
- justify-items: left;
- }
-
- .kol-input.default,
- .kol-input.switch {
- grid-template-columns: auto 1fr;
- }
-
- .kol-input .input {
- align-items: center;
- display: grid;
- order: 1;
- }
-
- .kol-input .input div {
- display: inline-flex;
- }
-
- .kol-input .input input {
- margin: 0;
- }
-
- .kol-input label {
- order: 2;
- }
-
- .kol-input .hint,
- .kol-input.error > .kol-alert {
- grid-column: span 2;
- }
-
- .kol-input .kol-alert.error {
- order: 3;
- }
-
- .kol-input .hint {
- order: 4;
- }
-
- input {
- border-style: solid;
- border-width: 2px;
- line-height: 24px;
- }
-
- input[type='checkbox'] {
- appearance: none;
- background-color: #fff;
- cursor: pointer;
- transition: 0.5s;
- }
-
- input[type='checkbox']:before {
- content: '';
- cursor: pointer;
- }
-
- input[type='checkbox']:disabled:before {
- cursor: not-allowed;
- }
-
- .kol-input.required .tooltip-content .span-label::after {
- content: '*';
- }
-}
diff --git a/packages/components/src/components/input-checkbox/component.tsx b/packages/components/src/components/input-checkbox/component.tsx
deleted file mode 100644
index ec349b4db5..0000000000
--- a/packages/components/src/components/input-checkbox/component.tsx
+++ /dev/null
@@ -1,415 +0,0 @@
-import type {
- CheckedPropType,
- HideErrorPropType,
- IdPropType,
- IndeterminatePropType,
- InputCheckboxAPI,
- InputCheckboxIconsProp,
- InputCheckboxStates,
- InputCheckboxVariant,
- InputTypeOnDefault,
- LabelWithExpertSlotPropType,
- MsgPropType,
- NamePropType,
- StencilUnknown,
- Stringified,
- SyncValueBySelectorPropType,
- TooltipAlignPropType,
-} from '@public-ui/schema';
-import { propagateFocus, showExpertSlot } from '@public-ui/schema';
-import { Component, Element, Fragment, h, Host, Method, Prop, State, Watch } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { tryToDispatchKoliBriEvent } from '../../utils/events';
-import { getRenderStates } from '../input/controller';
-import { InternalUnderlinedAccessKey } from '../span/InternalUnderlinedAccessKey';
-import { InputCheckboxController } from './controller';
-
-import type { JSX } from '@stencil/core';
-import { KolIconTag, KolInputTag } from '../../core/component-names';
-
-/**
- * @slot expert - Die Beschriftung der Checkbox.
- */
-@Component({
- tag: 'kol-input-checkbox',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolInputCheckbox implements InputCheckboxAPI {
- @Element() private readonly host?: HTMLKolInputCheckboxElement;
- private ref?: HTMLInputElement;
-
- private readonly catchRef = (ref?: HTMLInputElement) => {
- this.ref = ref;
- propagateFocus(this.host, ref);
- };
-
- @Method()
- // eslint-disable-next-line @typescript-eslint/require-await
- public async getValue(): Promise {
- return this.ref?.checked;
- }
-
- public render(): JSX.Element {
- const { ariaDescribedBy } = getRenderStates(this.state);
- const hasExpertSlot = showExpertSlot(this.state._label);
-
- return (
-
-
-
- {hasExpertSlot ? (
-
- ) : typeof this.state._accessKey === 'string' ? (
- <>
- {' '}
-
- {this.state._accessKey}
-
- >
- ) : (
- {this.state._label}
- )}
-
-
-
- 0 ? ariaDescribedBy.join(' ') : undefined}
- aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
- checked={this.state._checked}
- disabled={this.state._disabled}
- id={this.state._id}
- indeterminate={this.state._indeterminate}
- name={this.state._name}
- required={this.state._required}
- tabIndex={this.state._tabIndex}
- type="checkbox"
- {...this.controller.onFacade}
- onInput={this.onInput}
- onChange={this.onChange}
- onClick={undefined} // onClick is not needed since onChange already triggers the correct event
- />
-
-
-
- );
- }
-
- private readonly controller: InputCheckboxController;
-
- /**
- * Defines which key combination can be used to trigger or focus the interactive element of the component.
- */
- @Prop() public _accessKey?: string;
-
- /**
- * Defines whether the screen-readers should read out the notification.
- */
- @Prop({ mutable: true, reflect: true }) public _alert?: boolean = true;
-
- /**
- * Defines whether the checkbox is checked or not. Can be read and written.
- * @TODO: Change type back to `CheckedPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _checked?: boolean = false;
-
- /**
- * Hides the error message but leaves it in the DOM for the input's aria-describedby.
- * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
-
- /**
- * Makes the element not focusable and ignore all events.
- * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the error message text.
- * @deprecated Will be removed in v3. Use `msg` instead.
- */
- @Prop() public _error?: string;
-
- /**
- * Hides the caption by default and displays the caption text with a tooltip when the
- * interactive element is focused or the mouse is over it.
- * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hideLabel?: boolean = false;
-
- /**
- * Defines the hint text.
- */
- @Prop() public _hint?: string = '';
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: Stringified;
-
- /**
- * Defines the internal ID of the primary component element.
- */
- @Prop() public _id?: IdPropType;
-
- /**
- * Puts the checkbox in the indeterminate state, does not change the value of _checked.
- * @TODO: Change type back to `IndeterminatePropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _indeterminate?: boolean;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines the properties for a message rendered as Alert component.
- */
- @Prop() public _msg?: MsgPropType;
-
- /**
- * Defines the technical name of an input field.
- */
- @Prop() public _name?: NamePropType;
-
- /**
- * Gibt die EventCallback-Funktionen für das Input-Event an.
- */
- @Prop() public _on?: InputTypeOnDefault;
-
- /**
- * Makes the input element required.
- * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _required?: boolean = false;
-
- /**
- * Selector for synchronizing the value with another input element.
- * @internal
- */
- @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
-
- /**
- * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
- */
- @Prop() public _tabIndex?: number;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Shows if the input was touched by a user.
- * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
-
- /**
- * Defines the value of the input.
- */
- @Prop() public _value?: Stringified = true;
-
- /**
- * Defines which variant should be used for presentation.
- */
- @Prop() public _variant?: InputCheckboxVariant = 'default';
-
- @State() public state: InputCheckboxStates = {
- _checked: false,
- _hideError: false,
- _icons: {
- checked: 'codicon codicon-check',
- indeterminate: 'codicon codicon-remove',
- unchecked: 'codicon codicon-close',
- },
- _id: `id-${nonce()}`,
- _indeterminate: false,
- _label: '', // ⚠ required
- _value: true,
- _variant: 'default',
- };
-
- public constructor() {
- this.controller = new InputCheckboxController(this, 'checkbox', this.host);
- }
-
- @Watch('_accessKey')
- public validateAccessKey(value?: string): void {
- this.controller.validateAccessKey(value);
- }
-
- @Watch('_alert')
- public validateAlert(value?: boolean): void {
- this.controller.validateAlert(value);
- }
-
- @Watch('_checked')
- public validateChecked(value?: CheckedPropType): void {
- this.controller.validateChecked(value);
- }
-
- @Watch('_disabled')
- public validateDisabled(value?: boolean): void {
- this.controller.validateDisabled(value);
- }
-
- @Watch('_error')
- public validateError(value?: string): void {
- this.controller.validateError(value);
- }
-
- @Watch('_hideError')
- public validateHideError(value?: HideErrorPropType): void {
- this.controller.validateHideError(value);
- }
-
- @Watch('_hideLabel')
- public validateHideLabel(value?: boolean): void {
- this.controller.validateHideLabel(value);
- }
-
- @Watch('_hint')
- public validateHint(value?: string): void {
- this.controller.validateHint(value);
- }
-
- @Watch('_icons')
- public validateIcons(value?: Stringified): void {
- this.controller.validateIcons(value);
- }
-
- @Watch('_id')
- public validateId(value?: string): void {
- this.controller.validateId(value);
- }
-
- @Watch('_indeterminate')
- public validateIndeterminate(value?: IndeterminatePropType): void {
- this.controller.validateIndeterminate(value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelWithExpertSlotPropType): void {
- this.controller.validateLabel(value);
- }
-
- @Watch('_msg')
- public validateMsg(value?: MsgPropType): void {
- this.controller.validateMsg(value);
- }
-
- @Watch('_name')
- public validateName(value?: string): void {
- this.controller.validateName(value);
- }
-
- @Watch('_on')
- public validateOn(value?: InputTypeOnDefault): void {
- this.controller.validateOn(value);
- }
-
- @Watch('_required')
- public validateRequired(value?: boolean): void {
- this.controller.validateRequired(value);
- }
-
- @Watch('_syncValueBySelector')
- public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
- this.controller.validateSyncValueBySelector(value);
- }
-
- @Watch('_tabIndex')
- public validateTabIndex(value?: number): void {
- this.controller.validateTabIndex(value);
- }
-
- @Watch('_touched')
- public validateTouched(value?: boolean): void {
- this.controller.validateTouched(value);
- }
-
- @Watch('_value')
- public validateValue(value?: Stringified): void {
- this.controller.validateValue(value);
- }
-
- @Watch('_variant')
- public validateVariant(value?: InputCheckboxVariant): void {
- this.controller.validateVariant(value);
- }
-
- public componentWillLoad(): void {
- this._alert = this._alert === true;
- this._touched = this._touched === true;
- this.controller.componentWillLoad();
- }
-
- private onInput = (event: Event): void => {
- this._checked = !this._checked;
- this._indeterminate = false;
-
- const value = this._checked ? this.state._value : null;
-
- // Event handling
- tryToDispatchKoliBriEvent('input', this.host, value);
-
- // Callback
- if (typeof this._on?.onInput === 'function') {
- this._on.onInput(event, value);
- }
- };
-
- private onChange = (event: Event): void => {
- const value = this._checked ? this.state._value : null;
-
- // Event handling
- // stopPropagation(event);
- tryToDispatchKoliBriEvent('change', this.host, value);
-
- // Static form handling
- // this.controller.setFormAssociatedValue(value);
- this.controller.setFormAssociatedCheckboxValue(value);
-
- // Callback
- if (typeof this._on?.onChange === 'function') {
- this._on.onChange(event, value);
- }
- };
-}
diff --git a/packages/components/src/components/input-checkbox/controller.ts b/packages/components/src/components/input-checkbox/controller.ts
index c94c3b1708..97d398eb1f 100644
--- a/packages/components/src/components/input-checkbox/controller.ts
+++ b/packages/components/src/components/input-checkbox/controller.ts
@@ -6,10 +6,11 @@ import type {
InputCheckboxProps,
InputCheckboxVariant,
InputCheckboxWatches,
+ LabelAlignPropType,
StencilUnknown,
Stringified,
-} from '@public-ui/schema';
-import { inputCheckboxVariantOptions, isString, setState, validateChecked, validateIndeterminate, watchValidator } from '@public-ui/schema';
+} from '../../schema';
+import { inputCheckboxVariantOptions, isString, setState, validateChecked, validateIndeterminate, validateLabelAlign, watchValidator } from '../../schema';
import { InputCheckboxRadioController } from '../input-radio/controller';
@@ -61,6 +62,10 @@ export class InputCheckboxController extends InputCheckboxRadioController implem
validateIndeterminate(this.component, value);
}
+ public validateLabelAlign(value?: LabelAlignPropType): void {
+ validateLabelAlign(this.component, value);
+ }
+
public validateValue(value?: Stringified): void {
setState(this.component, '_value', value);
this.setFormAssociatedCheckboxValue(this.component.state._value as StencilUnknown);
@@ -83,5 +88,6 @@ export class InputCheckboxController extends InputCheckboxRadioController implem
this.validateIndeterminate(this.component._indeterminate);
this.validateValue(this.component._value);
this.validateVariant(this.component._variant);
+ this.validateLabelAlign(this.component._labelAlign);
}
}
diff --git a/packages/components/src/components/input-checkbox/input-checkbox.e2e.ts b/packages/components/src/components/input-checkbox/input-checkbox.e2e.ts
new file mode 100644
index 0000000000..77e3b92735
--- /dev/null
+++ b/packages/components/src/components/input-checkbox/input-checkbox.e2e.ts
@@ -0,0 +1,24 @@
+import { test } from '@stencil/playwright';
+import { testInputCallbacksAndEvents } from '../../e2e';
+import type { FillAction } from '../../e2e/utils/FillAction';
+import { expect } from '@playwright/test';
+
+const COMPONENT_NAME = 'kol-input-checkbox';
+const TEST_VALUE = true;
+const fillAction: FillAction = async (page) => {
+ await page.locator('input').check();
+};
+const OMITTED_EVENTS = ['click'];
+
+test.describe(COMPONENT_NAME, () => {
+ testInputCallbacksAndEvents(COMPONENT_NAME, TEST_VALUE, fillAction, OMITTED_EVENTS);
+
+ test(`should reflect the _checked property on the web component`, async ({ page }) => {
+ const getCheckedProperty = () => page.locator(COMPONENT_NAME).evaluate((element: HTMLKolInputCheckboxElement) => element._checked);
+ await page.setContent(` `);
+
+ expect(await getCheckedProperty()).toBe(false);
+ await fillAction(page);
+ expect(await getCheckedProperty()).toBe(true);
+ });
+});
diff --git a/packages/components/src/components/input-checkbox/readme.md b/packages/components/src/components/input-checkbox/readme.md
deleted file mode 100644
index 2f3ae09976..0000000000
--- a/packages/components/src/components/input-checkbox/readme.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Checkbox
-
-Der Input-Typ **_Checkbox_** generiert eine rechteckige Box, die durch Anklicken aktiviert und wieder deaktiviert wird. In aktiviertem Zustand befindet sich ein farbiger Haken in der Box.
-
-## Konstruktion
-
-### Code
-
-```html
-Ich stimme der zu.
-
-
-
-```
-
-### Beispiel
-
-Ich stimme der zu.
-
-
-
-
-## Verwendung
-
-Checkboxen werden als Einzelelement oder als Liste beliebig vieler Checkboxen verwendet. Sie ermöglichen den Nutzer:innen, aus einer vordefinierten Anzahl von Möglichkeiten eine oder mehrere auszuwählen.
-
-### Varianten
-
-Mittels des Attributs **`_variant`** können folgende Varianten ausgewählt werden (Beispiele siehe oben):
-
-- `button`: wechselt das Icon je nach Zustand (Beispiel 3+4)
-- `switch`: verwandelt die Checkbox in einen horizontalen Schalter, hierbei gilt rechts als aktiv und links als inaktiv. (Beispiel 2)
-
-### Best practices
-
-- Verwenden Sie eine einzelne Checkbox, wenn Sie von den Nutzer:innen eine einfach Bestätigung wünschen, z.B. Akzeptieren der Datenschutzerklärung.
-- Verwenden Sie eine Gruppe von Checkboxen, um den Nutzer:innen die Möglichkeit zu geben einen oder mehrere Werte auszuwählen.
-
-## Barrierefreiheit
-
-Vermeiden Sie die Verwendung von vielen Checkboxen auf einer Seite, da Ihre Inhalte hierdurch schnell unübersichtlich und lang werden. Prüfen Sie in solchen Anwendungsfällen die Verwendung einer Select-Box mit **`_multiple`** .
-
-Achten Sie darauf, jeder Checkbox ein Label zuzuweisen, da dieses von Screenreadern vorgelesen wird und so eine eindeutige Identifikation des Eingabefeldes ermöglicht.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------ | ------------------------------------------------------------------------------------------------------------------ |
-| `Tab` | Fokussiert die Checkbox bzw. ermöglicht den Wechsel zwischen Checkboxen einer Liste. |
-| `Leer` | Aktiviert bzw. deaktiviert die Checkbox. Der Zustand **_Indeterminate_** ist über die Tastatur nicht herzustellen. |
-
-## Links und Referenzen
-
--
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_accessKey` | `_access-key` | Defines which key combination can be used to trigger or focus the interactive element of the component. | `string \| undefined` | `undefined` |
-| `_alert` | `_alert` | Defines whether the screen-readers should read out the notification. | `boolean \| undefined` | `true` |
-| `_checked` | `_checked` | Defines whether the checkbox is checked or not. Can be read and written. | `boolean \| undefined` | `false` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_error` | `_error` | **[DEPRECATED]** Will be removed in v3. Use `msg` instead. Defines the error message text. | `string \| undefined` | `undefined` |
-| `_hideError` | `_hide-error` | Hides the error message but leaves it in the DOM for the input's aria-describedby. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_hint` | `_hint` | Defines the hint text. | `string \| undefined` | `''` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `string \| undefined \| { checked: string; indeterminate?: string \| undefined; unchecked?: string \| undefined; } \| { checked?: string \| undefined; indeterminate: string; unchecked?: string \| undefined; } \| { checked?: string \| undefined; indeterminate?: string \| undefined; unchecked: string; }` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_indeterminate` | `_indeterminate` | Puts the checkbox in the indeterminate state, does not change the value of \_checked. | `boolean \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_msg` | -- | Defines the properties for a message rendered as Alert component. | `undefined \| {} & { _level?: 0 \| 2 \| 1 \| 3 \| 4 \| 5 \| 6 \| undefined; _on?: KoliBriAlertEventCallbacks \| undefined; _type?: "error" \| "warning" \| "info" \| "success" \| "default" \| undefined; _variant?: "card" \| "msg" \| undefined; _label?: string \| undefined; _alert?: boolean \| undefined; _hasCloser?: boolean \| undefined; } & { _description: string; }` | `undefined` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für das Input-Event an. | `InputTypeOnBlur & InputTypeOnClick & InputTypeOnChange & InputTypeOnFocus & InputTypeOnInput \| undefined` | `undefined` |
-| `_required` | `_required` | Makes the input element required. | `boolean \| undefined` | `false` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_touched` | `_touched` | Shows if the input was touched by a user. | `boolean \| undefined` | `false` |
-| `_value` | `_value` | Defines the value of the input. | `boolean \| null \| number \| object \| string \| undefined` | `true` |
-| `_variant` | `_variant` | Defines which variant should be used for presentation. | `"button" \| "default" \| "switch" \| undefined` | `'default'` |
-
-## Methods
-
-### `getValue() => Promise`
-
-#### Returns
-
-Type: `Promise`
-
-## Slots
-
-| Slot | Description |
-| ---------- | ------------------------------ |
-| `"expert"` | Die Beschriftung der Checkbox. |
-
----
diff --git a/packages/components/src/components/input-checkbox/shadow.tsx b/packages/components/src/components/input-checkbox/shadow.tsx
new file mode 100644
index 0000000000..a96429d08f
--- /dev/null
+++ b/packages/components/src/components/input-checkbox/shadow.tsx
@@ -0,0 +1,408 @@
+/* eslint-disable jsx-a11y/label-has-associated-control */
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
+import clsx from 'clsx';
+
+import type {
+ CheckedPropType,
+ FocusableElement,
+ HideErrorPropType,
+ IdPropType,
+ IndeterminatePropType,
+ InputCheckboxAPI,
+ InputCheckboxIconsProp,
+ InputCheckboxStates,
+ InputCheckboxVariant,
+ InputTypeOnDefault,
+ LabelAlignPropType,
+ LabelWithExpertSlotPropType,
+ MsgPropType,
+ NamePropType,
+ ShortKeyPropType,
+ StencilUnknown,
+ Stringified,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+} from '../../schema';
+
+import { nonce } from '../../utils/dev.utils';
+import { InputCheckboxController } from './controller';
+
+import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper';
+import KolFieldControlStateWrapperFc, { type FieldControlStateWrapperProps } from '../../functional-component-wrappers/FieldControlStateWrapper';
+import KolCheckboxStateWrapperFc, { type CheckboxStateWrapperProps } from '../../functional-component-wrappers/CheckboxStateWrapper';
+
+/**
+ * @slot expert - Checkbox description.
+ */
+@Component({
+ tag: 'kol-input-checkbox',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: {
+ delegatesFocus: true,
+ },
+})
+export class KolInputCheckbox implements InputCheckboxAPI, FocusableElement {
+ @Element() private readonly host?: HTMLKolInputCheckboxElement;
+ private inputRef?: HTMLInputElement;
+
+ private readonly catchRef = (ref?: HTMLInputElement) => {
+ this.inputRef = ref;
+ };
+
+ private getModelValue(): StencilUnknown {
+ return this._checked ? this.state._value : null;
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async getValue(): Promise {
+ return this.getModelValue();
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ this.inputRef?.focus();
+ }
+
+ private getFormFieldProps(): FormFieldStateWrapperProps {
+ return {
+ state: this.state,
+ class: clsx('kol-input-checkbox', {
+ [`kol-input-checkbox--checked`]: this.state._checked,
+ [`kol-input-checkbox--indeterminate`]: this.state._indeterminate,
+ [`kol-input-checkbox--variant-${this.state._variant || 'default'}`]: true,
+ [`kol-input-checkbox--label-align-${this.state._labelAlign || 'right'}`]: true,
+ }),
+ tooltipAlign: this._tooltipAlign,
+ 'data-role': this.state._variant === 'button' ? 'button' : undefined,
+ alert: this.showAsAlert(),
+ renderNoTooltip: true,
+ };
+ }
+
+ private getFieldControlProps(): FieldControlStateWrapperProps {
+ return {
+ class: clsx('kol-input-checkbox__field-control', {
+ [`kol-input-checkbox__field-control--checked`]: this.state._checked,
+ [`kol-input-checkbox__field-control--indeterminate`]: this.state._indeterminate,
+ [`kol-input-checkbox__field-control--variant-${this.state._variant || 'default'}`]: true,
+ }),
+ state: this.state,
+ };
+ }
+
+ private getInputProps(): CheckboxStateWrapperProps {
+ return {
+ state: this.state,
+ icon: this.getIcon(),
+ inputProps: {
+ class: clsx({
+ 'visually-hidden': this.state._variant === 'button',
+ }),
+ ref: this.catchRef,
+ ...this.controller.onFacade,
+ onInput: this.onInput,
+ onChange: this.onChange,
+ onFocus: (event: Event) => {
+ this.controller.onFacade.onFocus(event);
+ this.inputHasFocus = true;
+ },
+ onBlur: (event: Event) => {
+ this.controller.onFacade.onBlur(event);
+ this.inputHasFocus = false;
+ },
+ onClick: undefined, // onClick is not needed since onChange already triggers the correct event
+ },
+ };
+ }
+
+ private getIcon(): string {
+ if (this.state._indeterminate) return this.state._icons.indeterminate;
+ if (this.state._checked) return this.state._icons.checked;
+ return this.state._icons.unchecked;
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+ );
+ }
+
+ private readonly controller: InputCheckboxController;
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: string;
+
+ /**
+ * Defines whether the checkbox is checked or not. Can be read and written.
+ * @TODO: Change type back to `CheckedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _checked?: boolean = false;
+
+ /**
+ * Hides the error message but leaves it in the DOM for the input's aria-describedby.
+ * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the hint text.
+ */
+ @Prop() public _hint?: string = '';
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: Stringified;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: IdPropType;
+
+ /**
+ * Puts the checkbox in the indeterminate state, does not change the value of _checked.
+ * @TODO: Change type back to `IndeterminatePropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _indeterminate?: boolean;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines which alignment should be used for presentation.
+ */
+ @Prop() public _labelAlign?: LabelAlignPropType = 'right';
+
+ /**
+ * Defines the properties for a message rendered as Alert component.
+ */
+ @Prop() public _msg?: Stringified;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: NamePropType;
+
+ /**
+ * Gibt die EventCallback-Funktionen für das Input-Event an.
+ */
+ @Prop() public _on?: InputTypeOnDefault;
+
+ /**
+ * Makes the input element required.
+ * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _required?: boolean = false;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Shows if the input was touched by a user.
+ * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
+
+ /**
+ * Defines the value of the input.
+ */
+ @Prop() public _value?: Stringified = true;
+
+ /**
+ * Defines which variant should be used for presentation.
+ */
+ @Prop() public _variant?: InputCheckboxVariant = 'default';
+
+ @State() public state: InputCheckboxStates = {
+ _checked: false,
+ _hideError: false,
+ _icons: {
+ checked: 'codicon codicon-check',
+ indeterminate: 'codicon codicon-remove',
+ unchecked: 'codicon codicon-close',
+ },
+ _id: `id-${nonce()}`,
+ _indeterminate: false,
+ _label: '', // ⚠ required
+ _value: true,
+ _variant: 'default',
+ _labelAlign: 'right',
+ };
+
+ @State() private inputHasFocus = false;
+
+ public constructor() {
+ this.controller = new InputCheckboxController(this, 'checkbox', this.host);
+ }
+
+ private showAsAlert(): boolean {
+ return Boolean(this.state._touched) && !this.inputHasFocus;
+ }
+
+ @Watch('_accessKey')
+ public validateAccessKey(value?: string): void {
+ this.controller.validateAccessKey(value);
+ }
+
+ @Watch('_checked')
+ public validateChecked(value?: CheckedPropType): void {
+ this.controller.validateChecked(value);
+ }
+
+ @Watch('_disabled')
+ public validateDisabled(value?: boolean): void {
+ this.controller.validateDisabled(value);
+ }
+
+ @Watch('_hideError')
+ public validateHideError(value?: HideErrorPropType): void {
+ this.controller.validateHideError(value);
+ }
+
+ @Watch('_hideLabel')
+ public validateHideLabel(value?: boolean): void {
+ this.controller.validateHideLabel(value);
+ }
+
+ @Watch('_hint')
+ public validateHint(value?: string): void {
+ this.controller.validateHint(value);
+ }
+
+ @Watch('_icons')
+ public validateIcons(value?: Stringified): void {
+ this.controller.validateIcons(value);
+ }
+
+ @Watch('_id')
+ public validateId(value?: string): void {
+ this.controller.validateId(value);
+ }
+
+ @Watch('_indeterminate')
+ public validateIndeterminate(value?: IndeterminatePropType): void {
+ this.controller.validateIndeterminate(value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelWithExpertSlotPropType): void {
+ this.controller.validateLabel(value);
+ }
+
+ @Watch('_labelAlign')
+ public validateLabelAlign(value?: LabelAlignPropType): void {
+ this.controller.validateLabelAlign(value);
+ }
+
+ @Watch('_msg')
+ public validateMsg(value?: Stringified): void {
+ this.controller.validateMsg(value);
+ }
+
+ @Watch('_name')
+ public validateName(value?: string): void {
+ this.controller.validateName(value);
+ }
+
+ @Watch('_on')
+ public validateOn(value?: InputTypeOnDefault): void {
+ this.controller.validateOn(value);
+ }
+
+ @Watch('_required')
+ public validateRequired(value?: boolean): void {
+ this.controller.validateRequired(value);
+ }
+
+ @Watch('_shortKey')
+ public validateShortKey(value?: ShortKeyPropType): void {
+ this.controller.validateShortKey(value);
+ }
+
+ @Watch('_syncValueBySelector')
+ public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
+ this.controller.validateSyncValueBySelector(value);
+ }
+
+ @Watch('_tabIndex')
+ public validateTabIndex(value?: number): void {
+ this.controller.validateTabIndex(value);
+ }
+
+ @Watch('_touched')
+ public validateTouched(value?: boolean): void {
+ this.controller.validateTouched(value);
+ }
+
+ @Watch('_value')
+ public validateValue(value?: Stringified): void {
+ this.controller.validateValue(value);
+ }
+
+ @Watch('_variant')
+ public validateVariant(value?: InputCheckboxVariant): void {
+ this.controller.validateVariant(value);
+ }
+
+ public componentWillLoad(): void {
+ this._touched = this._touched === true;
+ this.controller.componentWillLoad();
+ }
+
+ private onInput = (event: Event): void => {
+ this._checked = !this._checked;
+ this._indeterminate = false;
+
+ const value = this.getModelValue();
+ this.controller.onFacade.onInput(event, false, value);
+ this.controller.setFormAssociatedCheckboxValue(value);
+ };
+
+ private onChange = (event: Event): void => {
+ this.controller.onFacade.onChange(event, this.getModelValue());
+ };
+}
diff --git a/packages/components/src/components/input-checkbox/style.scss b/packages/components/src/components/input-checkbox/style.scss
index 31c5aef49d..34c245bd9e 100644
--- a/packages/components/src/components/input-checkbox/style.scss
+++ b/packages/components/src/components/input-checkbox/style.scss
@@ -1,8 +1,151 @@
-@import '../input';
-@import 'common';
-@import 'button';
-@import 'checkbox';
-@import 'switch';
-@import '../@shared/kol-alert-mixin.scss';
-
-@include kol-alert-styles;
+@import '../../styles/global';
+@import '../../styles/kol-field-control-mixin';
+@import '../../styles/kol-form-field-mixin';
+@import '../@shared/mixins';
+@import '../host-display-block';
+@import '../tooltip/style';
+
+@include kol-form-field;
+@include kol-field-control;
+
+@layer kol-component {
+ $root: '.kol-checkbox';
+
+ .kol-form-field {
+ display: grid;
+ }
+
+ #{$root} {
+ position: relative;
+ display: flex;
+ align-items: center;
+
+ .kol-input {
+ font-size: rem(16);
+
+ appearance: none;
+ background-color: #fff;
+ cursor: pointer;
+ transition: 0.5s;
+
+ margin: 0;
+ border-style: solid;
+ border-width: rem(2);
+
+ &:before {
+ content: '';
+ cursor: pointer;
+ }
+
+ &:disabled:before {
+ cursor: not-allowed;
+ }
+ }
+ }
+
+ /**
+ * Variant: Checkbox
+ */
+ #{$root}--variant-default {
+ height: var(--a11y-min-size);
+ justify-content: center;
+ position: relative;
+ width: var(--a11y-min-size);
+
+ .kol-icon {
+ display: flex;
+ inset: auto;
+ position: absolute;
+ z-index: 1;
+ pointer-events: none;
+
+ &::part(icon) {
+ display: none;
+ }
+ }
+
+ .kol-input {
+ width: rem(22);
+ height: rem(22);
+ }
+
+ {$root}--checked,
+ {$root}--indeterminate {
+ .kol-icon::part(icon) {
+ display: block;
+ }
+ }
+ }
+
+ /**
+ * Variant: Switch
+ */
+ #{$root}--variant-switch {
+ position: relative;
+
+ .kol-input {
+ display: inline-block;
+ height: 1.7em;
+ min-width: 3.2em;
+ position: relative;
+ width: 3.2em;
+
+ &::before {
+ background-color: #000;
+ height: 1.2em;
+ left: calc(0.25em - rem(2));
+ top: calc(0.25em - rem(2));
+ position: absolute;
+ transition: 0.5s;
+ width: 1.2em;
+ }
+
+ &:checked::before {
+ transform: translateX(1.5em);
+ }
+
+ &:indeterminate::before {
+ transform: translateX(0.75em);
+ }
+ }
+
+ .kol-icon {
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 1.2em;
+ height: 1.2em;
+ position: absolute;
+ z-index: 1;
+ top: 50%;
+ left: rem(4);
+ transform: translate(0, -50%);
+ transition: 0.5s;
+ color: #000;
+ }
+
+ {$root}--checked .kol-icon {
+ transform: translate(1.5em, -50%);
+ }
+
+ {$root}--indeterminate .kol-icon {
+ transform: translate(0.75em, -50%);
+ }
+ }
+
+ /**
+ * Variant: Button
+ */
+ #{$root}--variant-button {
+ width: var(--a11y-min-size);
+
+ .kol-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: var(--a11y-min-size);
+ height: var(--a11y-min-size);
+ }
+ }
+}
diff --git a/packages/components/src/components/input-checkbox/switch.scss b/packages/components/src/components/input-checkbox/switch.scss
deleted file mode 100644
index a800e44af1..0000000000
--- a/packages/components/src/components/input-checkbox/switch.scss
+++ /dev/null
@@ -1,55 +0,0 @@
-@layer kol-component {
- .switch .input {
- position: relative;
- }
-
- .switch input[type='checkbox'] {
- display: inline-block;
- height: 1.7em;
- min-width: 3.2em;
- position: relative;
- width: 3.2em;
- }
-
- .switch input[type='checkbox']::before {
- background-color: #000;
- height: 1.2em;
- left: calc(0.25em - 2px);
- top: calc(0.25em - 2px);
- position: absolute;
- transition: 0.5s;
- width: 1.2em;
- }
-
- .switch input[type='checkbox']:checked::before {
- transform: translateX(1.5em);
- }
-
- .switch input[type='checkbox']:indeterminate::before {
- transform: translateX(0.75em);
- }
-
- .switch .icon {
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 1.2em;
- height: 1.2em;
- position: absolute;
- z-index: 1;
- top: 50%;
- left: 4px;
- transform: translate(0, -50%);
- transition: 0.5s;
- color: #000;
- }
-
- .switch.checked .icon {
- transform: translate(1.5em, -50%);
- }
-
- .switch.indeterminate .icon {
- transform: translate(0.75em, -50%);
- }
-}
diff --git a/packages/components/src/components/input-checkbox/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/input-checkbox/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..0fe262b580
--- /dev/null
+++ b/packages/components/src/components/input-checkbox/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,2745 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _labelAlign="left" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="button" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=false _variant="switch" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="left" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _labelAlign="right" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="button" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _checked=true _variant="switch" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-checkbox should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _indeterminate=true 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/input-checkbox/test/html.mock.ts b/packages/components/src/components/input-checkbox/test/html.mock.ts
deleted file mode 100644
index 4367aa2882..0000000000
--- a/packages/components/src/components/input-checkbox/test/html.mock.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import type { InputCheckboxProps, InputCheckboxStates } from '@public-ui/schema';
-import { mixMembers } from 'stencil-awesome-test';
-import { nonce } from '../../../utils/dev.utils';
-import { KolIconTag, KolInputTag } from '../../../core/component-names';
-import { showExpertSlot } from '@public-ui/schema';
-import { getRenderStates } from '../../input/controller';
-
-export const getInputCheckboxHtml = (props: InputCheckboxProps): string => {
- const state = mixMembers(
- {
- _checked: false,
- _hideError: false,
- _icons: {
- checked: 'codicon codicon-check',
- indeterminate: 'codicon codicon-remove',
- unchecked: 'codicon codicon-close',
- },
- _id: `id-${nonce()}`,
- _indeterminate: false,
- _label: '', // ⚠ required
- _value: true,
- _variant: 'default',
- },
- props,
- );
- const hasExpertSlot = showExpertSlot(state._label);
- const { ariaDescribedBy } = getRenderStates(state);
-
- return `
-
-
- <${KolInputTag}
- ${state._disabled ? `_disabled=""` : ''}
- ${state._hideLabel ? `_hideLabel=""` : ''}
- ${state._touched ? `_touched=""` : ''}
- ${state._required ? `_required=""` : ''}
- _hint=""
- _id="${state._id}"
- _label="${state._label ? `${state._label}` : ''}"
- _tooltipalign="top"
- class="checkbox ${state._hideLabel ? 'hide-label' : ''} default"
- ${state._alert || state._alert === undefined ? `_alert=""` : ''}
- >
- ${
- hasExpertSlot
- ? ` `
- : typeof state._accessKey === 'string'
- ? `
- ${state._label}
-
- ${state._accessKey}
-
- `
- : ` ${state._label} `
- }
-
-
- <${KolIconTag}
- class="icon"
- _icons="${state._indeterminate ? state._icons.indeterminate : state._checked ? state._icons.checked : state._icons.unchecked}"
- _label=""
- > ${KolIconTag}>
- 0 ? `aria-describedby="${ariaDescribedBy.join(' ')}"` : ''}
-
- ${state._hideLabel && typeof state._label === 'string' ? `aria-label="${state._label}"` : ''}
- id="${state._id}"
- type="checkbox"
- ${state._disabled ? `disabled=""` : ''}
- ${state._required ? `required=""` : ''}
- ${state._name ? `name=""` : ''}
- ${state._checked ? `checked=""` : ''}
- ${state._indeterminate ? `indeterminate=""` : ''}
- ${state._tabIndex ? `tabIndex=""` : ''}
-
- />
-
- ${KolInputTag}>
-
- `;
-};
diff --git a/packages/components/src/components/input-checkbox/test/snapshot.spec.tsx b/packages/components/src/components/input-checkbox/test/snapshot.spec.tsx
index 01649d5120..572332ac98 100644
--- a/packages/components/src/components/input-checkbox/test/snapshot.spec.tsx
+++ b/packages/components/src/components/input-checkbox/test/snapshot.spec.tsx
@@ -1,34 +1,44 @@
-import { executeTests } from 'stencil-awesome-test';
-
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
-
-import { getInputCheckboxHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { InputCheckboxProps } from '@public-ui/schema';
-import { KolInputCheckbox } from '../component';
-
-executeTests(
- 'InputCheckbox',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolInputCheckbox],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Label'],
- _hideLabel: [true, false],
- _disabled: [true, false],
- _alert: [true, false],
- _required: [true, false],
- _touched: [true, false],
- },
- getInputCheckboxHtml,
- {
- execMode: 'default', // ready
- needTimers: true,
- },
-);
+import { KolInputCheckboxTag } from '../../../core/component-names';
+import type { InputCheckboxProps } from '../../../schema';
+import { executeInputSnapshotTests } from '../../../utils/testing';
+
+import { KolInputCheckbox } from '../shadow';
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: false,
+ _labelAlign: 'left',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: true,
+ _labelAlign: 'left',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: true,
+ _labelAlign: 'right',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: false,
+ _variant: 'switch',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: true,
+ _variant: 'switch',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: false,
+ _variant: 'button',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _checked: true,
+ _variant: 'button',
+});
+
+executeInputSnapshotTests(KolInputCheckboxTag, [KolInputCheckbox], {
+ _indeterminate: true,
+});
diff --git a/packages/components/src/components/input-color/component.tsx b/packages/components/src/components/input-color/component.tsx
deleted file mode 100644
index 360b4ddd2f..0000000000
--- a/packages/components/src/components/input-color/component.tsx
+++ /dev/null
@@ -1,352 +0,0 @@
-import type {
- ButtonProps,
- HideErrorPropType,
- IdPropType,
- InputColorAPI,
- InputColorStates,
- InputTypeOnDefault,
- InputTypeOnOff,
- KoliBriHorizontalIcons,
- LabelWithExpertSlotPropType,
- MsgPropType,
- NamePropType,
- Stringified,
- SuggestionsPropType,
- SyncValueBySelectorPropType,
- TooltipAlignPropType,
-} from '@public-ui/schema';
-import { propagateFocus, showExpertSlot } from '@public-ui/schema';
-import { Component, Element, Fragment, h, Host, Method, Prop, State, Watch } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { getRenderStates } from '../input/controller';
-import { InternalUnderlinedAccessKey } from '../span/InternalUnderlinedAccessKey';
-import { InputColorController } from './controller';
-
-import type { JSX } from '@stencil/core';
-import { KolInputTag } from '../../core/component-names';
-/**
- * @slot - Die Beschriftung des Eingabefeldes.
- */
-@Component({
- tag: 'kol-input-color',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolInputColor implements InputColorAPI {
- @Element() private readonly host?: HTMLKolInputColorElement;
- private ref?: HTMLInputElement;
-
- private readonly catchRef = (ref?: HTMLInputElement) => {
- this.ref = ref;
- propagateFocus(this.host, this.ref);
- };
-
- @Method()
- // eslint-disable-next-line @typescript-eslint/require-await
- public async getValue(): Promise {
- return this.ref?.value;
- }
-
- public render(): JSX.Element {
- const { ariaDescribedBy } = getRenderStates(this.state);
- const hasSuggestions = Array.isArray(this.state._suggestions) && this.state._suggestions.length > 0;
- const hasExpertSlot = showExpertSlot(this.state._label);
-
- return (
-
- this.ref?.focus()}
- role={`presentation` /* Avoid element being read as 'clickable' in NVDA */}
- >
-
- {hasExpertSlot ? (
-
- ) : typeof this.state._accessKey === 'string' ? (
- <>
- {' '}
-
- {this.state._accessKey}
-
- >
- ) : (
- {this.state._label}
- )}
-
-
- 0 ? ariaDescribedBy.join(' ') : undefined}
- aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
- autoCapitalize="off"
- autoComplete={this.state._autoComplete}
- autoCorrect="off"
- disabled={this.state._disabled}
- id={this.state._id}
- list={hasSuggestions ? `${this.state._id}-list` : undefined}
- name={this.state._name}
- slot="input"
- spellcheck="false"
- type="color"
- value={this.state._value as string}
- {...this.controller.onFacade}
- />
-
-
-
- );
- }
-
- private readonly controller: InputColorController;
-
- /**
- * Defines which key combination can be used to trigger or focus the interactive element of the component.
- */
- @Prop() public _accessKey?: string;
-
- /**
- * Defines whether the screen-readers should read out the notification.
- */
- @Prop({ mutable: true, reflect: true }) public _alert?: boolean = true;
-
- /**
- * Defines whether the input can be auto-completed.
- */
- @Prop() public _autoComplete?: InputTypeOnOff;
-
- /**
- * Makes the element not focusable and ignore all events.
- * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the error message text.
- * @deprecated Will be removed in v3. Use `msg` instead.
- */
- @Prop() public _error?: string;
-
- /**
- * Hides the error message but leaves it in the DOM for the input's aria-describedby.
- * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
-
- /**
- * Hides the caption by default and displays the caption text with a tooltip when the
- * interactive element is focused or the mouse is over it.
- * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hideLabel?: boolean = false;
-
- /**
- * Defines the hint text.
- */
- @Prop() public _hint?: string = '';
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: Stringified;
-
- /**
- * Defines the internal ID of the primary component element.
- */
- @Prop() public _id?: IdPropType;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines the properties for a message rendered as Alert component.
- */
- @Prop() public _msg?: MsgPropType;
-
- /**
- * Defines the technical name of an input field.
- */
- @Prop() public _name?: NamePropType;
-
- /**
- * Gibt die EventCallback-Funktionen für das Input-Event an.
- */
- @Prop() public _on?: InputTypeOnDefault;
-
- /**
- * Allows to add a button with an arbitrary action within the element (_hide-label only).
- */
- @Prop() public _smartButton?: Stringified;
-
- /**
- * Suggestions to provide for the input.
- */
- @Prop() public _suggestions?: SuggestionsPropType;
-
- /**
- * Selector for synchronizing the value with another input element.
- * @internal
- */
- @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
-
- /**
- * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
- */
- @Prop() public _tabIndex?: number;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Shows if the input was touched by a user.
- * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
-
- /**
- * Defines the value of the input.
- */
- @Prop() public _value?: string;
-
- @State() public state: InputColorStates = {
- _autoComplete: 'off',
- _hideError: false,
- _id: `id-${nonce()}`,
- _label: '', // ⚠ required
- _suggestions: [],
- };
-
- public constructor() {
- this.controller = new InputColorController(this, 'color', this.host);
- }
-
- @Watch('_accessKey')
- public validateAccessKey(value?: string): void {
- this.controller.validateAccessKey(value);
- }
-
- @Watch('_alert')
- public validateAlert(value?: boolean): void {
- this.controller.validateAlert(value);
- }
-
- @Watch('_autoComplete')
- public validateAutoComplete(value?: InputTypeOnOff): void {
- this.controller.validateAutoComplete(value);
- }
-
- @Watch('_disabled')
- public validateDisabled(value?: boolean): void {
- this.controller.validateDisabled(value);
- }
-
- @Watch('_error')
- public validateError(value?: string): void {
- this.controller.validateError(value);
- }
-
- @Watch('_hideError')
- public validateHideError(value?: HideErrorPropType): void {
- this.controller.validateHideError(value);
- }
-
- @Watch('_hideLabel')
- public validateHideLabel(value?: boolean): void {
- this.controller.validateHideLabel(value);
- }
-
- @Watch('_hint')
- public validateHint(value?: string): void {
- this.controller.validateHint(value);
- }
-
- @Watch('_icons')
- public validateIcons(value?: Stringified): void {
- this.controller.validateIcons(value);
- }
-
- @Watch('_id')
- public validateId(value?: string): void {
- this.controller.validateId(value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelWithExpertSlotPropType): void {
- this.controller.validateLabel(value);
- }
-
- @Watch('_msg')
- public validateMsg(value?: MsgPropType): void {
- this.controller.validateMsg(value);
- }
-
- @Watch('_name')
- public validateName(value?: string): void {
- this.controller.validateName(value);
- }
-
- @Watch('_on')
- public validateOn(value?: InputTypeOnDefault): void {
- this.controller.validateOn(value);
- }
-
- @Watch('_smartButton')
- public validateSmartButton(value?: ButtonProps | string): void {
- this.controller.validateSmartButton(value);
- }
-
- @Watch('_suggestions')
- public validateSuggestions(value?: SuggestionsPropType): void {
- this.controller.validateSuggestions(value);
- }
-
- @Watch('_syncValueBySelector')
- public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
- this.controller.validateSyncValueBySelector(value);
- }
-
- @Watch('_tabIndex')
- public validateTabIndex(value?: number): void {
- this.controller.validateTabIndex(value);
- }
-
- @Watch('_touched')
- public validateTouched(value?: boolean): void {
- this.controller.validateTouched(value);
- }
-
- @Watch('_value')
- public validateValue(value?: string): void {
- this.controller.validateValue(value);
- }
-
- public componentWillLoad(): void {
- this._alert = this._alert === true;
- this._touched = this._touched === true;
- this.controller.componentWillLoad();
- }
-}
diff --git a/packages/components/src/components/input-color/controller.ts b/packages/components/src/components/input-color/controller.ts
index 759c87e34e..c4f0408085 100644
--- a/packages/components/src/components/input-color/controller.ts
+++ b/packages/components/src/components/input-color/controller.ts
@@ -1,5 +1,5 @@
-import type { InputColorProps, InputColorWatches, InputTypeOnOff, SuggestionsPropType } from '@public-ui/schema';
-import { inputTypeOnOffOptions, validateSuggestions, watchString, watchValidator } from '@public-ui/schema';
+import type { InputColorProps, InputColorWatches, InputTypeOnOff, SuggestionsPropType } from '../../schema';
+import { inputTypeOnOffOptions, validateSuggestions, watchString, watchValidator } from '../../schema';
import { InputIconController } from '../@deprecated/input/controller-icon';
diff --git a/packages/components/src/components/input-color/input-color.e2e.ts b/packages/components/src/components/input-color/input-color.e2e.ts
new file mode 100644
index 0000000000..3a5eac0e5a
--- /dev/null
+++ b/packages/components/src/components/input-color/input-color.e2e.ts
@@ -0,0 +1,10 @@
+import { test } from '@stencil/playwright';
+import { testInputCallbacksAndEvents, testInputValueReflection } from '../../e2e';
+
+const COMPONENT_NAME = 'kol-input-color';
+const TEST_VALUE = '#cc006e';
+
+test.describe(COMPONENT_NAME, () => {
+ testInputValueReflection(COMPONENT_NAME, TEST_VALUE);
+ testInputCallbacksAndEvents(COMPONENT_NAME, TEST_VALUE);
+});
diff --git a/packages/components/src/components/input-color/readme.md b/packages/components/src/components/input-color/readme.md
deleted file mode 100644
index 31c96aee6c..0000000000
--- a/packages/components/src/components/input-color/readme.md
+++ /dev/null
@@ -1,87 +0,0 @@
-# InputColor
-
-Der Input-Typ **Color** erzeugt ein Auswahlfeld für die Definition einer beliebigen Farbe. Die Eingabe der Farbe kann in hexadezimaler Schreibweise, in RGB-Schreibweise oder in HSL-Schreibweise erfolgen. Möglich ist die Auswahl einer Farbe über einen Picker oder auch die exakte Eingabe von Farbwerten.
-
-## Konstruktion
-
-### Code
-
-```html
-
-```
-
-### Beispiel
-
-
-
-## Verwendung
-
-Stellen Sie die Default-Farbe über das Attribut `_value` ein. Verwenden Sie hierfür eine hexadezimale Schreibweise (#xxxxxx).
-
-### Best practices
-
-- Achten Sie darauf `id` und `name` korrekt zu setzen, damit die Daten beim Formular Absenden mitgesendet werden.
-
-## Barrierefreiheit
-
-Beachten Sie, dass die **InputColor**-Komponente nicht vollständig barrierefrei ist. Die Auswahl einer Farbe ist über Tastatursteuerung möglich. Die Ausgabe der gewählten Farbe über Screenreader ist jedoch technisch eingeschränkt.
-Siehe auch: [https://github.com/public-ui/kolibri/blob/develop/KNOWN_ISSUES.md#input-color](Known Issues).
-
-Für eine vollständige Barrierefreiheit prüfen Sie die Verwendung einer vorgefertigten Farbauswahlliste, z.B. über Checkboxen oder Select-Felder.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
-| `Tab` | Fokussiert das Eingabefeld. Bei geöffnetem Dialogfeld kann mit der Tab-Taste zwischen den Steuerfeldern gewechselt werden. |
-| `Enter` | Öffnet bzw. schließt das Dialogfeld der Komponente. Bei fokussierter Pipette wird mit der Enter-Taste die Funktion **_Pipette_** gestartet. |
-| `ESC` | Beendet die Pipettenfunktion. Schließt das Dialogfeld, wenn die Pipettenfunktion nicht aktiv ist. |
-| `Pfeil-Tasten (rechts / links)` | Verschieben bei fokussiertem Feld **_Farbspektrum_** den Auswahlpunkt. |
-| `Pfeil-Tasten (oben / unten)` | Ändert bei fokussiertem Feld **_Farbsystem_** die Auswahl. |
-
-## Links und Referenzen
-
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_accessKey` | `_access-key` | Defines which key combination can be used to trigger or focus the interactive element of the component. | `string \| undefined` | `undefined` |
-| `_alert` | `_alert` | Defines whether the screen-readers should read out the notification. | `boolean \| undefined` | `true` |
-| `_autoComplete` | `_auto-complete` | Defines whether the input can be auto-completed. | `"off" \| "on" \| undefined` | `undefined` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_error` | `_error` | **[DEPRECATED]** Will be removed in v3. Use `msg` instead. Defines the error message text. | `string \| undefined` | `undefined` |
-| `_hideError` | `_hide-error` | Hides the error message but leaves it in the DOM for the input's aria-describedby. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_hint` | `_hint` | Defines the hint text. | `string \| undefined` | `''` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `string \| undefined \| { right?: IconOrIconClass \| undefined; left?: IconOrIconClass \| undefined; }` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_msg` | -- | Defines the properties for a message rendered as Alert component. | `undefined \| {} & { _level?: 0 \| 2 \| 1 \| 3 \| 4 \| 5 \| 6 \| undefined; _on?: KoliBriAlertEventCallbacks \| undefined; _type?: "error" \| "warning" \| "info" \| "success" \| "default" \| undefined; _variant?: "card" \| "msg" \| undefined; _label?: string \| undefined; _alert?: boolean \| undefined; _hasCloser?: boolean \| undefined; } & { _description: string; }` | `undefined` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für das Input-Event an. | `InputTypeOnBlur & InputTypeOnClick & InputTypeOnChange & InputTypeOnFocus & InputTypeOnInput \| undefined` | `undefined` |
-| `_smartButton` | `_smart-button` | Allows to add a button with an arbitrary action within the element (\_hide-label only). | `string \| undefined \| { _label: string; } & { _tabIndex?: number \| undefined; _value?: Stringified; _role?: AlternativeButtonLinkRolePropType \| undefined; _ariaControls?: string \| undefined; _ariaExpanded?: boolean \| undefined; _ariaSelected?: boolean \| undefined; _on?: ButtonCallbacksPropType \| undefined; _type?: "button" \| "reset" \| "submit" \| undefined; _variant?: "primary" \| "secondary" \| "normal" \| "tertiary" \| "danger" \| "ghost" \| "custom" \| undefined; _customClass?: string \| undefined; _disabled?: boolean \| undefined; _hideLabel?: boolean \| undefined; _icons?: IconsPropType \| undefined; _id?: string \| undefined; _name?: string \| undefined; _syncValueBySelector?: string \| undefined; _tooltipAlign?: AlignPropType \| undefined; _accessKey?: string \| undefined; }` | `undefined` |
-| `_suggestions` | `_suggestions` | Suggestions to provide for the input. | `W3CInputValue[] \| string \| undefined` | `undefined` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_touched` | `_touched` | Shows if the input was touched by a user. | `boolean \| undefined` | `false` |
-| `_value` | `_value` | Defines the value of the input. | `string \| undefined` | `undefined` |
-
-## Methods
-
-### `getValue() => Promise`
-
-#### Returns
-
-Type: `Promise`
-
-## Slots
-
-| Slot | Description |
-| ---- | ----------------------------------- |
-| | Die Beschriftung des Eingabefeldes. |
-
----
diff --git a/packages/components/src/components/input-color/shadow.tsx b/packages/components/src/components/input-color/shadow.tsx
new file mode 100644
index 0000000000..7e0c6f2508
--- /dev/null
+++ b/packages/components/src/components/input-color/shadow.tsx
@@ -0,0 +1,334 @@
+import type {
+ ButtonProps,
+ FocusableElement,
+ HideErrorPropType,
+ IdPropType,
+ InputColorAPI,
+ InputColorStates,
+ InputTypeOnDefault,
+ InputTypeOnOff,
+ KoliBriHorizontalIcons,
+ LabelWithExpertSlotPropType,
+ MsgPropType,
+ NamePropType,
+ ShortKeyPropType,
+ Stringified,
+ SuggestionsPropType,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+} from '../../schema';
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
+
+import { nonce } from '../../utils/dev.utils';
+import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper';
+import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper';
+import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper';
+import { InputColorController } from './controller';
+
+/**
+ * @slot - Die Beschriftung des Eingabefeldes.
+ */
+@Component({
+ tag: 'kol-input-color',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: {
+ delegatesFocus: true,
+ },
+})
+export class KolInputColor implements InputColorAPI, FocusableElement {
+ @Element() private readonly host?: HTMLKolInputColorElement;
+ private inputRef?: HTMLInputElement;
+
+ private readonly catchRef = (ref?: HTMLInputElement) => {
+ this.inputRef = ref;
+ };
+
+ private readonly onBlur = (event: FocusEvent) => {
+ this.controller.onFacade.onBlur(event);
+ this.inputHasFocus = false;
+ };
+
+ private readonly onFocus = (event: FocusEvent) => {
+ this.controller.onFacade.onFocus(event);
+ this.inputHasFocus = true;
+ };
+
+ private readonly onInput = (event: InputEvent) => {
+ this._value = this.inputRef?.value ?? '';
+ this.controller.onFacade.onInput(event);
+ };
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async getValue(): Promise {
+ return this.inputRef?.value;
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ this.inputRef?.focus();
+ }
+
+ private getFormFieldProps(): FormFieldStateWrapperProps {
+ return {
+ state: this.state,
+ class: 'kol-input-color',
+ tooltipAlign: this._tooltipAlign,
+ onClick: () => this.inputRef?.focus(),
+ alert: this.showAsAlert(),
+ };
+ }
+
+ private getInputProps(): InputStateWrapperProps {
+ return {
+ ref: this.catchRef,
+ type: 'color',
+ slot: 'input',
+ state: this.state,
+ ...this.controller.onFacade,
+ onBlur: this.onBlur,
+ onFocus: this.onFocus,
+ onInput: this.onInput,
+ };
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+ );
+ }
+
+ private readonly controller: InputColorController;
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: string;
+
+ /**
+ * Defines whether the input can be auto-completed.
+ */
+ @Prop() public _autoComplete?: InputTypeOnOff;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the error message but leaves it in the DOM for the input's aria-describedby.
+ * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the hint text.
+ */
+ @Prop() public _hint?: string = '';
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: Stringified;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: IdPropType;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines the properties for a message rendered as Alert component.
+ */
+ @Prop() public _msg?: Stringified;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: NamePropType;
+
+ /**
+ * Gibt die EventCallback-Funktionen für das Input-Event an.
+ */
+ @Prop() public _on?: InputTypeOnDefault;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Allows to add a button with an arbitrary action within the element (_hide-label only).
+ */
+ @Prop() public _smartButton?: Stringified;
+
+ /**
+ * Suggestions to provide for the input.
+ */
+ @Prop() public _suggestions?: SuggestionsPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Shows if the input was touched by a user.
+ * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
+
+ /**
+ * Defines the value of the input.
+ */
+ @Prop({ reflect: true }) public _value?: string;
+
+ @State() public state: InputColorStates = {
+ _autoComplete: 'off',
+ _hideError: false,
+ _id: `id-${nonce()}`,
+ _label: '', // ⚠ required
+ _suggestions: [],
+ };
+
+ @State() private inputHasFocus = false;
+
+ public constructor() {
+ this.controller = new InputColorController(this, 'color', this.host);
+ }
+
+ private showAsAlert(): boolean {
+ return Boolean(this.state._touched) && !this.inputHasFocus;
+ }
+
+ @Watch('_accessKey')
+ public validateAccessKey(value?: string): void {
+ this.controller.validateAccessKey(value);
+ }
+
+ @Watch('_autoComplete')
+ public validateAutoComplete(value?: InputTypeOnOff): void {
+ this.controller.validateAutoComplete(value);
+ }
+
+ @Watch('_disabled')
+ public validateDisabled(value?: boolean): void {
+ this.controller.validateDisabled(value);
+ }
+
+ @Watch('_hideError')
+ public validateHideError(value?: HideErrorPropType): void {
+ this.controller.validateHideError(value);
+ }
+
+ @Watch('_hideLabel')
+ public validateHideLabel(value?: boolean): void {
+ this.controller.validateHideLabel(value);
+ }
+
+ @Watch('_hint')
+ public validateHint(value?: string): void {
+ this.controller.validateHint(value);
+ }
+
+ @Watch('_icons')
+ public validateIcons(value?: Stringified): void {
+ this.controller.validateIcons(value);
+ }
+
+ @Watch('_id')
+ public validateId(value?: string): void {
+ this.controller.validateId(value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelWithExpertSlotPropType): void {
+ this.controller.validateLabel(value);
+ }
+
+ @Watch('_msg')
+ public validateMsg(value?: Stringified): void {
+ this.controller.validateMsg(value);
+ }
+
+ @Watch('_name')
+ public validateName(value?: string): void {
+ this.controller.validateName(value);
+ }
+
+ @Watch('_on')
+ public validateOn(value?: InputTypeOnDefault): void {
+ this.controller.validateOn(value);
+ }
+
+ @Watch('_shortKey')
+ public validateShortKey(value?: ShortKeyPropType): void {
+ this.controller.validateShortKey(value);
+ }
+
+ @Watch('_smartButton')
+ public validateSmartButton(value?: ButtonProps | string): void {
+ this.controller.validateSmartButton(value);
+ }
+
+ @Watch('_suggestions')
+ public validateSuggestions(value?: SuggestionsPropType): void {
+ this.controller.validateSuggestions(value);
+ }
+
+ @Watch('_syncValueBySelector')
+ public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
+ this.controller.validateSyncValueBySelector(value);
+ }
+
+ @Watch('_tabIndex')
+ public validateTabIndex(value?: number): void {
+ this.controller.validateTabIndex(value);
+ }
+
+ @Watch('_touched')
+ public validateTouched(value?: boolean): void {
+ this.controller.validateTouched(value);
+ }
+
+ @Watch('_value')
+ public validateValue(value?: string): void {
+ this.controller.validateValue(value);
+ }
+
+ public componentWillLoad(): void {
+ this._touched = this._touched === true;
+ this.controller.componentWillLoad();
+ }
+}
diff --git a/packages/components/src/components/input-color/style.scss b/packages/components/src/components/input-color/style.scss
index bf877e2816..0afb4a2557 100644
--- a/packages/components/src/components/input-color/style.scss
+++ b/packages/components/src/components/input-color/style.scss
@@ -1,10 +1,11 @@
-@import '../input-line';
-@import '../@shared/kol-alert-mixin.scss';
+@import '../../styles/global';
+@import '../../styles/kol-alert-mixin';
+@import '../../styles/kol-form-field-mixin';
+@import '../../styles/kol-input-container-mixin';
+@import '../../styles/kol-input-mixin';
+@import '../@shared/mixins';
-@include kol-alert-styles;
-
-@layer kol-component {
- div.input {
- cursor: pointer;
- }
-}
+@include kol-alert;
+@include kol-form-field;
+@include kol-input-container;
+@include kol-input;
diff --git a/packages/components/src/components/input-color/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/input-color/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..e8dd38866d
--- /dev/null
+++ b/packages/components/src/components/input-color/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,761 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _smartButton={"_icons":["codicon codicon-eye"],"_hideLabel":true,"_label":"einblenden"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _smartButton={"_icons":["codicon codicon-eye"],"_hideLabel":true,"_label":"einblenden"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _suggestions=["#F00","#0F0","#00F"] 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-color should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="#FFF" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/input-color/test/html.mock.ts b/packages/components/src/components/input-color/test/html.mock.ts
deleted file mode 100644
index 259e6c9f2c..0000000000
--- a/packages/components/src/components/input-color/test/html.mock.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { InputColorProps, InputColorStates } from '@public-ui/schema';
-import { mixMembers } from 'stencil-awesome-test';
-import { nonce } from '../../../utils/dev.utils';
-import { KolInputTag } from '../../../core/component-names';
-import { showExpertSlot } from '@public-ui/schema';
-import { getRenderStates } from '../../input/controller';
-
-export const getInputColorHtml = (props: InputColorProps): string => {
- const state = mixMembers(
- {
- _autoComplete: 'off',
- _hideError: false,
- _id: `id-${nonce()}`,
- _label: '', // ⚠ required
- _suggestions: [],
- },
- props,
- );
- const hasExpertSlot = showExpertSlot(state._label);
- const { ariaDescribedBy } = getRenderStates(state);
-
- return `
-
-
- <${KolInputTag}
- ${state._disabled ? `_disabled=""` : ''}
- ${state._hideLabel ? `_hideLabel=""` : ''}
- ${state._touched ? `_touched=""` : ''}
- _hint=""
- _id="${state._id}"
- _label="${state._label ? `${state._label}` : ''}"
- _tooltipalign="top"
- class="color ${state._hideLabel ? 'hide-label' : ''} "
- role="presentation"
- >
- ${
- hasExpertSlot
- ? ` `
- : typeof state._accessKey === 'string'
- ? `
- ${state._label}
-
- ${state._accessKey}
-
- `
- : ` ${state._label} `
- }
-
-
- 0 ? `aria-describedby="${ariaDescribedBy.join(' ')}"` : ''}
- >
-
- ${KolInputTag}>
-
- `;
-};
diff --git a/packages/components/src/components/input-color/test/snapshot.spec.tsx b/packages/components/src/components/input-color/test/snapshot.spec.tsx
index c73c42488b..0ae6561dd8 100644
--- a/packages/components/src/components/input-color/test/snapshot.spec.tsx
+++ b/packages/components/src/components/input-color/test/snapshot.spec.tsx
@@ -1,41 +1,24 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolInputColorTag } from '../../../core/component-names';
+import type { InputColorProps } from '../../../schema';
+import { executeInputSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolInputColor } from '../shadow';
-import { getInputColorHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { InputColorProps } from '@public-ui/schema';
-import { KolInputColor } from '../component';
-
-executeTests(
- 'InputColor',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolInputColor],
- template: () => ,
- });
- return page;
- },
+executeInputSnapshotTests(
+ KolInputColorTag,
+ [KolInputColor],
{
- _label: ['Label'],
- _hideLabel: [true, false],
- _disabled: [true, false],
- _alert: [true, false],
- _icons: [[{ left: 'codicon codicon-home' }]],
- _touched: [true, false],
- _smartButton: [
- {
- _icons: ['codicon codicon-eye'],
- _hideLabel: true,
- _label: 'einblenden',
- },
- ],
+ _value: '#FFF',
},
- getInputColorHtml,
+ { hasSmartButton: true },
+);
+
+executeInputSnapshotTests(
+ KolInputColorTag,
+ [KolInputColor],
{
- execMode: 'default', // ready
- needTimers: true,
+ _value: '#FFF',
+ _suggestions: ['#F00', '#0F0', '#00F'],
},
+ { hasSmartButton: true },
);
diff --git a/packages/components/src/components/input-date/component.tsx b/packages/components/src/components/input-date/component.tsx
deleted file mode 100644
index 266a0a9e9e..0000000000
--- a/packages/components/src/components/input-date/component.tsx
+++ /dev/null
@@ -1,440 +0,0 @@
-import type { JSX } from '@stencil/core';
-import { type MsgPropType, propagateFocus, showExpertSlot } from '@public-ui/schema';
-import { Component, Element, Fragment, h, Host, Method, Prop, State, Watch } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { propagateSubmitEventToForm } from '../form/controller';
-import { getRenderStates } from '../input/controller';
-import { InternalUnderlinedAccessKey } from '../span/InternalUnderlinedAccessKey';
-import { InputDateController } from './controller';
-
-import type {
- ButtonProps,
- HideErrorPropType,
- IdPropType,
- InputDateAPI,
- InputDateStates,
- InputDateType,
- InputTypeOnDefault,
- InputTypeOnOff,
- Iso8601,
- KoliBriHorizontalIcons,
- LabelWithExpertSlotPropType,
- NamePropType,
- ReadOnlyPropType,
- Stringified,
- SuggestionsPropType,
- SyncValueBySelectorPropType,
- TooltipAlignPropType,
-} from '@public-ui/schema';
-import { KolInputTag } from '../../core/component-names';
-/**
- * @slot - Die Beschriftung des Eingabefeldes.
- */
-@Component({
- tag: 'kol-input-date',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolInputDate implements InputDateAPI {
- @Element() private readonly host?: HTMLKolInputDateElement;
- private ref?: HTMLInputElement;
-
- private readonly catchRef = (ref?: HTMLInputElement) => {
- this.ref = ref;
- propagateFocus(this.host, this.ref);
- };
-
- @Method()
- // eslint-disable-next-line @typescript-eslint/require-await
- public async getValue(): Promise {
- return this.ref?.value;
- }
-
- private readonly onKeyDown = (event: KeyboardEvent) => {
- if (event.code === 'Enter' || event.code === 'NumpadEnter') {
- propagateSubmitEventToForm({
- form: this.host,
- ref: this.ref,
- });
- }
- };
-
- public render(): JSX.Element {
- const { ariaDescribedBy } = getRenderStates(this.state);
- const hasSuggestions = Array.isArray(this.state._suggestions) && this.state._suggestions.length > 0;
- const hasExpertSlot = showExpertSlot(this.state._label);
-
- return (
-
-
-
- {hasExpertSlot ? (
-
- ) : typeof this.state._accessKey === 'string' ? (
- <>
- {' '}
-
- {this.state._accessKey}
-
- >
- ) : (
- {this.state._label}
- )}
-
-
- 0 ? ariaDescribedBy.join(' ') : undefined}
- aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
- autoCapitalize="off"
- autoComplete={this.state._autoComplete}
- autoCorrect="off"
- disabled={this.state._disabled}
- id={this.state._id}
- list={hasSuggestions ? `${this.state._id}-list` : undefined}
- max={this.state._max}
- min={this.state._min}
- name={this.state._name}
- readOnly={this.state._readOnly}
- required={this.state._required}
- step={this.state._step}
- spellcheck="false"
- type={this.state._type}
- value={this.state._value as string}
- {...this.controller.onFacade}
- onKeyDown={this.onKeyDown}
- />
-
-
-
- );
- }
-
- private readonly controller: InputDateController;
-
- /**
- * Defines which key combination can be used to trigger or focus the interactive element of the component.
- */
- @Prop() public _accessKey?: string;
-
- /**
- * Defines whether the screen-readers should read out the notification.
- */
- @Prop({ mutable: true, reflect: true }) public _alert?: boolean = true;
-
- /**
- * Defines whether the input can be auto-completed.
- */
- @Prop() public _autoComplete?: InputTypeOnOff;
-
- /**
- * Makes the element not focusable and ignore all events.
- * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the error message text.
- * @deprecated Will be removed in v3. Use `msg` instead.
- */
- @Prop() public _error?: string;
-
- /**
- * Hides the error message but leaves it in the DOM for the input's aria-describedby.
- * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
-
- /**
- * Hides the caption by default and displays the caption text with a tooltip when the
- * interactive element is focused or the mouse is over it.
- * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hideLabel?: boolean = false;
-
- /**
- * Defines the hint text.
- */
- @Prop() public _hint?: string = '';
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: Stringified;
-
- /**
- * Defines the internal ID of the primary component element.
- */
- @Prop() public _id?: IdPropType;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines the largest possible input value.
- */
- @Prop() public _max?: Iso8601 | Date;
-
- /**
- * Defines the smallest possible input value.
- */
- @Prop() public _min?: Iso8601 | Date;
-
- /**
- * Defines the properties for a message rendered as Alert component.
- */
- @Prop() public _msg?: MsgPropType;
-
- /**
- * Defines the technical name of an input field.
- */
- @Prop() public _name?: NamePropType;
-
- /**
- * Gibt die EventCallback-Funktionen für das Input-Event an.
- */
- @Prop() public _on?: InputTypeOnDefault;
-
- /**
- * Makes the input element read only.
- * @TODO: Change type back to `ReadOnlyPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _readOnly?: boolean = false;
-
- /**
- * Makes the input element required.
- * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _required?: boolean = false;
-
- /**
- * Allows to add a button with an arbitrary action within the element (_hide-label only).
- */
- @Prop() public _smartButton?: Stringified;
-
- /**
- * Suggestions to provide for the input.
- */
- @Prop() public _suggestions?: SuggestionsPropType;
-
- /**
- * Selector for synchronizing the value with another input element.
- * @internal
- */
- @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
-
- /**
- * Defines the step size for value changes.
- */
- @Prop() public _step?: number;
-
- /**
- * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
- */
- @Prop() public _tabIndex?: number;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Shows if the input was touched by a user.
- * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
-
- /**
- * Defines either the type of the component or of the components interactive element.
- */
- @Prop() public _type: InputDateType = 'date';
-
- /**
- * Defines the value of the input.
- */
- @Prop({ mutable: true }) public _value?: Iso8601 | Date | null;
-
- @State() public state: InputDateStates = {
- _autoComplete: 'off',
- _hasValue: false,
- _hideError: false,
- _id: `id-${nonce()}`,
- _label: '', // ⚠ required
- _suggestions: [],
- _type: 'datetime-local',
- };
-
- public constructor() {
- this.controller = new InputDateController(this, 'date', this.host);
- }
-
- @Watch('_accessKey')
- public validateAccessKey(value?: string): void {
- this.controller.validateAccessKey(value);
- }
-
- @Watch('_alert')
- public validateAlert(value?: boolean): void {
- this.controller.validateAlert(value);
- }
-
- @Watch('_autoComplete')
- public validateAutoComplete(value?: InputTypeOnOff): void {
- this.controller.validateAutoComplete(value);
- }
-
- @Watch('_disabled')
- public validateDisabled(value?: boolean): void {
- this.controller.validateDisabled(value);
- }
-
- @Watch('_error')
- public validateError(value?: string): void {
- this.controller.validateError(value);
- }
-
- @Watch('_hideError')
- public validateHideError(value?: HideErrorPropType): void {
- this.controller.validateHideError(value);
- }
-
- @Watch('_hideLabel')
- public validateHideLabel(value?: boolean): void {
- this.controller.validateHideLabel(value);
- }
-
- @Watch('_hint')
- public validateHint(value?: string): void {
- this.controller.validateHint(value);
- }
-
- @Watch('_icons')
- public validateIcons(value?: Stringified): void {
- this.controller.validateIcons(value);
- }
-
- @Watch('_id')
- public validateId(value?: string): void {
- this.controller.validateId(value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelWithExpertSlotPropType): void {
- this.controller.validateLabel(value);
- }
-
- @Watch('_max')
- public validateMax(value?: Iso8601 | Date): void {
- this.controller.validateMax(value);
- }
-
- @Watch('_min')
- public validateMin(value?: Iso8601 | Date): void {
- this.controller.validateMin(value);
- }
-
- @Watch('_msg')
- public validateMsg(value?: MsgPropType): void {
- this.controller.validateMsg(value);
- }
-
- @Watch('_name')
- public validateName(value?: string): void {
- this.controller.validateName(value);
- }
-
- @Watch('_on')
- public validateOn(value?: InputTypeOnDefault): void {
- this.controller.validateOn(value);
- }
-
- @Watch('_readOnly')
- public validateReadOnly(value?: ReadOnlyPropType): void {
- this.controller.validateReadOnly(value);
- }
-
- @Watch('_required')
- public validateRequired(value?: boolean): void {
- this.controller.validateRequired(value);
- }
-
- @Watch('_smartButton')
- public validateSmartButton(value?: ButtonProps | string): void {
- this.controller.validateSmartButton(value);
- }
-
- @Watch('_suggestions')
- public validateSuggestions(value?: SuggestionsPropType): void {
- this.controller.validateSuggestions(value);
- }
-
- @Watch('_step')
- public validateStep(value?: number): void {
- this.controller.validateStep(value);
- }
-
- @Watch('_syncValueBySelector')
- public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
- this.controller.validateSyncValueBySelector(value);
- }
-
- @Watch('_tabIndex')
- public validateTabIndex(value?: number): void {
- this.controller.validateTabIndex(value);
- }
-
- @Watch('_touched')
- public validateTouched(value?: boolean): void {
- this.controller.validateTouched(value);
- }
-
- @Watch('_type')
- public validateType(value?: InputDateType): void {
- this.controller.validateType(value);
- }
-
- @Watch('_value')
- public validateValue(value?: Iso8601 | Date | null): void {
- this.controller.validateValueEx(value, (v) => {
- if (v === '' && this.ref) {
- this.ref.value = '';
- }
- });
- }
-
- public componentWillLoad(): void {
- this._alert = this._alert === true;
- this._touched = this._touched === true;
- this.controller.componentWillLoad();
-
- this.state._hasValue = !!this.state._value;
- this.controller.addValueChangeListener((v) => (this.state._hasValue = !!v));
- }
-}
diff --git a/packages/components/src/components/input-date/controller.spec.ts b/packages/components/src/components/input-date/controller.spec.ts
new file mode 100644
index 0000000000..935d2f1166
--- /dev/null
+++ b/packages/components/src/components/input-date/controller.spec.ts
@@ -0,0 +1,65 @@
+import { InputDateController } from './controller';
+import { describe, it, expect } from '@jest/globals';
+
+const TEST_DATE = new Date('2020-03-03T03:02:01.099');
+
+describe('InputDateController', () => {
+ describe('method tryParseToString', () => {
+ it(`returns the value when it's a string`, () => {
+ expect(InputDateController.tryParseToString('2020-03-04')).toBe('2020-03-04');
+ });
+
+ it(`returns the value when it's null`, () => {
+ expect(InputDateController.tryParseToString(null)).toBeNull();
+ });
+
+ describe('when the type is date', () => {
+ it('returns a ISO8601 date string for type date', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'date')).toBe('2020-03-03');
+ });
+
+ it('returns a ISO8601 datetime string for type datetime-local', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'datetime-local')).toBe('2020-03-03T03:02:01');
+ });
+
+ it('returns a ISO8601 month string for type month', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'month')).toBe('2020-03');
+ });
+
+ it('returns a ISO8601 time string omitting seconds for type time with no step', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'time')).toBe('03:02');
+ });
+
+ it('returns a ISO8601 time string omitting seconds for type time with a step of string "60"', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'time', '60')).toBe('03:02');
+ });
+
+ it('returns a ISO8601 time string omitting seconds for type time with a step of number 60', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'time', 60)).toBe('03:02');
+ });
+
+ it('returns a ISO8601 time string including seconds for type time with a step != "60"', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'time', 10)).toBe('03:02:01');
+ });
+
+ it('returns a ISO8601 week string for type week', () => {
+ expect(InputDateController.tryParseToString(TEST_DATE, 'week')).toBe('2020-W10');
+ });
+ });
+ });
+ describe('method getWeekNumberOfDate', () => {
+ it('should return correct WeekOfYear', () => {
+ expect(InputDateController.getWeekNumberOfDate(TEST_DATE)).toBe('10');
+ });
+
+ it('should return correct WeekOfYear when first day of year is in last kw', () => {
+ const date = new Date('2021-01-01T03:02:01.099');
+ expect(InputDateController.getWeekNumberOfDate(date)).toBe('53');
+ });
+
+ it('should return correct WeekOfYear when last years week is in first kw ', () => {
+ const date = new Date('2019-12-30T03:02:01.099');
+ expect(InputDateController.getWeekNumberOfDate(date)).toBe('01');
+ });
+ });
+});
diff --git a/packages/components/src/components/input-date/controller.ts b/packages/components/src/components/input-date/controller.ts
index 2c811383cb..2d825e0a59 100644
--- a/packages/components/src/components/input-date/controller.ts
+++ b/packages/components/src/components/input-date/controller.ts
@@ -7,12 +7,13 @@ import type {
Iso8601,
ReadOnlyPropType,
SuggestionsPropType,
-} from '@public-ui/schema';
-import { inputDateTypeOptions, setState, validateReadOnly, validateSuggestions, watchBoolean, watchNumber, watchValidator } from '@public-ui/schema';
+} from '../../schema';
+import { inputDateTypeOptions, setState, validateReadOnly, validateSuggestions, watchBoolean, watchNumber, watchValidator } from '../../schema';
import { InputIconController } from '../@deprecated/input/controller-icon';
import type { Generic } from 'adopted-style-sheets';
+
export class InputDateController extends InputIconController implements InputDateWatches {
// test: https://regex101.com/r/NTVh4L/1
private static readonly isoDateRegex = /^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])/;
@@ -44,38 +45,69 @@ export class InputDateController extends InputIconController implements InputDat
validateSuggestions(this.component, value);
}
- private tryParseToString(value?: Iso8601 | Date | null, defaultValue?: Date): string | null | undefined {
- const v: Iso8601 | Date | undefined = value ?? defaultValue;
- if (typeof v === 'string') {
- return v;
+ public static tryParseToString(value: Iso8601 | Date | null | undefined, type?: InputDateType, step?: string | number): string | null | undefined {
+ if (typeof value === 'string' || value === null) {
+ return value;
}
- if (typeof v === 'object' && v instanceof Date) {
- switch (this.component._type) {
+
+ if (typeof value === 'object' && value instanceof Date) {
+ const formattedYear = value.getFullYear();
+ const formattedMonth = String(value.getMonth() + 1).padStart(2, '0');
+ const formattedDay = String(value.getDate()).padStart(2, '0');
+ const formattedHours = String(value.getHours()).padStart(2, '0');
+ const formattedMinutes = String(value.getMinutes()).padStart(2, '0');
+ const formattedSeconds = String(value.getSeconds()).padStart(2, '0');
+
+ const formattedDate = [formattedYear, formattedMonth, formattedDay].join('-');
+ const formattedTimeWithSeconds = [formattedHours, formattedMinutes, formattedSeconds].join(':');
+
+ switch (type) {
case 'date':
- return `${v.getFullYear()}-${v.getMonth() + 1}-${v.getDate()}`;
+ return formattedDate;
case 'datetime-local':
- return `${v.getFullYear()}-${v.getMonth() + 1}-${v.getDate()}T${v.getHours()}:${v.getMinutes()}:${v.getSeconds()}`;
+ return `${formattedDate}T${formattedTimeWithSeconds}`;
case 'month':
- return `${v.getFullYear()}-${v.getMonth() + 1}`;
+ return `${formattedYear}-${formattedMonth}`;
case 'time':
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#using_the_step_attribute
- if (
- this.component._step === undefined ||
- (typeof this.component._step === 'string' && this.component._step === '60') ||
- (typeof this.component._step === 'number' && this.component._step === 60)
- ) {
- return `${v.getHours()}:${v.getMinutes()}`;
+ if (step === undefined || String(step) === '60') {
+ return `${formattedHours}:${formattedMinutes}`;
} else {
- return `${v.getHours()}:${v.getMinutes()}:${v.getSeconds()}`;
+ return formattedTimeWithSeconds;
}
case 'week':
- throw new Error('Auto convert to week is not supported!');
+ return `${formattedYear}-W${this.getWeekNumberOfDate(value)}`;
}
}
- if (value === null) {
- return null;
+ }
+
+ static getWeekNumberOfDate(date: Date): string {
+ const copiedDate = new Date(date);
+
+ // ISO week date weeks start on Monday, so correct the day number
+ const nDay = (copiedDate.getDay() + 6) % 7;
+
+ // ISO 8601 states that week 1 is the week with the first Thursday of that year
+ // Set the target date to the Thursday in the target week
+ copiedDate.setDate(copiedDate.getDate() - nDay + 3);
+
+ // Store the millisecond value of the target date
+ const n1stThursday = copiedDate.valueOf();
+
+ // Set the target to the first Thursday of the year
+ // First, set the target to January 1st
+ copiedDate.setMonth(0, 1);
+
+ // Not a Thursday? Correct the date to the next Thursday
+ if (copiedDate.getDay() !== 4) {
+ copiedDate.setMonth(0, 1 + ((4 - copiedDate.getDay() + 7) % 7));
}
- return undefined;
+
+ // The week number is the number of weeks between the first Thursday of the year
+ // and the Thursday in the target week (604800000 = 7 * 24 * 3600 * 1000)
+ const dayOfYear = 1 + Math.ceil((n1stThursday - copiedDate.valueOf()) / 604800000);
+
+ return dayOfYear.toString().padStart(2, '0');
}
private validateDateString(value: string): boolean {
@@ -101,7 +133,7 @@ export class InputDateController extends InputIconController implements InputDat
propName,
(value): boolean => value === undefined || value == null || value === '' || this.validateDateString(value),
new Set(['Date', 'string{ISO-8601}']),
- this.tryParseToString(value),
+ InputDateController.tryParseToString(value, this.component._type, this.component._step),
{
hooks: {
afterPatch: (value) => {
@@ -124,28 +156,17 @@ export class InputDateController extends InputIconController implements InputDat
}
public validateMax(value?: Iso8601 | Date): void {
- watchValidator(
- this.component,
- '_max',
- (value): boolean => value === undefined || (value !== null && this.validateDateString(value)),
- new Set(['Iso8601', 'Date']),
- this.tryParseToString(
- value,
- this.component._type === 'date' || this.component._type === 'month' || this.component._type === 'datetime-local'
- ? InputDateController.DEFAULT_MAX_DATE
- : undefined,
- ),
- );
+ const ensuredValue =
+ (value === undefined || value === null) &&
+ (this.component._type === 'date' || this.component._type === 'month' || this.component._type === 'datetime-local')
+ ? InputDateController.DEFAULT_MAX_DATE
+ : value;
+
+ this.validateIso8601('_max', ensuredValue);
}
public validateMin(value?: Iso8601 | Date): void {
- watchValidator(
- this.component,
- '_min',
- (value): boolean => value === undefined || (value !== null && this.validateDateString(value)),
- new Set(['Iso8601', 'Date']),
- this.tryParseToString(value),
- );
+ this.validateIso8601('_min', value);
}
public validateOn(value?: InputTypeOnDefault) {
diff --git a/packages/components/src/components/input-date/input-date.e2e.ts b/packages/components/src/components/input-date/input-date.e2e.ts
new file mode 100644
index 0000000000..cddf02d044
--- /dev/null
+++ b/packages/components/src/components/input-date/input-date.e2e.ts
@@ -0,0 +1,299 @@
+import { expect } from '@playwright/test';
+import { test } from '@stencil/playwright';
+import type { Iso8601 } from '../../schema';
+import { testInputCallbacksAndEvents } from '../../e2e';
+import type { FillAction } from '../../e2e/utils/FillAction';
+
+const TEST_VALUE_STRING = '2023-05-06';
+const TEST_VALUE_DATE = new Date(TEST_VALUE_STRING);
+
+test.describe('kol-input-date', () => {
+ test.describe('when value is Date object', () => {
+ const TEST_DATE = new Date('2020-03-03T03:02:01.099Z');
+
+ test('should set the correct value for type date', async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date;
+ }, TEST_DATE);
+ await expect(page.locator('input')).toHaveValue('2020-03-03');
+ });
+
+ test('should set the correct value for type datetime-local', async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date;
+ }, TEST_DATE);
+ await expect(page.locator('input')).toHaveValue('2020-03-03T04:02:01');
+ });
+
+ test('should set the correct value for type month', async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date;
+ }, TEST_DATE);
+ await expect(page.locator('input')).toHaveValue('2020-03');
+ });
+
+ test('should set the correct value for type time', async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date;
+ }, TEST_DATE);
+ await expect(page.locator('input')).toHaveValue('04:02');
+ });
+
+ const fillAction: FillAction = async (page) => {
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, value) => {
+ element._value = value;
+ }, TEST_VALUE_DATE);
+ };
+ testInputCallbacksAndEvents('kol-input-date', TEST_VALUE_DATE, fillAction, ['click', 'focus', 'blur'], undefined, undefined, 'toEqual'); // emitted events are tested independently of type
+ });
+
+ test.describe('when value is String', () => {
+ test('should set the correct value for type date', async ({ page }) => {
+ await page.setContent(` `);
+ await expect(page.locator('input')).toHaveValue('2020-03-03');
+ });
+
+ test('should set the correct value for type datetime-local', async ({ page }) => {
+ await page.setContent(` `);
+ await expect(page.locator('input')).toHaveValue('2020-03-03T04:02:01');
+ });
+
+ test('should set the correct value for type month', async ({ page }) => {
+ await page.setContent(` `);
+ await expect(page.locator('input')).toHaveValue('2020-03');
+ });
+
+ test('should set the correct value for type time', async ({ page }) => {
+ await page.setContent(` `);
+ await expect(page.locator('input')).toHaveValue('04:02');
+ });
+
+ testInputCallbacksAndEvents('kol-input-date', TEST_VALUE_STRING, undefined, ['click', 'focus', 'blur']); // emitted events are tested independently of type
+ });
+
+ test.describe('Value reflection', () => {
+ const testValues = [
+ { label: 'ISO String', value: '2020-03-03' as Iso8601 },
+ { label: 'Date Object', value: new Date('2020-03-03T03:02:01.099Z') },
+ ];
+
+ testValues.forEach(({ label, value }) => {
+ test.describe(`when initial value is a ${label}`, () => {
+ test(`should return the correct value for getValue() as ${label}`, async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date;
+ }, value);
+
+ const getValue = await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement) => {
+ return element.getValue();
+ });
+
+ if (value instanceof Date) {
+ expect(getValue).toBeInstanceOf(Date);
+ expect((getValue as Date).toISOString().split('T')[0]).toBe(value.toISOString().split('T')[0]);
+ } else {
+ expect(getValue).toBe(value);
+ }
+ });
+
+ test(`should reflect the correct _value property as ${label} on the web component`, async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement, date) => {
+ element._value = date; // set the initial value
+ }, value);
+
+ const NEW_DATE = '2021-03-03';
+ await page.locator('input').fill(NEW_DATE);
+
+ const valueDomProperty = await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement) => element._value);
+
+ if (value instanceof Date) {
+ expect(valueDomProperty).toBeInstanceOf(Date);
+ expect((valueDomProperty as Date).toISOString().split('T')[0]).toBe(new Date(NEW_DATE).toISOString().split('T')[0]);
+ } else {
+ expect(valueDomProperty).toBe(NEW_DATE);
+ }
+ });
+ });
+ });
+ });
+
+ test.describe('when min and max is set', () => {
+ test.describe('for Iso8601-Format', () => {
+ test('should set correct min and max for type date', async ({ page }) => {
+ const minDate = '2024-09-26';
+ const maxDate = '2024-09-27';
+ await page.setContent(` `);
+
+ await expect(page.locator('input')).toHaveAttribute('min', minDate);
+ await expect(page.locator('input')).toHaveAttribute('max', maxDate);
+ });
+
+ test('should set correct min and max for type time', async ({ page }) => {
+ const minTime = '12:00';
+ const maxTime = '15:00';
+ await page.setContent(` `);
+
+ await expect(page.locator('input')).toHaveAttribute('min', minTime);
+ await expect(page.locator('input')).toHaveAttribute('max', maxTime);
+ });
+
+ test('should set correct min and max for type datetime_locale', async ({ page }) => {
+ const minDayTime = '2024-09-26T12:00';
+ const maxDaytime = '2024-09-27T15:00';
+ await page.setContent(` `);
+
+ await expect(page.locator('input')).toHaveAttribute('min', minDayTime);
+ await expect(page.locator('input')).toHaveAttribute('max', maxDaytime);
+ });
+
+ test('should set correct min and max for type week', async ({ page }) => {
+ const minWeek = '2024-W10';
+ const maxWeek = '2024-W50';
+ await page.setContent(` `);
+
+ await expect(page.locator('input')).toHaveAttribute('min', minWeek);
+ await expect(page.locator('input')).toHaveAttribute('max', maxWeek);
+ });
+
+ test('should set correct min and max for type month', async ({ page }) => {
+ const minMonth = '2024-02';
+ const maxMonth = '2024-10';
+ await page.setContent(` `);
+
+ await expect(page.locator('input')).toHaveAttribute('min', minMonth);
+ await expect(page.locator('input')).toHaveAttribute('max', maxMonth);
+ });
+ });
+ test.describe('for Date-Format', () => {
+ let minDateFormat: Date;
+ let maxDateFormat: Date;
+
+ test.beforeEach(() => {
+ minDateFormat = new Date('2024-01-10T12:00:00Z');
+ maxDateFormat = new Date('2024-10-20T15:00:00Z');
+ });
+ test('should set correct min and max for type date', async ({ page }) => {
+ const minDate = '2024-01-10';
+ const maxDate = '2024-10-20';
+ await page.setContent(` `);
+
+ await page.locator('kol-input-date').evaluate(
+ (element: HTMLKolInputDateElement, { minDateFormat, maxDateFormat }) => {
+ element._min = minDateFormat;
+ element._max = maxDateFormat;
+ },
+ { minDateFormat, maxDateFormat },
+ );
+ await page.waitForChanges();
+
+ await expect(page.locator('input')).toHaveAttribute('min', minDate);
+ await expect(page.locator('input')).toHaveAttribute('max', maxDate);
+ });
+
+ test('should set correct min and max for type time', async ({ page }) => {
+ const minTime = '13:00';
+ const maxTime = '17:00';
+ await page.setContent(` `);
+
+ await page.locator('kol-input-date').evaluate(
+ (element: HTMLKolInputDateElement, { minDateFormat, maxDateFormat }) => {
+ element._min = minDateFormat;
+ element._max = maxDateFormat;
+ },
+ { minDateFormat, maxDateFormat },
+ );
+
+ await expect(page.locator('input')).toHaveAttribute('min', minTime);
+ await expect(page.locator('input')).toHaveAttribute('max', maxTime);
+ });
+
+ test('should set correct min and max for type datetime_locale', async ({ page }) => {
+ const minDayTime = '2024-01-10T13:00:00';
+ const maxDaytime = '2024-10-20T17:00:00';
+ await page.setContent(` `);
+
+ await page.locator('kol-input-date').evaluate(
+ (element: HTMLKolInputDateElement, { minDateFormat, maxDateFormat }) => {
+ element._min = minDateFormat;
+ element._max = maxDateFormat;
+ },
+ { minDateFormat, maxDateFormat },
+ );
+
+ await expect(page.locator('input')).toHaveAttribute('min', minDayTime);
+ await expect(page.locator('input')).toHaveAttribute('max', maxDaytime);
+ });
+
+ test('should set correct min and max for type week', async ({ page }) => {
+ const minWeek = '2024-W02';
+ const maxWeek = '2024-W42';
+ await page.setContent(` `);
+
+ await page.locator('kol-input-date').evaluate(
+ (element: HTMLKolInputDateElement, { minDateFormat, maxDateFormat }) => {
+ element._min = minDateFormat;
+ element._max = maxDateFormat;
+ },
+ { minDateFormat, maxDateFormat },
+ );
+
+ await expect(page.locator('input')).toHaveAttribute('min', minWeek);
+ await expect(page.locator('input')).toHaveAttribute('max', maxWeek);
+ });
+
+ test('should set correct min and max for type month', async ({ page }) => {
+ const minMonth = '2024-01';
+ const maxMonth = '2024-10';
+ await page.setContent(` `);
+
+ await page.locator('kol-input-date').evaluate(
+ (element: HTMLKolInputDateElement, { minDateFormat, maxDateFormat }) => {
+ element._min = minDateFormat;
+ element._max = maxDateFormat;
+ },
+ { minDateFormat, maxDateFormat },
+ );
+
+ await expect(page.locator('input')).toHaveAttribute('min', minMonth);
+ await expect(page.locator('input')).toHaveAttribute('max', maxMonth);
+ });
+ });
+ });
+
+ test.describe('when initial value is null', () => {
+ test('should set value as empty string', async ({ page }) => {
+ await page.setContent(' ');
+ await page.locator('kol-input-date').evaluate((element: HTMLKolInputDateElement) => {
+ element._value = null;
+ });
+ await expect(page.locator('input')).toHaveValue('');
+ });
+ });
+
+ test.describe('when _msg is set', () => {
+ test('should display and hide message based on _msg value', async ({ page }) => {
+ await page.setContent(` `);
+
+ await expect(page.locator('.kol-alert')).toBeVisible();
+
+ const input = page.locator('kol-input-date');
+ await input.evaluate((element: HTMLKolInputDateElement) => {
+ element._msg = undefined;
+ });
+
+ await expect(page.locator('.kol-alert')).not.toBeVisible();
+ });
+ });
+
+ testInputCallbacksAndEvents('kol-input-date', TEST_VALUE_STRING, undefined, ['input', 'change']); // emitted events are tested specifically for value type
+});
diff --git a/packages/components/src/components/input-date/readme.md b/packages/components/src/components/input-date/readme.md
deleted file mode 100644
index 81e6220f3d..0000000000
--- a/packages/components/src/components/input-date/readme.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# InputDate
-
-Der Input-Typ **Date** erzeugt ein Eingabefeld für Datumswerte. Diese können konkrete Daten sein, aber auch Wochen, Monate oder Zeitangaben.
-
-## Konstruktion
-
-### Code
-
-```html
-
-```
-
-### Beispiel
-
-
-
-#### Datum entfernen
-
-Folgendes Beispiel zeigt eine Component in React, die die Möglichkeit bietet über einen Button den Wert im Datumsfeld zu entfernen.
-
-```jsx
-const ClearableDateInput = () => {
- const [value, setValue] = useState();
- return (
- <>
- setValue(v) }}
- />
- {/* Set null as value to clear the inputs value. */}
- setValue(null) }} _label="Clear" />
- >
- );
-};
-```
-
-## Verwendung
-
-Die **InputDate**-Komponente kann für die Erfassung von Daten verwendet werden. Es verwendet intern die InputNumber-Komponente.
-
-Beachten Sie, dass im **Firefox** nicht alle **`_types`** der **InputDate**-Komponente funktional sind. Es werden bei den Typen `month`, `time` und `week` keine Auswahldialoge angezeigt.
-
-Die Komponente zeichnet sich dadurch aus, dass sie zahlreiche Ziffern-basierte Eingabemuster unterstützt. Hierbei ist es wichtig zu beachten, dass sich das Verhalten bei der Eingabe von Browser zu Browser und Geräte zu Gerät unterscheiden kann. Beispielsweise ist es möglich beim Datum, 01.01.999999 einzugeben, auch wenn max=2022-02-02 ist. Der Feldwert ist aber trotzdem 2022-02-02.
-
-### Best practices
-
-- Achten sie darauf `id` und `name` korrekt zu setzen, damit die Daten beim Formular Absenden mitgesendet werden.
-
-## Barrierefreiheit
-
-Die Icons in der Komponente sind per Tab-Taste nicht erreichbar. Die Auswahlhilfen der Komponente werden über die **Leertaste** geöffnet. So erhalten Sie beispielsweise beim Typ **date** ein Kalendermodul, über das per Maus oder über die Tastatur das gewünschte Datum ausgewählt werden kann. Die manuelle Eingabe der Werte ist alternativ möglich.
-
-### Tastatursteuerung
-
-Das Eingabefeld für Zeitangaben gibt es in unterschiedlichen Ausprägungen (Datum, Uhrzeit u.a). Mit der `Tab`-Taste wird der Fokus auf das Eingabefeld gesetzt. Anschließend kann mittels der `Leer`-Taste das gerätespezifische Auswahldialog geöffent werden.
-
-> Hinweis: Wir haben in unseren Tests festgestellt, dass es je nach Browser-Version manchmal möglich ist, das Kalender-Icon anzufokusieren und mal nicht. Ohne das sich die Implementierung der Komponente geändert hat. Warum das so ist ist uns noch nicht bekannt. Nichtsdestotrotz ist das Öffnen des Auswahldialogs immer mittels der `Leer`-Taste möglich.
-
-| Taste | Funktion |
-| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `Tab` | Fokussiert das Eingabefeld. Nach erhalt des Fokus wechselt die `Tab`-Taste durch die Eingabebereiche. Danach erst wechselt die `Tab`-Taste zum nächsten Eingabefeld. |
-| `Leer` | Wenn das Eingabefeld fokussiert ist, kann im Browser mit der `Leer`-Taste ein Auswahldialog aufgerufen bzw. geschlossen werden. Die Navigation und Auswahl erfolgt hier mit Hilfe der `Tab`-Taste, der `Pfeil`-Tasten und der Bestätigung mittes `Enter`-Taste. |
-| `Pfeil-Tasten (links / rechts)` | Wenn das Eingabefeld fokussiert ist, kann mit den `Pfeil`-Tasten zwischen den Eingabebereichen gewechselt werden. |
-| `Pfeil-Tasten (oben / unten)` | Wenn ein Eingabebereich aktiviert ist, können mit den `Pfeil`-Tasten oben und unten die Werte verändert werden. |
-| `Esc` | Ist ein Auswahldialog verfügbar, kann dieser alternativ zur `Leer`-Taste oder auch mit der `Esc`-Taste geschlossen werden. |
-
-## Links und Referenzen
-
--
--
--
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_accessKey` | `_access-key` | Defines which key combination can be used to trigger or focus the interactive element of the component. | `string \| undefined` | `undefined` |
-| `_alert` | `_alert` | Defines whether the screen-readers should read out the notification. | `boolean \| undefined` | `true` |
-| `_autoComplete` | `_auto-complete` | Defines whether the input can be auto-completed. | `"off" \| "on" \| undefined` | `undefined` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_error` | `_error` | **[DEPRECATED]** Will be removed in v3. Use `msg` instead. Defines the error message text. | `string \| undefined` | `undefined` |
-| `_hideError` | `_hide-error` | Hides the error message but leaves it in the DOM for the input's aria-describedby. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_hint` | `_hint` | Defines the hint text. | `string \| undefined` | `''` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `string \| undefined \| { right?: IconOrIconClass \| undefined; left?: IconOrIconClass \| undefined; }` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_max` | `_max` | Defines the largest possible input value. | `Date \| `${number}-${number}-${number}T${number}:${number}:${number}`\|`${number}-${number}-${number}T${number}:${number}` \| `${number}-${number}-${number}`\|`${number}-${number}`\|`${number}-W${number}`\|`${number}:${number}:${number}` \| `${number}:${number}` \| undefined` | `undefined` |
-| `_min` | `_min` | Defines the smallest possible input value. | `Date \| `${number}-${number}-${number}T${number}:${number}:${number}`\|`${number}-${number}-${number}T${number}:${number}` \| `${number}-${number}-${number}`\|`${number}-${number}`\|`${number}-W${number}`\|`${number}:${number}:${number}` \| `${number}:${number}` \| undefined` | `undefined` |
-| `_msg` | -- | Defines the properties for a message rendered as Alert component. | `undefined \| {} & { _level?: 0 \| 2 \| 1 \| 3 \| 4 \| 5 \| 6 \| undefined; _on?: KoliBriAlertEventCallbacks \| undefined; _type?: "error" \| "warning" \| "info" \| "success" \| "default" \| undefined; _variant?: "card" \| "msg" \| undefined; _label?: string \| undefined; _alert?: boolean \| undefined; _hasCloser?: boolean \| undefined; } & { _description: string; }` | `undefined` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für das Input-Event an. | `InputTypeOnBlur & InputTypeOnClick & InputTypeOnChange & InputTypeOnFocus & InputTypeOnInput \| undefined` | `undefined` |
-| `_readOnly` | `_read-only` | Makes the input element read only. | `boolean \| undefined` | `false` |
-| `_required` | `_required` | Makes the input element required. | `boolean \| undefined` | `false` |
-| `_smartButton` | `_smart-button` | Allows to add a button with an arbitrary action within the element (\_hide-label only). | `string \| undefined \| { _label: string; } & { _tabIndex?: number \| undefined; _value?: Stringified; _role?: AlternativeButtonLinkRolePropType \| undefined; _ariaControls?: string \| undefined; _ariaExpanded?: boolean \| undefined; _ariaSelected?: boolean \| undefined; _on?: ButtonCallbacksPropType \| undefined; _type?: "button" \| "reset" \| "submit" \| undefined; _variant?: "primary" \| "secondary" \| "normal" \| "tertiary" \| "danger" \| "ghost" \| "custom" \| undefined; _customClass?: string \| undefined; _disabled?: boolean \| undefined; _hideLabel?: boolean \| undefined; _icons?: IconsPropType \| undefined; _id?: string \| undefined; _name?: string \| undefined; _syncValueBySelector?: string \| undefined; _tooltipAlign?: AlignPropType \| undefined; _accessKey?: string \| undefined; }` | `undefined` |
-| `_step` | `_step` | Defines the step size for value changes. | `number \| undefined` | `undefined` |
-| `_suggestions` | `_suggestions` | Suggestions to provide for the input. | `W3CInputValue[] \| string \| undefined` | `undefined` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_touched` | `_touched` | Shows if the input was touched by a user. | `boolean \| undefined` | `false` |
-| `_type` | `_type` | Defines either the type of the component or of the components interactive element. | `"date" \| "datetime-local" \| "month" \| "time" \| "week"` | `'date'` |
-| `_value` | `_value` | Defines the value of the input. | `Date \| `${number}-${number}-${number}T${number}:${number}:${number}`\|`${number}-${number}-${number}T${number}:${number}` \| `${number}-${number}-${number}`\|`${number}-${number}`\|`${number}-W${number}`\|`${number}:${number}:${number}` \| `${number}:${number}` \| null \| undefined` | `undefined` |
-
-## Methods
-
-### `getValue() => Promise`
-
-#### Returns
-
-Type: `Promise`
-
-## Slots
-
-| Slot | Description |
-| ---- | ----------------------------------- |
-| | Die Beschriftung des Eingabefeldes. |
-
----
diff --git a/packages/components/src/components/input-date/shadow.tsx b/packages/components/src/components/input-date/shadow.tsx
new file mode 100644
index 0000000000..72ad42ff78
--- /dev/null
+++ b/packages/components/src/components/input-date/shadow.tsx
@@ -0,0 +1,463 @@
+import type { JSX } from '@stencil/core';
+import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core';
+import clsx from 'clsx';
+
+import type {
+ ButtonProps,
+ FocusableElement,
+ HideErrorPropType,
+ IdPropType,
+ InputDateAPI,
+ InputDateStates,
+ InputDateType,
+ InputTypeOnDefault,
+ InputTypeOnOff,
+ Iso8601,
+ KoliBriHorizontalIcons,
+ LabelWithExpertSlotPropType,
+ MsgPropType,
+ NamePropType,
+ ReadOnlyPropType,
+ ShortKeyPropType,
+ Stringified,
+ SuggestionsPropType,
+ SyncValueBySelectorPropType,
+ TooltipAlignPropType,
+} from '../../schema';
+import { deprecatedHint } from '../../schema';
+
+import { nonce } from '../../utils/dev.utils';
+import { propagateSubmitEventToForm } from '../form/controller';
+import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper';
+import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper';
+import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper';
+import { InputDateController } from './controller';
+
+/**
+ * @slot - Die Beschriftung des Eingabefeldes.
+ */
+@Component({
+ tag: 'kol-input-date',
+ styleUrls: {
+ default: './style.scss',
+ },
+ shadow: {
+ delegatesFocus: true,
+ },
+})
+export class KolInputDate implements InputDateAPI, FocusableElement {
+ @Element() private readonly host?: HTMLKolInputDateElement;
+ private inputRef?: HTMLInputElement;
+
+ @State() private _initialValueType: 'Date' | 'String' | null = null;
+
+ private readonly catchRef = (ref?: HTMLInputElement) => {
+ this.inputRef = ref;
+ };
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async getValue(): Promise {
+ return this.inputRef && this.remapValue(this.inputRef?.value);
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async kolFocus() {
+ this.inputRef?.focus();
+ }
+
+ @Method()
+ // eslint-disable-next-line @typescript-eslint/require-await
+ public async reset() {
+ this.state = {
+ ...this.state,
+ _value: null,
+ };
+ this.controller.setFormAssociatedValue('');
+
+ // Setting the state value might not trigger a state change and rerender if the previous value is already an empty string,
+ // which can occur during an incomplete input. Directly setting the DOM property "forces" a reset of the native element.
+ if (this.inputRef) {
+ this.inputRef.value = '';
+ }
+ }
+
+ private setInitialValueType(value: Iso8601 | Date | null) {
+ if (value instanceof Date) {
+ this._initialValueType = 'Date';
+ } else if (typeof value === 'string') {
+ this._initialValueType = 'String';
+ } else {
+ this._initialValueType = null;
+ }
+ }
+ private remapValue(newValue: string): Date | Iso8601 {
+ return this._initialValueType === 'Date' ? new Date(newValue) : (newValue as Iso8601);
+ }
+
+ private readonly onBlur = (event: Event) => {
+ this.controller.onFacade.onBlur(event);
+ this.inputHasFocus = false;
+ };
+
+ private readonly onFocus = (event: Event) => {
+ this.controller.onFacade.onFocus(event);
+ this.inputHasFocus = true;
+ };
+
+ private readonly onChange = (event: Event) => {
+ const newValue = (event.target as HTMLInputElement).value;
+ const remappedValue = this.remapValue(newValue);
+ this.controller.onFacade.onChange(event, remappedValue);
+ };
+
+ private readonly onInput = (event: Event) => {
+ const newValue = (event.target as HTMLInputElement).value;
+ const remappedValue = this.remapValue(newValue);
+ this._value = remappedValue;
+ this.controller.onFacade.onInput(event, true, remappedValue);
+ };
+
+ private readonly onKeyDown = (event: KeyboardEvent) => {
+ if (event.code === 'Enter' || event.code === 'NumpadEnter') {
+ propagateSubmitEventToForm({
+ form: this.host,
+ ref: this.inputRef,
+ });
+ }
+ };
+
+ private getFormFieldProps(): FormFieldStateWrapperProps {
+ return {
+ state: this.state,
+ class: clsx('kol-input-date', this.state._type as string, {
+ 'has-value': this.state._hasValue,
+ }),
+ tooltipAlign: this._tooltipAlign,
+ onClick: () => this.inputRef?.focus(),
+ alert: this.showAsAlert(),
+ };
+ }
+
+ private getInputProps(): InputStateWrapperProps {
+ return {
+ ref: this.catchRef,
+ state: this.state,
+ ...this.controller.onFacade,
+ onBlur: this.onBlur,
+ onFocus: this.onFocus,
+ onKeyDown: this.onKeyDown,
+ onChange: this.onChange,
+ onInput: this.onInput,
+ };
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+ );
+ }
+
+ private readonly controller: InputDateController;
+
+ /**
+ * Defines which key combination can be used to trigger or focus the interactive element of the component.
+ */
+ @Prop() public _accessKey?: string;
+
+ /**
+ * Defines whether the input can be auto-completed.
+ */
+ @Prop() public _autoComplete?: InputTypeOnOff;
+
+ /**
+ * Makes the element not focusable and ignore all events.
+ * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _disabled?: boolean = false;
+
+ /**
+ * Hides the error message but leaves it in the DOM for the input's aria-describedby.
+ * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
+
+ /**
+ * Hides the caption by default and displays the caption text with a tooltip when the
+ * interactive element is focused or the mouse is over it.
+ * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _hideLabel?: boolean = false;
+
+ /**
+ * Defines the hint text.
+ */
+ @Prop() public _hint?: string = '';
+
+ /**
+ * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
+ */
+ @Prop() public _icons?: Stringified;
+
+ /**
+ * Defines the internal ID of the primary component element.
+ */
+ @Prop() public _id?: IdPropType;
+
+ /**
+ * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
+ */
+ @Prop() public _label!: LabelWithExpertSlotPropType;
+
+ /**
+ * Defines the largest possible input value.
+ */
+ @Prop() public _max?: Iso8601 | Date;
+
+ /**
+ * Defines the smallest possible input value.
+ */
+ @Prop() public _min?: Iso8601 | Date;
+
+ /**
+ * Defines the properties for a message rendered as Alert component.
+ */
+ @Prop() public _msg?: Stringified;
+
+ /**
+ * Defines the technical name of an input field.
+ */
+ @Prop() public _name?: NamePropType;
+
+ /**
+ * Gibt die EventCallback-Funktionen für das Input-Event an.
+ */
+ @Prop() public _on?: InputTypeOnDefault;
+
+ /**
+ * Makes the input element read only.
+ * @TODO: Change type back to `ReadOnlyPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _readOnly?: boolean = false;
+
+ /**
+ * Makes the input element required.
+ * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop() public _required?: boolean = false;
+
+ /**
+ * Adds a visual short key hint to the component.
+ */
+ @Prop() public _shortKey?: ShortKeyPropType;
+
+ /**
+ * Allows to add a button with an arbitrary action within the element (_hide-label only).
+ */
+ @Prop() public _smartButton?: Stringified;
+
+ /**
+ * Suggestions to provide for the input.
+ */
+ @Prop() public _suggestions?: SuggestionsPropType;
+
+ /**
+ * Selector for synchronizing the value with another input element.
+ * @internal
+ */
+ @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
+
+ /**
+ * Defines the step size for value changes.
+ */
+ @Prop() public _step?: number;
+
+ /**
+ * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
+ */
+ @Prop() public _tabIndex?: number;
+
+ /**
+ * Defines where to show the Tooltip preferably: top, right, bottom or left.
+ */
+ @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
+
+ /**
+ * Shows if the input was touched by a user.
+ * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
+ */
+ @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
+
+ /**
+ * Defines either the type of the component or of the components interactive element.
+ */
+ @Prop() public _type: InputDateType = 'date';
+
+ /**
+ * Defines the value of the input.
+ */
+ @Prop({ mutable: true, reflect: true }) public _value?: Iso8601 | Date | null;
+
+ @State() public state: InputDateStates = {
+ _autoComplete: 'off',
+ _hasValue: false,
+ _hideError: false,
+ _id: `id-${nonce()}`,
+ _label: '', // ⚠ required
+ _suggestions: [],
+ _type: 'datetime-local',
+ };
+
+ @State() private inputHasFocus = false;
+
+ public constructor() {
+ this.controller = new InputDateController(this, 'date', this.host);
+ }
+
+ private showAsAlert(): boolean {
+ return Boolean(this.state._touched) && !this.inputHasFocus;
+ }
+
+ @Watch('_accessKey')
+ public validateAccessKey(value?: string): void {
+ this.controller.validateAccessKey(value);
+ }
+
+ @Watch('_autoComplete')
+ public validateAutoComplete(value?: InputTypeOnOff): void {
+ this.controller.validateAutoComplete(value);
+ }
+
+ @Watch('_disabled')
+ public validateDisabled(value?: boolean): void {
+ this.controller.validateDisabled(value);
+ }
+
+ @Watch('_hideError')
+ public validateHideError(value?: HideErrorPropType): void {
+ this.controller.validateHideError(value);
+ }
+
+ @Watch('_hideLabel')
+ public validateHideLabel(value?: boolean): void {
+ this.controller.validateHideLabel(value);
+ }
+
+ @Watch('_hint')
+ public validateHint(value?: string): void {
+ this.controller.validateHint(value);
+ }
+
+ @Watch('_icons')
+ public validateIcons(value?: Stringified): void {
+ this.controller.validateIcons(value);
+ }
+
+ @Watch('_id')
+ public validateId(value?: string): void {
+ this.controller.validateId(value);
+ }
+
+ @Watch('_label')
+ public validateLabel(value?: LabelWithExpertSlotPropType): void {
+ this.controller.validateLabel(value);
+ }
+
+ @Watch('_max')
+ public validateMax(value?: Iso8601 | Date): void {
+ this.controller.validateMax(value);
+ }
+
+ @Watch('_min')
+ public validateMin(value?: Iso8601 | Date): void {
+ this.controller.validateMin(value);
+ }
+
+ @Watch('_msg')
+ public validateMsg(value?: Stringified): void {
+ this.controller.validateMsg(value);
+ }
+
+ @Watch('_name')
+ public validateName(value?: string): void {
+ this.controller.validateName(value);
+ }
+
+ @Watch('_on')
+ public validateOn(value?: InputTypeOnDefault): void {
+ this.controller.validateOn(value);
+ }
+
+ @Watch('_readOnly')
+ public validateReadOnly(value?: ReadOnlyPropType): void {
+ this.controller.validateReadOnly(value);
+ }
+
+ @Watch('_required')
+ public validateRequired(value?: boolean): void {
+ this.controller.validateRequired(value);
+ }
+
+ @Watch('_shortKey')
+ public validateShortKey(value?: ShortKeyPropType): void {
+ this.controller.validateShortKey(value);
+ }
+
+ @Watch('_smartButton')
+ public validateSmartButton(value?: ButtonProps | string): void {
+ this.controller.validateSmartButton(value);
+ }
+
+ @Watch('_suggestions')
+ public validateSuggestions(value?: SuggestionsPropType): void {
+ this.controller.validateSuggestions(value);
+ }
+
+ @Watch('_step')
+ public validateStep(value?: number): void {
+ this.controller.validateStep(value);
+ }
+
+ @Watch('_syncValueBySelector')
+ public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
+ this.controller.validateSyncValueBySelector(value);
+ }
+
+ @Watch('_tabIndex')
+ public validateTabIndex(value?: number): void {
+ this.controller.validateTabIndex(value);
+ }
+
+ @Watch('_touched')
+ public validateTouched(value?: boolean): void {
+ this.controller.validateTouched(value);
+ }
+
+ @Watch('_type')
+ public validateType(value?: InputDateType): void {
+ this.controller.validateType(value);
+ }
+
+ @Watch('_value')
+ public validateValue(value?: Iso8601 | Date | null): void {
+ if (value instanceof Date) {
+ deprecatedHint('Date type will be removed in v3. Use `Iso8601` instead.');
+ }
+ this.controller.validateValueEx(value);
+ if (value !== undefined) this.setInitialValueType(value);
+ }
+
+ public componentWillLoad(): void {
+ if (this._value !== undefined) this.setInitialValueType(this._value);
+ this._touched = this._touched === true;
+ this.controller.componentWillLoad();
+
+ this.state._hasValue = !!this.state._value;
+ this.controller.addValueChangeListener((v) => (this.state._hasValue = !!v));
+ }
+}
diff --git a/packages/components/src/components/input-date/style.scss b/packages/components/src/components/input-date/style.scss
index 48ca837213..0afb4a2557 100644
--- a/packages/components/src/components/input-date/style.scss
+++ b/packages/components/src/components/input-date/style.scss
@@ -1,10 +1,11 @@
-@import '../input-line';
-@import '../@shared/kol-alert-mixin.scss';
+@import '../../styles/global';
+@import '../../styles/kol-alert-mixin';
+@import '../../styles/kol-form-field-mixin';
+@import '../../styles/kol-input-container-mixin';
+@import '../../styles/kol-input-mixin';
+@import '../@shared/mixins';
-@include kol-alert-styles;
-
-@layer kol-component {
- .kol-input-number {
- display: block;
- }
-}
+@include kol-alert;
+@include kol-form-field;
+@include kol-input-container;
+@include kol-input;
diff --git a/packages/components/src/components/input-date/test/__snapshots__/snapshot.spec.tsx.snap b/packages/components/src/components/input-date/test/__snapshots__/snapshot.spec.tsx.snap
new file mode 100644
index 0000000000..d98ab88a58
--- /dev/null
+++ b/packages/components/src/components/input-date/test/__snapshots__/snapshot.spec.tsx.snap
@@ -0,0 +1,319 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _accessKey="V" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _alert=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _disabled=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _hint="Hint" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _icons={"left":{"icon":"codicon codicon-arrow-left"},"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _icons={"left":{"icon":"codicon codicon-arrow-left"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _icons={"right":{"icon":"codicon codicon-arrow-right"}} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} _hideError=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _msg={"_type":"error","_description":"Es ist ein Fehler aufgetreten"} 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _readOnly=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _shortKey="S" 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" _touched=true 1`] = `
+
+
+
+
+
+`;
+
+exports[`kol-input-date should render with _label="Label" _name="field" _placeholder="Hier steht ein Platzhaltertext" _value="2025-01-01" 1`] = `
+
+
+
+
+
+`;
diff --git a/packages/components/src/components/input-date/test/html.mock.ts b/packages/components/src/components/input-date/test/html.mock.ts
deleted file mode 100644
index 5f9092eed5..0000000000
--- a/packages/components/src/components/input-date/test/html.mock.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import type { InputDateProps, InputDateStates } from '@public-ui/schema';
-import { mixMembers } from 'stencil-awesome-test';
-import { nonce } from '../../../utils/dev.utils';
-import { KolInputTag } from '../../../core/component-names';
-import { showExpertSlot } from '@public-ui/schema';
-import { getRenderStates } from '../../input/controller';
-
-export const getInputDateHtml = (props: InputDateProps): string => {
- const state = mixMembers(
- {
- _autoComplete: 'off',
- _hasValue: false,
- _hideError: false,
- _id: `id-${nonce()}`,
- _label: '', // ⚠ required
- _suggestions: [],
- _type: 'datetime-local',
- },
- props,
- );
- const hasExpertSlot = showExpertSlot(state._label);
- const { ariaDescribedBy } = getRenderStates(state);
- return `
-
-
- <${KolInputTag}
- ${state._disabled ? `_disabled=""` : ''}
- ${state._hideLabel ? `_hideLabel=""` : ''}
- ${state._required ? `_required=""` : ''}
- ${state._readOnly ? `_readonly=""` : ''}
- ${state._touched ? `_touched=""` : ''}
- _hint=""
- _id="${state._id}"
- _label="${state._label ? `${state._label}` : ''}"
- _tooltipalign="top"
- class="date ${state._hideLabel ? `hide-label` : ''}"
- >
- ${
- hasExpertSlot
- ? ` `
- : typeof state._accessKey === 'string'
- ? `
- ${state._label}
-
- ${state._accessKey}
-
- `
- : ` ${state._label} `
- }
-
-
- 0 ? `aria-describedby="${ariaDescribedBy.join(' ')}"` : ''}
- >
-
- ${KolInputTag}>
-
- `;
-};
diff --git a/packages/components/src/components/input-date/test/snapshot.spec.tsx b/packages/components/src/components/input-date/test/snapshot.spec.tsx
index 93c998f216..eefd773f4a 100644
--- a/packages/components/src/components/input-date/test/snapshot.spec.tsx
+++ b/packages/components/src/components/input-date/test/snapshot.spec.tsx
@@ -1,43 +1,10 @@
-import { executeTests } from 'stencil-awesome-test';
+import { KolInputDateTag } from '../../../core/component-names';
+import type { InputDateProps } from '../../../schema';
+import { executeInputSnapshotTests } from '../../../utils/testing';
-import { h } from '@stencil/core';
-import { newSpecPage } from '@stencil/core/testing';
+import { KolInputDate } from '../shadow';
-import { getInputDateHtml } from './html.mock';
-
-import type { SpecPage } from '@stencil/core/testing';
-import type { InputDateProps } from '@public-ui/schema';
-import { KolInputDate } from '../component';
-
-executeTests(
- 'InputDate',
- async (props): Promise => {
- const page = await newSpecPage({
- components: [KolInputDate],
- template: () => ,
- });
- return page;
- },
- {
- _label: ['Label'],
- _hideLabel: [true, false],
- _disabled: [true, false],
- _alert: [true, false],
- _readOnly: [true, false],
- _msg: [{ _type: 'error', _description: 'Error message' }],
- _required: [true, false],
- _touched: [true, false],
- _smartButton: [
- {
- _icons: ['codicon codicon-eye'],
- _hideLabel: true,
- _label: 'einblenden',
- },
- ],
- },
- getInputDateHtml,
- {
- execMode: 'default', // ready
- needTimers: true,
- },
-);
+executeInputSnapshotTests(KolInputDateTag, [KolInputDate], {
+ _value: '2025-01-01',
+ // _suggestions: [ ]
+});
diff --git a/packages/components/src/components/input-email/component.tsx b/packages/components/src/components/input-email/component.tsx
deleted file mode 100644
index d846c4a84d..0000000000
--- a/packages/components/src/components/input-email/component.tsx
+++ /dev/null
@@ -1,461 +0,0 @@
-import type {
- ButtonProps,
- HideErrorPropType,
- IdPropType,
- InputEmailAPI,
- InputEmailStates,
- InputTypeOnDefault,
- InputTypeOnOff,
- KoliBriHorizontalIcons,
- LabelWithExpertSlotPropType,
- MsgPropType,
- MultiplePropType,
- NamePropType,
- Stringified,
- SuggestionsPropType,
- SyncValueBySelectorPropType,
- TooltipAlignPropType,
-} from '@public-ui/schema';
-import { propagateFocus, setState, showExpertSlot } from '@public-ui/schema';
-import { Component, Element, Fragment, h, Host, Method, Prop, State, Watch } from '@stencil/core';
-
-import { nonce } from '../../utils/dev.utils';
-import { propagateSubmitEventToForm } from '../form/controller';
-import { getRenderStates } from '../input/controller';
-import { InternalUnderlinedAccessKey } from '../span/InternalUnderlinedAccessKey';
-import { InputEmailController } from './controller';
-
-import type { JSX } from '@stencil/core';
-import { KolInputTag } from '../../core/component-names';
-/**
- * @slot - Die Beschriftung des Eingabefeldes.
- */
-@Component({
- tag: 'kol-input-email',
- styleUrls: {
- default: './style.scss',
- },
- shadow: true,
-})
-export class KolInputEmail implements InputEmailAPI {
- @Element() private readonly host?: HTMLKolInputEmailElement;
- private ref?: HTMLInputElement;
-
- private readonly catchRef = (ref?: HTMLInputElement) => {
- this.ref = ref;
- propagateFocus(this.host, this.ref);
- };
-
- @Method()
- // eslint-disable-next-line @typescript-eslint/require-await
- public async getValue(): Promise {
- return this.ref?.value;
- }
-
- private readonly onKeyDown = (event: KeyboardEvent) => {
- if (event.code === 'Enter' || event.code === 'NumpadEnter') {
- propagateSubmitEventToForm({
- form: this.host,
- ref: this.ref,
- });
- }
- };
-
- private readonly onInput = (event: InputEvent) => {
- setState(this, '_currentLength', (event.target as HTMLInputElement).value.length);
- this.controller.onFacade.onInput(event);
- };
-
- public render(): JSX.Element {
- const { ariaDescribedBy } = getRenderStates(this.state);
- const hasSuggestions = Array.isArray(this.state._suggestions) && this.state._suggestions.length > 0;
- const hasExpertSlot = showExpertSlot(this.state._label);
-
- return (
-
- this.ref?.focus()}
- role={`presentation` /* Avoid element being read as 'clickable' in NVDA */}
- >
-
- {hasExpertSlot ? (
-
- ) : typeof this.state._accessKey === 'string' ? (
- <>
- {' '}
-
- {this.state._accessKey}
-
- >
- ) : (
- {this.state._label}
- )}
-
-
- 0 ? ariaDescribedBy.join(' ') : undefined}
- aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
- autoCapitalize="off"
- autoComplete={this.state._autoComplete}
- autoCorrect="off"
- disabled={this.state._disabled}
- multiple={this.state._multiple}
- id={this.state._id}
- list={hasSuggestions ? `${this.state._id}-list` : undefined}
- maxlength={this.state._maxLength}
- name={this.state._name}
- pattern={this.state._pattern}
- placeholder={this.state._placeholder}
- readOnly={this.state._readOnly}
- required={this.state._required}
- spellcheck="false"
- type="email"
- value={this.state._value as string}
- {...this.controller.onFacade}
- onKeyDown={this.onKeyDown}
- onInput={this.onInput}
- />
-
-
-
- );
- }
-
- private readonly controller: InputEmailController;
-
- /**
- * Defines which key combination can be used to trigger or focus the interactive element of the component.
- */
- @Prop() public _accessKey?: string;
-
- /**
- * Defines whether the screen-readers should read out the notification.
- */
- @Prop({ mutable: true, reflect: true }) public _alert?: boolean = true;
-
- /**
- * Defines whether the input can be auto-completed.
- */
- @Prop() public _autoComplete?: InputTypeOnOff;
-
- /**
- * Makes the element not focusable and ignore all events.
- * @TODO: Change type back to `DisabledPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _disabled?: boolean = false;
-
- /**
- * Defines the error message text.
- */
- @Prop() public _error?: string;
-
- /**
- * Shows the character count on the lower border of the input.
- * @TODO: Change type back to `HasCounterPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hasCounter?: boolean = false;
-
- /**
- * Hides the error message but leaves it in the DOM for the input's aria-describedby.
- * @TODO: Change type back to `HideErrorPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _hideError?: boolean = false;
-
- /**
- * Hides the caption by default and displays the caption text with a tooltip when the
- * interactive element is focused or the mouse is over it.
- * @TODO: Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _hideLabel?: boolean = false;
-
- /**
- * Defines the hint text.
- */
- @Prop() public _hint?: string = '';
-
- /**
- * Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`).
- */
- @Prop() public _icons?: Stringified;
-
- /**
- * Defines the internal ID of the primary component element.
- */
- @Prop() public _id?: IdPropType;
-
- /**
- * Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot.
- */
- @Prop() public _label!: LabelWithExpertSlotPropType;
-
- /**
- * Defines the maximum number of input characters.
- */
- @Prop() public _maxLength?: number;
-
- /**
- * Defines the properties for a message rendered as Alert component.
- */
- @Prop() public _msg?: MsgPropType;
-
- /**
- * Makes the input accept multiple inputs.
- * @TODO: Change type back to `MultiplePropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _multiple?: boolean = false;
-
- /**
- * Defines the technical name of an input field.
- */
- @Prop() public _name?: NamePropType;
-
- /**
- * Gibt die EventCallback-Funktionen für das Input-Event an.
- */
- @Prop() public _on?: InputTypeOnDefault;
-
- /**
- * Defines a validation pattern for the input field.
- */
- @Prop() public _pattern?: string;
-
- /**
- * Defines the placeholder for input field. To be shown when there's no value.
- */
- @Prop() public _placeholder?: string;
-
- /**
- * Makes the input element read only.
- * @TODO: Change type back to `ReadOnlyPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _readOnly?: boolean = false;
-
- /**
- * Makes the input element required.
- * @TODO: Change type back to `RequiredPropType` after Stencil#4663 has been resolved.
- */
- @Prop() public _required?: boolean = false;
-
- /**
- * Allows to add a button with an arbitrary action within the element (_hide-label only).
- */
- @Prop() public _smartButton?: Stringified;
-
- /**
- * Suggestions to provide for the input.
- */
- @Prop() public _suggestions?: SuggestionsPropType;
-
- /**
- * Selector for synchronizing the value with another input element.
- * @internal
- */
- @Prop() public _syncValueBySelector?: SyncValueBySelectorPropType;
-
- /**
- * Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
- */
- @Prop() public _tabIndex?: number;
-
- /**
- * Defines where to show the Tooltip preferably: top, right, bottom or left.
- */
- @Prop() public _tooltipAlign?: TooltipAlignPropType = 'top';
-
- /**
- * Shows if the input was touched by a user.
- * @TODO: Change type back to `TouchedPropType` after Stencil#4663 has been resolved.
- */
- @Prop({ mutable: true, reflect: true }) public _touched?: boolean = false;
-
- /**
- * Defines the value of the input.
- */
- @Prop() public _value?: string;
-
- @State() public state: InputEmailStates = {
- _autoComplete: 'off',
- _currentLength: 0,
- _hasValue: false,
- _hideError: false,
- _id: `id-${nonce()}`,
- _label: '', // ⚠ required
- _suggestions: [],
- };
-
- public constructor() {
- this.controller = new InputEmailController(this, 'email', this.host);
- }
-
- @Watch('_accessKey')
- public validateAccessKey(value?: string): void {
- this.controller.validateAccessKey(value);
- }
-
- @Watch('_alert')
- public validateAlert(value?: boolean): void {
- this.controller.validateAlert(value);
- }
-
- @Watch('_autoComplete')
- public validateAutoComplete(value?: InputTypeOnOff): void {
- this.controller.validateAutoComplete(value);
- }
-
- @Watch('_disabled')
- public validateDisabled(value?: boolean): void {
- this.controller.validateDisabled(value);
- }
-
- @Watch('_error')
- public validateError(value?: string): void {
- this.controller.validateError(value);
- }
-
- @Watch('_hasCounter')
- public validateHasCounter(value?: boolean): void {
- this.controller.validateHasCounter(value);
- }
-
- @Watch('_hideError')
- public validateHideError(value?: HideErrorPropType): void {
- this.controller.validateHideError(value);
- }
-
- @Watch('_hideLabel')
- public validateHideLabel(value?: boolean): void {
- this.controller.validateHideLabel(value);
- }
-
- @Watch('_hint')
- public validateHint(value?: string): void {
- this.controller.validateHint(value);
- }
-
- @Watch('_icons')
- public validateIcons(value?: Stringified): void {
- this.controller.validateIcons(value);
- }
-
- @Watch('_id')
- public validateId(value?: string): void {
- this.controller.validateId(value);
- }
-
- @Watch('_label')
- public validateLabel(value?: LabelWithExpertSlotPropType): void {
- this.controller.validateLabel(value);
- }
-
- @Watch('_maxLength')
- public validateMaxLength(value?: number): void {
- this.controller.validateMaxLength(value);
- }
-
- @Watch('_msg')
- public validateMsg(value?: MsgPropType): void {
- this.controller.validateMsg(value);
- }
-
- @Watch('_multiple')
- public validateMultiple(value?: MultiplePropType): void {
- this.controller.validateMultiple(value);
- }
-
- @Watch('_name')
- public validateName(value?: string): void {
- this.controller.validateName(value);
- }
-
- @Watch('_on')
- public validateOn(value?: InputTypeOnDefault): void {
- this.controller.validateOn(value);
- }
-
- @Watch('_pattern')
- public validatePattern(value?: string): void {
- this.controller.validatePattern(value);
- }
-
- @Watch('_placeholder')
- public validatePlaceholder(value?: string): void {
- this.controller.validatePlaceholder(value);
- }
-
- @Watch('_readOnly')
- public validateReadOnly(value?: boolean): void {
- this.controller.validateReadOnly(value);
- }
-
- @Watch('_required')
- public validateRequired(value?: boolean): void {
- this.controller.validateRequired(value);
- }
-
- @Watch('_suggestions')
- public validateSuggestions(value?: SuggestionsPropType): void {
- this.controller.validateSuggestions(value);
- }
-
- @Watch('_smartButton')
- public validateSmartButton(value?: ButtonProps | string): void {
- this.controller.validateSmartButton(value);
- }
-
- @Watch('_syncValueBySelector')
- public validateSyncValueBySelector(value?: SyncValueBySelectorPropType): void {
- this.controller.validateSyncValueBySelector(value);
- }
-
- @Watch('_tabIndex')
- public validateTabIndex(value?: number): void {
- this.controller.validateTabIndex(value);
- }
-
- @Watch('_touched')
- public validateTouched(value?: boolean): void {
- this.controller.validateTouched(value);
- }
-
- @Watch('_value')
- public validateValue(value?: string): void {
- this.controller.validateValue(value);
- }
-
- public componentWillLoad(): void {
- this._alert = this._alert === true;
- this._touched = this._touched === true;
- this.controller.componentWillLoad();
-
- this.state._hasValue = !!this.state._value;
- this.controller.addValueChangeListener((v) => (this.state._hasValue = !!v));
- }
-}
diff --git a/packages/components/src/components/input-email/controller.ts b/packages/components/src/components/input-email/controller.ts
index e82c37e020..76f41bc2da 100644
--- a/packages/components/src/components/input-email/controller.ts
+++ b/packages/components/src/components/input-email/controller.ts
@@ -1,7 +1,7 @@
import type { Generic } from 'adopted-style-sheets';
-import type { InputEmailProps, InputEmailWatches, MultiplePropType } from '@public-ui/schema';
-import { validateMultiple } from '@public-ui/schema';
+import type { InputEmailProps, InputEmailWatches, MultiplePropType } from '../../schema';
+import { validateMultiple } from '../../schema';
import { InputTextEmailController } from '../input-text/controller';
diff --git a/packages/components/src/components/input-email/input-email.e2e.ts b/packages/components/src/components/input-email/input-email.e2e.ts
new file mode 100644
index 0000000000..b9e316ade9
--- /dev/null
+++ b/packages/components/src/components/input-email/input-email.e2e.ts
@@ -0,0 +1,10 @@
+import { test } from '@stencil/playwright';
+import { testInputCallbacksAndEvents, testInputValueReflection } from '../../e2e';
+
+const COMPONENT_NAME = 'kol-input-email';
+const TEST_VALUE = 'example@example.com';
+
+test.describe(COMPONENT_NAME, () => {
+ testInputValueReflection(COMPONENT_NAME, TEST_VALUE);
+ testInputCallbacksAndEvents(COMPONENT_NAME);
+});
diff --git a/packages/components/src/components/input-email/readme.md b/packages/components/src/components/input-email/readme.md
deleted file mode 100644
index f8ec642330..0000000000
--- a/packages/components/src/components/input-email/readme.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# InputEmail
-
-Der Input-Typ **E-Mail** erzeugt ein Eingabefeld für E-Mails.
-
-## Konstruktion
-
-### Code
-
-```html
-
-```
-
-### Beispiel
-
-
-
-## Verwendung
-
-Setzen Sie die **InputEmail**-Komponente auf Formularen ein, wenn dort die Eingabe einer oder mehrerer E-Mail-Adressen erforderlich ist.
-
-Standardmäßig ist die Komponente für die Erfassung einer einzelnen E-Mail-Adresse vorgesehen. Setzen Sie das Attribut **`_multiple`**, um mehrere E-Mail-Adressen zu erfassen. Trennen Sie die einzelnen E-Mail-Adressen mit einem Komma (,) voneinander.
-
-### Best practices
-
-- Achten sie darauf `id` und `name` korrekt zu setzen, damit die Daten beim Formular Absenden mitgesendet werden.
-
-## Barrierefreiheit
-
-Eine Validierung der erfassten E-Mail-Adressen innerhalb der Komponente erfolgt nicht.
-Um eine fehlgeschlagene Validierung anzuzeigen, setzen Sie das Attrbut **`_error`** mit der entsprechenden Fehlermeldung, diese wird dann via **kol-alert** unterhalb angezeigt.
-
-### Tastatursteuerung
-
-| Taste | Funktion |
-| ----- | --------------------------- |
-| `Tab` | Fokussiert das Eingabefeld. |
-
-## Links und Referenzen
-
--
--
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type | Default |
-| --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
-| `_accessKey` | `_access-key` | Defines which key combination can be used to trigger or focus the interactive element of the component. | `string \| undefined` | `undefined` |
-| `_alert` | `_alert` | Defines whether the screen-readers should read out the notification. | `boolean \| undefined` | `true` |
-| `_autoComplete` | `_auto-complete` | Defines whether the input can be auto-completed. | `"off" \| "on" \| undefined` | `undefined` |
-| `_disabled` | `_disabled` | Makes the element not focusable and ignore all events. | `boolean \| undefined` | `false` |
-| `_error` | `_error` | Defines the error message text. | `string \| undefined` | `undefined` |
-| `_hasCounter` | `_has-counter` | Shows the character count on the lower border of the input. | `boolean \| undefined` | `false` |
-| `_hideError` | `_hide-error` | Hides the error message but leaves it in the DOM for the input's aria-describedby. | `boolean \| undefined` | `false` |
-| `_hideLabel` | `_hide-label` | Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it. | `boolean \| undefined` | `false` |
-| `_hint` | `_hint` | Defines the hint text. | `string \| undefined` | `''` |
-| `_icons` | `_icons` | Defines the icon classnames (e.g. `_icons="fa-solid fa-user"`). | `string \| undefined \| { right?: IconOrIconClass \| undefined; left?: IconOrIconClass \| undefined; }` | `undefined` |
-| `_id` | `_id` | Defines the internal ID of the primary component element. | `string \| undefined` | `undefined` |
-| `_label` _(required)_ | `_label` | Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.). Set to `false` to enable the expert slot. | `string` | `undefined` |
-| `_maxLength` | `_max-length` | Defines the maximum number of input characters. | `number \| undefined` | `undefined` |
-| `_msg` | -- | Defines the properties for a message rendered as Alert component. | `undefined \| {} & { _level?: 0 \| 2 \| 1 \| 3 \| 4 \| 5 \| 6 \| undefined; _on?: KoliBriAlertEventCallbacks \| undefined; _type?: "error" \| "warning" \| "info" \| "success" \| "default" \| undefined; _variant?: "card" \| "msg" \| undefined; _label?: string \| undefined; _alert?: boolean \| undefined; _hasCloser?: boolean \| undefined; } & { _description: string; }` | `undefined` |
-| `_multiple` | `_multiple` | Makes the input accept multiple inputs. | `boolean \| undefined` | `false` |
-| `_name` | `_name` | Defines the technical name of an input field. | `string \| undefined` | `undefined` |
-| `_on` | -- | Gibt die EventCallback-Funktionen für das Input-Event an. | `InputTypeOnBlur & InputTypeOnClick & InputTypeOnChange & InputTypeOnFocus & InputTypeOnInput \| undefined` | `undefined` |
-| `_pattern` | `_pattern` | Defines a validation pattern for the input field. | `string \| undefined` | `undefined` |
-| `_placeholder` | `_placeholder` | Defines the placeholder for input field. To be shown when there's no value. | `string \| undefined` | `undefined` |
-| `_readOnly` | `_read-only` | Makes the input element read only. | `boolean \| undefined` | `false` |
-| `_required` | `_required` | Makes the input element required. | `boolean \| undefined` | `false` |
-| `_smartButton` | `_smart-button` | Allows to add a button with an arbitrary action within the element (\_hide-label only). | `string \| undefined \| { _label: string; } & { _tabIndex?: number \| undefined; _value?: Stringified; _role?: AlternativeButtonLinkRolePropType \| undefined; _ariaControls?: string \| undefined; _ariaExpanded?: boolean \| undefined; _ariaSelected?: boolean \| undefined; _on?: ButtonCallbacksPropType \| undefined; _type?: "button" \| "reset" \| "submit" \| undefined; _variant?: "primary" \| "secondary" \| "normal" \| "tertiary" \| "danger" \| "ghost" \| "custom" \| undefined; _customClass?: string \| undefined; _disabled?: boolean \| undefined; _hideLabel?: boolean \| undefined; _icons?: IconsPropType \| undefined; _id?: string \| undefined; _name?: string \| undefined; _syncValueBySelector?: string \| undefined; _tooltipAlign?: AlignPropType \| undefined; _accessKey?: string \| undefined; }` | `undefined` |
-| `_suggestions` | `_suggestions` | Suggestions to provide for the input. | `W3CInputValue[] \| string \| undefined` | `undefined` |
-| `_tabIndex` | `_tab-index` | Defines which tab-index the primary element of the component has. (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) | `number \| undefined` | `undefined` |
-| `_tooltipAlign` | `_tooltip-align` | Defines where to show the Tooltip preferably: top, right, bottom or left. | `"bottom" \| "left" \| "right" \| "top" \| undefined` | `'top'` |
-| `_touched` | `_touched` | Shows if the input was touched by a user. | `boolean \| undefined` | `false` |
-| `_value` | `_value` | Defines the value of the input. | `string \| undefined` | `undefined` |
-
-## Methods
-
-### `getValue() => Promise`
-
-#### Returns
-
-Type: `Promise