From 15eb89b4e2835f99695ed02fbd0a2a3c68a3eee6 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Fri, 21 Jun 2024 17:14:20 +0200 Subject: [PATCH] chore: tidy project files --- CHANGELOG.md | 6 +- nix/config/release.nix | 2 +- nix/packages/monster.nix | 16 +- nix/scripts/build.nix | 13 +- nix/scripts/create-issue.nix | 162 +- nix/scripts/create-new-component-class.nix | 27 +- nix/scripts/deploy.nix | 14 +- nix/scripts/go-task.nix | 2 +- nix/scripts/release.nix | 166 +- nix/scripts/run-ci-tests.nix | 5 +- nix/scripts/run-ci-web-tests.nix | 48 +- nix/scripts/run-tests.nix | 103 +- nix/scripts/start-server.nix | 23 +- source/components/datatable/change-button.mjs | 11 +- source/components/datatable/dataset.mjs | 404 +- .../components/datatable/datasource/dom.mjs | 2 +- source/components/datatable/datatable.mjs | 16 +- source/components/datatable/filter.mjs | 8 +- source/components/datatable/pagination.mjs | 8 +- source/components/datatable/save-button.mjs | 9 +- source/components/datatable/status.mjs | 9 +- .../stylesheet/embedded-pagination.mjs | 6 +- source/components/form/select.mjs | 3688 ++++++++--------- source/components/form/stylesheet/select.mjs | 19 +- source/components/host/call-button.mjs | 8 +- .../components/layout/stylesheet/collapse.mjs | 6 +- source/components/notify/message.mjs | 9 +- source/components/style/mixin/property.pcss | 4 +- source/components/stylesheet/link.mjs | 4 +- .../components/stylesheet/mixin/property.mjs | 19 +- source/data/datasource/dom.mjs | 170 +- source/dom/resource/data.mjs | 244 +- source/dom/template.mjs | 226 +- 33 files changed, 2724 insertions(+), 2733 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef78c4521..5fc4c4b34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,14 @@ ### Bug Fixes -- exchange of document.selector with function findElementWithSelectorUpwards [#199](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/199) +- exchange of `document.selector` with function findElementWithSelectorUpwards [#199](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/199) ## [3.65.20] - 2024-06-20 -- Changeover to new release process +- Changeover to a new release process ## [3.65.3] - 2024-06-19 -### Bug Fixes - - switch nodejs_22 to nodejs_20 (segmentation fault) ## [3.65.1] - 2024-06-17 diff --git a/nix/config/release.nix b/nix/config/release.nix index 51e158acf..b766319ce 100644 --- a/nix/config/release.nix +++ b/nix/config/release.nix @@ -3,4 +3,4 @@ commit = "75ea5eefe4be8a871508b6eac6f5044bd42debd5"; name = "Monster"; mnemonic = "monster"; -} \ No newline at end of file +} diff --git a/nix/packages/monster.nix b/nix/packages/monster.nix index 96fb98191..5e9c7e9ee 100644 --- a/nix/packages/monster.nix +++ b/nix/packages/monster.nix @@ -7,13 +7,13 @@ buildDate = builtins.toString self.lastModified; releaseInfo = import ../config/release.nix; in -derivation { - name = "monster"; + derivation { + name = "monster"; version = releaseInfo.version; builder = "${pkgs'.bash}/bin/bash"; - args = let - script = pkgs'.callPackage ../scripts/build.nix {inherit pkgs' system;}; - in ["${script}/bin/build"]; - buildInputs = with pkgs'; []; - system = system; -} + args = let + script = pkgs'.callPackage ../scripts/build.nix {inherit pkgs' system;}; + in ["${script}/bin/build"]; + buildInputs = with pkgs'; []; + system = system; + } diff --git a/nix/scripts/build.nix b/nix/scripts/build.nix index d0178ac1c..a8c7afe75 100644 --- a/nix/scripts/build.nix +++ b/nix/scripts/build.nix @@ -1,5 +1,4 @@ {pkgs', ...}: let - bashFktScript = import ./bash-fkt.nix { inherit pkgs'; }; @@ -27,9 +26,9 @@ }; in pkgs'.writeShellScriptBin "build" '' - + set -e - + source ${pkgs'.common}/bin/common ${bashFktScript} @@ -66,7 +65,7 @@ in echo_fail "Failed to copy CHANGELOG.md. Exiting." exit 1 fi - + if ! ${pkgs'.coreutils}/bin/cp ${root}/.npmignore "./" then echo_fail "Failed to copy .gitignore Exiting." @@ -78,13 +77,13 @@ in echo_fail "Failed to write package.json. Exiting." exit 1 fi - + ${pkgs'.coreutils}/bin/mkdir -p $out if ! ${pkgs'.nodejs_20}/bin/npm pack --pack-destination $out/ ; then echo_fail "Failed to create tarball. Exiting." exit 1 - fi - + fi + echo_ok "Tarball created successfully." '' diff --git a/nix/scripts/create-issue.nix b/nix/scripts/create-issue.nix index b50d35547..900da6296 100644 --- a/nix/scripts/create-issue.nix +++ b/nix/scripts/create-issue.nix @@ -1,85 +1,85 @@ {pkgs', ...}: let in pkgs'.writeShellScriptBin "create-issue" '' - source ${pkgs'.common}/bin/common - - echo_section "create-issue" - echo_hint "This script will check the code for formatting and linting issues" - echo_hint "The command is executed in the current working directory and not in a nix derivation." - cd_working_dir - - echo_step "enter issue title" - issue_text=$(${pkgs'.gum}/bin/gum input --placeholder "Enter issue title") - - echo_step "enter issue description (End with Ctrl+D)" - issue_description=$(${pkgs'.gum}/bin/gum write --placeholder "Enter issue description. End with Ctrl+D") - - if [[ -z "$issue_text" ]]; then - echo_fail "Issue title is empty. Exiting." - exit 1 - fi - - escaped_issue_text=$(${pkgs'.gnused}/bin/sed 's/"/\\"/g' <<< "$issue_text") - escaped_issue_description=$(${pkgs'.gnused}/bin/sed 's/"/\\"/g' <<< "$issue_description") - - issue_output=$(${pkgs'.glab}/bin/glab issue create -t"$issue_text" --no-editor --description "$issue_description") - if [ $? -ne 0 ]; then - echo_fail "Issue creation failed. Exiting." - exit 1 - fi - - issue_id=$(echo "$issue_output" | ${pkgs'.gnugrep}/bin/grep -oP '(?<=/issues/)\d+') - if [ -z "$issue_id" ]; then - echo_fail "Issue creation failed. Exiting." - exit 1 - fi - - echo_ok "Issue with id $issue_id created" - - echo_step "create new issue file in test/cases" - issue_dir="development/issues/open" - ${pkgs'.coreutils}/bin/mkdir -p "$issue_dir" - - ${pkgs'.coreutils}/bin/cat <<EOF > $issue_dir/''${issue_id}.mjs - /** - * @file development/issues/open/''${issue_id}.mjs - * @url https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/''${issue_id} - * @description ''${escaped_issue_text} - * @issue ''${issue_id} - */ - - import "../../../source/components/style/property.pcss"; - import "../../../source/components/style/normalize.pcss"; - import "../../../source/components/style/typography.pcss"; - -EOF - - cat <<EOF > $issue_dir/''${issue_id}.html - <!DOCTYPE html> - <html lang="en"> - <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>''${escaped_issue_text} #''${issue_id}</title> - <script src="./''${issue_id}.mjs" type="module"></script> - </head> - <body> - <h1>''${escaped_issue_text} #''${issue_id}</h1> - <p>''${escaped_issue_description}</p> - <ul> - <li><a href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/''${issue_id}">Issue #''${issue_id}</a></li> - <li><a href="/">Back to overview</a></li> - </ul> - <main> - - <!-- Write your code here --> - - </main> - </body> - </html> -EOF - - echo_ok "Issue file created" - echo_hint "You can find the issue file in ''${issue_dir}/''${issue_id}.mjs" - echo_hint "You can find the issue html file in ''${issue_dir}/''${issue_id}.html" + source ${pkgs'.common}/bin/common + + echo_section "create-issue" + echo_hint "This script will check the code for formatting and linting issues" + echo_hint "The command is executed in the current working directory and not in a nix derivation." + cd_working_dir + + echo_step "enter issue title" + issue_text=$(${pkgs'.gum}/bin/gum input --placeholder "Enter issue title") + + echo_step "enter issue description (End with Ctrl+D)" + issue_description=$(${pkgs'.gum}/bin/gum write --placeholder "Enter issue description. End with Ctrl+D") + + if [[ -z "$issue_text" ]]; then + echo_fail "Issue title is empty. Exiting." + exit 1 + fi + + escaped_issue_text=$(${pkgs'.gnused}/bin/sed 's/"/\\"/g' <<< "$issue_text") + escaped_issue_description=$(${pkgs'.gnused}/bin/sed 's/"/\\"/g' <<< "$issue_description") + + issue_output=$(${pkgs'.glab}/bin/glab issue create -t"$issue_text" --no-editor --description "$issue_description") + if [ $? -ne 0 ]; then + echo_fail "Issue creation failed. Exiting." + exit 1 + fi + + issue_id=$(echo "$issue_output" | ${pkgs'.gnugrep}/bin/grep -oP '(?<=/issues/)\d+') + if [ -z "$issue_id" ]; then + echo_fail "Issue creation failed. Exiting." + exit 1 + fi + + echo_ok "Issue with id $issue_id created" + + echo_step "create new issue file in test/cases" + issue_dir="development/issues/open" + ${pkgs'.coreutils}/bin/mkdir -p "$issue_dir" + + ${pkgs'.coreutils}/bin/cat <<EOF > $issue_dir/''${issue_id}.mjs + /** + * @file development/issues/open/''${issue_id}.mjs + * @url https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/''${issue_id} + * @description ''${escaped_issue_text} + * @issue ''${issue_id} + */ + + import "../../../source/components/style/property.pcss"; + import "../../../source/components/style/normalize.pcss"; + import "../../../source/components/style/typography.pcss"; + + EOF + + cat <<EOF > $issue_dir/''${issue_id}.html + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>''${escaped_issue_text} #''${issue_id}</title> + <script src="./''${issue_id}.mjs" type="module"></script> + </head> + <body> + <h1>''${escaped_issue_text} #''${issue_id}</h1> + <p>''${escaped_issue_description}</p> + <ul> + <li><a href="https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/''${issue_id}">Issue #''${issue_id}</a></li> + <li><a href="/">Back to overview</a></li> + </ul> + <main> + + <!-- Write your code here --> + + </main> + </body> + </html> + EOF + + echo_ok "Issue file created" + echo_hint "You can find the issue file in ''${issue_dir}/''${issue_id}.mjs" + echo_hint "You can find the issue html file in ''${issue_dir}/''${issue_id}.html" '' diff --git a/nix/scripts/create-new-component-class.nix b/nix/scripts/create-new-component-class.nix index 7b2da894e..a31875399 100644 --- a/nix/scripts/create-new-component-class.nix +++ b/nix/scripts/create-new-component-class.nix @@ -1,17 +1,18 @@ -{pkgs', ...}: pkgs'.writeShellScriptBin "create-new-component-class" '' - source ${pkgs'.common}/bin/common +{pkgs', ...}: +pkgs'.writeShellScriptBin "create-new-component-class" '' + source ${pkgs'.common}/bin/common - echo_section "create new component class" - echo_hint "This script will check the code for formatting and linting issues" - echo_hint "The command is executed in the current working directory and not in a nix derivation." - cd_working_dir + echo_section "create new component class" + echo_hint "This script will check the code for formatting and linting issues" + echo_hint "The command is executed in the current working directory and not in a nix derivation." + cd_working_dir - if ! ${pkgs'.nodejs_20}/bin/node development/scripts/createNewComponentClass.mjs "$@" - then - echo_fail "script createNewClass.mjs failed, check your JS!" - exit 1 - fi - echo_ok "New component class created" + if ! ${pkgs'.nodejs_20}/bin/node development/scripts/createNewComponentClass.mjs "$@" + then + echo_fail "script createNewClass.mjs failed, check your JS!" + exit 1 + fi + echo_ok "New component class created" - '' +'' diff --git a/nix/scripts/deploy.nix b/nix/scripts/deploy.nix index 46dc69cde..a32983e27 100644 --- a/nix/scripts/deploy.nix +++ b/nix/scripts/deploy.nix @@ -1,7 +1,9 @@ -{pkgs', -system, -self, - ...}: let +{ + pkgs', + system, + self, + ... +}: let bashFktScript = import ./bash-fkt.nix { inherit pkgs'; }; @@ -10,10 +12,10 @@ in pkgs'.writeShellScriptBin "deploy" '' source ${pkgs'.common}/bin/common ${bashFktScript} - + echo_section "build and publish" archive=$(ls ${monster} | grep tgz) - + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc if ! publishingResult=$(${pkgs'.nodejs_20}/bin/npm publish "${monster}/$archive" --no-git-checks --access public) then diff --git a/nix/scripts/go-task.nix b/nix/scripts/go-task.nix index 6bc87c19c..8d1d9d9ff 100644 --- a/nix/scripts/go-task.nix +++ b/nix/scripts/go-task.nix @@ -97,7 +97,7 @@ - ${scriptUpdateWebTest}/bin/update-web-test - ${scriptRunWebTests}/bin/run-web-tests aliases: - - b + - b create-new-component-class: silent: true diff --git a/nix/scripts/release.nix b/nix/scripts/release.nix index 705c00259..33e6232e9 100644 --- a/nix/scripts/release.nix +++ b/nix/scripts/release.nix @@ -9,88 +9,88 @@ in pkgs'.writeShellScriptBin "release" '' - source ${pkgs'.common}/bin/common - ${bashFktScript} - - echo_header "Release " - - if [ -z "$CI_REPOSITORY_URL" ]; then - echo_fail "Error: CI_REPOSITORY_URL environment variable is not set." - exit 1 - fi - - if [ -z "$CI_PROJECT_DIR" ]; then - echo_fail "Error: CI_PROJECT_DIR environment variable is not set." - exit 1 - fi - - cd $CI_PROJECT_DIR || exit 1 - -#### ${pkgs'.git}/bin/git remote set-url origin https://''${CI_REPOSITORY_URL#*@} - echo_step "Set git remote url to https://pad:secret@''${CI_REPOSITORY_URL#*@}" - ${pkgs'.git}/bin/git remote set-url origin https://pad:''${GITLAB_TOKEN}@''${CI_REPOSITORY_URL#*@} - - - ${pkgs'.git}/bin/git fetch --all --tags --unshallow - ${pkgs'.git}/bin/git reset --hard origin/master - ${pkgs'.git}/bin/git clean -fd - ${pkgs'.git}/bin/git checkout $CI_COMMIT_REF_NAME - ${pkgs'.git}/bin/git pull origin $CI_COMMIT_REF_NAME - - if ! ${pkgs'.git}/bin/git --no-pager log --decorate=short --pretty=oneline -n 10 - then - echo_fail "Error: Could not get git log." - exit 1 - fi - - ${pkgs'.git}/bin/git fetch --prune --prune-tags - - echo_step "Bumping version" - gitVersion=$(${pkgs'.version}/bin/version predict --exit-code-if-no-bump) - if [ -z "$gitVersion" ]; then - echo_ok "There is no version bump." + source ${pkgs'.common}/bin/common + ${bashFktScript} + + echo_header "Release " + + if [ -z "$CI_REPOSITORY_URL" ]; then + echo_fail "Error: CI_REPOSITORY_URL environment variable is not set." + exit 1 + fi + + if [ -z "$CI_PROJECT_DIR" ]; then + echo_fail "Error: CI_PROJECT_DIR environment variable is not set." + exit 1 + fi + + cd $CI_PROJECT_DIR || exit 1 + + #### ${pkgs'.git}/bin/git remote set-url origin https://''${CI_REPOSITORY_URL#*@} + echo_step "Set git remote url to https://pad:secret@''${CI_REPOSITORY_URL#*@}" + ${pkgs'.git}/bin/git remote set-url origin https://pad:''${GITLAB_TOKEN}@''${CI_REPOSITORY_URL#*@} + + + ${pkgs'.git}/bin/git fetch --all --tags --unshallow + ${pkgs'.git}/bin/git reset --hard origin/master + ${pkgs'.git}/bin/git clean -fd + ${pkgs'.git}/bin/git checkout $CI_COMMIT_REF_NAME + ${pkgs'.git}/bin/git pull origin $CI_COMMIT_REF_NAME + + if ! ${pkgs'.git}/bin/git --no-pager log --decorate=short --pretty=oneline -n 10 + then + echo_fail "Error: Could not get git log." + exit 1 + fi + + ${pkgs'.git}/bin/git fetch --prune --prune-tags + + echo_step "Bumping version" + gitVersion=$(${pkgs'.version}/bin/version predict --exit-code-if-no-bump) + if [ -z "$gitVersion" ]; then + echo_ok "There is no version bump." + echo_ok "done" + exit 0 + fi + + echo_step "Write project version" + ### marker + + export VERSION=$gitVersion + export COMMIT="$CI_COMMIT_SHA" + export NAME=$(basename $(pwd) | sed 's/./\U&/' | sed 's/-//g') + export MNEMONIC=$(echo $NAME | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]//g') + ${pkgs'.envsubst}/bin/envsubst < ./nix/config/release.nix.template > ./nix/config/release.nix + + if ! ${pkgs'.nodejs_20}/bin/npm version "$gitVersion" --no-git-tag-version --allow-same-version 2>/dev/null; then + echo_fail "Error: Could not write project version." + exit 1 + fi + + if ${pkgs'.git}/bin/git tag -l | grep -q "$gitVersion"; then + echo_step "Tag $gitVersion existiert bereits. Lösche und setze den Tag neu." + ${pkgs'.git}/bin/git tag -d "$gitVersion" + ${pkgs'.git}/bin/git push --push-option=ci.skip origin --delete "$gitVersion" + fi + + ${pkgs'.git}/bin/git tag -a "$gitVersion" -m"chore: bump version to $gitVersion" + ${updateChangelogScript}/bin/update-changelog + cd $CI_PROJECT_DIR || exit 1 + + if ! ${pkgs'.git}/bin/git tag -d "$gitVersion" 2>/dev/null; then + echo_fail "Error: Could not delete git tag $gitVersion." + exit 1 + fi + + ${pkgs'.git}/bin/git commit -m "chore: release $gitVersion" CHANGELOG.md ./nix/config/release.nix package.json + + ${pkgs'.git}/bin/git tag -a "$gitVersion" -m"chore: bump version to $gitVersion" + ${pkgs'.git}/bin/git --no-pager log --decorate=short --pretty=oneline -n 5 + + if ! ${pkgs'.git}/bin/git push --push-option=ci.variable="DEPLOY_VERSION=$gitVersion" origin "$CI_COMMIT_REF_NAME" --tags ; then + echo_fail "Error: Could not push git tag $gitVersion." + exit 1 + fi + echo_ok "done" - exit 0 - fi - - echo_step "Write project version" - ### marker - - export VERSION=$gitVersion - export COMMIT="$CI_COMMIT_SHA" - export NAME=$(basename $(pwd) | sed 's/./\U&/' | sed 's/-//g') - export MNEMONIC=$(echo $NAME | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]//g') - ${pkgs'.envsubst}/bin/envsubst < ./nix/config/release.nix.template > ./nix/config/release.nix - - if ! ${pkgs'.nodejs_20}/bin/npm version "$gitVersion" --no-git-tag-version --allow-same-version 2>/dev/null; then - echo_fail "Error: Could not write project version." - exit 1 - fi - - if ${pkgs'.git}/bin/git tag -l | grep -q "$gitVersion"; then - echo_step "Tag $gitVersion existiert bereits. Lösche und setze den Tag neu." - ${pkgs'.git}/bin/git tag -d "$gitVersion" - ${pkgs'.git}/bin/git push --push-option=ci.skip origin --delete "$gitVersion" - fi - - ${pkgs'.git}/bin/git tag -a "$gitVersion" -m"chore: bump version to $gitVersion" - ${updateChangelogScript}/bin/update-changelog - cd $CI_PROJECT_DIR || exit 1 - - if ! ${pkgs'.git}/bin/git tag -d "$gitVersion" 2>/dev/null; then - echo_fail "Error: Could not delete git tag $gitVersion." - exit 1 - fi - - ${pkgs'.git}/bin/git commit -m "chore: release $gitVersion" CHANGELOG.md ./nix/config/release.nix package.json - - ${pkgs'.git}/bin/git tag -a "$gitVersion" -m"chore: bump version to $gitVersion" - ${pkgs'.git}/bin/git --no-pager log --decorate=short --pretty=oneline -n 5 - - if ! ${pkgs'.git}/bin/git push --push-option=ci.variable="DEPLOY_VERSION=$gitVersion" origin "$CI_COMMIT_REF_NAME" --tags ; then - echo_fail "Error: Could not push git tag $gitVersion." - exit 1 - fi - - echo_ok "done" '' diff --git a/nix/scripts/run-ci-tests.nix b/nix/scripts/run-ci-tests.nix index 7a2ee1fa7..520097e53 100644 --- a/nix/scripts/run-ci-tests.nix +++ b/nix/scripts/run-ci-tests.nix @@ -1,7 +1,4 @@ -{ - pkgs', - ... -}: +{pkgs', ...}: pkgs'.writeShellScriptBin "run-ci-tests" '' echo "run ci tests" diff --git a/nix/scripts/run-ci-web-tests.nix b/nix/scripts/run-ci-web-tests.nix index 0f801080d..8c171d4fd 100644 --- a/nix/scripts/run-ci-web-tests.nix +++ b/nix/scripts/run-ci-web-tests.nix @@ -1,33 +1,31 @@ -{ - pkgs', - ... -}: pkgs'.writeShellScriptBin "run-ci-web-tests" '' - echo "run ci web tests" +{pkgs', ...}: +pkgs'.writeShellScriptBin "run-ci-web-tests" '' + echo "run ci web tests" - if [ -z "''${CI_JOB_TOKEN}" ]; then - echo "You are in a CI environment, this shell is not intended for CI, but for local development" - exit 1 - fi + if [ -z "''${CI_JOB_TOKEN}" ]; then + echo "You are in a CI environment, this shell is not intended for CI, but for local development" + exit 1 + fi - cd ''${CI_PROJECT_DIR} || exit 1 + cd ''${CI_PROJECT_DIR} || exit 1 - echo "This script will run tests in the project working directory: ''${CI_PROJECT_DIR}" - echo "The command is executed in the current working directory and not in a nix derivation." + echo "This script will run tests in the project working directory: ''${CI_PROJECT_DIR}" + echo "The command is executed in the current working directory and not in a nix derivation." - TEST_CASES_PATH="''${CI_PROJECT_DIR}/test/web/" + TEST_CASES_PATH="''${CI_PROJECT_DIR}/test/web/" - if ! ${pkgs'.corepack}/bin/pnpm install - then - echo "Failed to install dependencies" - exit 1 - fi + if ! ${pkgs'.corepack}/bin/pnpm install + then + echo "Failed to install dependencies" + exit 1 + fi - if ! ${pkgs'.nodejs_20}/bin/node "''${TEST_CASES_PATH}/puppeteer.mjs" --browser ${pkgs'.chromium}/bin/chromium --path "''${TEST_CASES_PATH}/test.html" - then - echo "Tests failed, check your JS!" - exit 1 - fi - exit 0 + if ! ${pkgs'.nodejs_20}/bin/node "''${TEST_CASES_PATH}/puppeteer.mjs" --browser ${pkgs'.chromium}/bin/chromium --path "''${TEST_CASES_PATH}/test.html" + then + echo "Tests failed, check your JS!" + exit 1 + fi + exit 0 - '' +'' diff --git a/nix/scripts/run-tests.nix b/nix/scripts/run-tests.nix index a8cabd487..e8ce0b4f4 100644 --- a/nix/scripts/run-tests.nix +++ b/nix/scripts/run-tests.nix @@ -1,51 +1,52 @@ -{pkgs', ...}: pkgs'.writeShellScriptBin "run-tests" '' - source ${pkgs'.common}/bin/common - - echo_section "run tests" - echo_hint "This script will run tests in the current working directory." - echo_hint "The command is executed in the current working directory and not in a nix derivation." - cd_working_dir - - TEST_PATH="./test" - TEST_CASES_PATH="''${TEST_PATH}/cases/" - - echo_section "choose the test option" - - selection=$(${pkgs'.gum}/bin/gum choose "run specific test" "run all tests" "Cancel") - - if [[ "$selection" == "Cancel" ]]; then - echo_ok "You cancelled the operation." - exit 0 - fi - - if [[ "$selection" == "run all tests" ]]; then - echo_step "run specific tests" - if ! ${pkgs'.nodePackages.mocha}/bin/mocha --colors --jobs 1 --bail --recursive $TEST_CASES_PATH - then - echo_fail "Tests failed, check your JS!" - exit 1 - fi - exit 0 - fi - - escaped_test_cases_path=$(${pkgs'.coreutils}/bin/printf '%s\n' "$TEST_CASES_PATH" | ${pkgs'.gnused}/bin/sed 's:[\\/&]:\\&:g;$!s/$/\\/') - - echo_step "run all tests" - files=$(${pkgs'.findutils}/bin/find $TEST_CASES_PATH -type f -name "*.mjs") - relative_files=$(echo "$files" | ${pkgs'.gnused}/bin/sed "s|''${escaped_test_cases_path}||g") - - selected=$(echo "$relative_files" | ${pkgs'.gum}/bin/gum filter --no-limit --header="Select the test case to run" --placeholder="Select test case to run, use tab to select multiple files") - - if [[ -z "$selected" ]]; then - echo_ok "No test case selected, exiting." - exit 0 - fi - - full_paths=$(echo "$selected" | ${pkgs'.gnused}/bin/sed "s|^|''${escaped_test_cases_path}|") - if ! ${pkgs'.nodePackages.mocha}/bin/mocha --colors --jobs 1 --bail --recursive $full_paths - then - echo_fail "Tests failed, check your JS!" - exit 1 - fi - - '' +{pkgs', ...}: +pkgs'.writeShellScriptBin "run-tests" '' + source ${pkgs'.common}/bin/common + + echo_section "run tests" + echo_hint "This script will run tests in the current working directory." + echo_hint "The command is executed in the current working directory and not in a nix derivation." + cd_working_dir + + TEST_PATH="./test" + TEST_CASES_PATH="''${TEST_PATH}/cases/" + + echo_section "choose the test option" + + selection=$(${pkgs'.gum}/bin/gum choose "run specific test" "run all tests" "Cancel") + + if [[ "$selection" == "Cancel" ]]; then + echo_ok "You cancelled the operation." + exit 0 + fi + + if [[ "$selection" == "run all tests" ]]; then + echo_step "run specific tests" + if ! ${pkgs'.nodePackages.mocha}/bin/mocha --colors --jobs 1 --bail --recursive $TEST_CASES_PATH + then + echo_fail "Tests failed, check your JS!" + exit 1 + fi + exit 0 + fi + + escaped_test_cases_path=$(${pkgs'.coreutils}/bin/printf '%s\n' "$TEST_CASES_PATH" | ${pkgs'.gnused}/bin/sed 's:[\\/&]:\\&:g;$!s/$/\\/') + + echo_step "run all tests" + files=$(${pkgs'.findutils}/bin/find $TEST_CASES_PATH -type f -name "*.mjs") + relative_files=$(echo "$files" | ${pkgs'.gnused}/bin/sed "s|''${escaped_test_cases_path}||g") + + selected=$(echo "$relative_files" | ${pkgs'.gum}/bin/gum filter --no-limit --header="Select the test case to run" --placeholder="Select test case to run, use tab to select multiple files") + + if [[ -z "$selected" ]]; then + echo_ok "No test case selected, exiting." + exit 0 + fi + + full_paths=$(echo "$selected" | ${pkgs'.gnused}/bin/sed "s|^|''${escaped_test_cases_path}|") + if ! ${pkgs'.nodePackages.mocha}/bin/mocha --colors --jobs 1 --bail --recursive $full_paths + then + echo_fail "Tests failed, check your JS!" + exit 1 + fi + +'' diff --git a/nix/scripts/start-server.nix b/nix/scripts/start-server.nix index 4b0d6968b..1032c2e31 100644 --- a/nix/scripts/start-server.nix +++ b/nix/scripts/start-server.nix @@ -1,10 +1,5 @@ -{ - pkgs', - ... -}: let - - releaseInfo = import ../config/release.nix; - +{pkgs', ...}: let + releaseInfo = import ../config/release.nix; in pkgs'.writeShellScriptBin "start-server" '' source ${pkgs'.common}/bin/common @@ -15,19 +10,19 @@ in cd_working_dir echo_step "Starting server" - + export WORKING_DIR=$(pwd) - + export RUN_DIR=$(${pkgs'.mktemp}/bin/mktemp -d -t run-XXXXXX) if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo_fail "Failed to create temporary run directory" exit 1 fi echo_ok "Temporary run directory created: $RUN_DIR" - + export VERSION=${releaseInfo.version} export COMMIT=${releaseInfo.commit} - + export PNPX_BIN=${pkgs'.nodePackages.pnpm}/bin/pnpx export NODE_BIN=${pkgs'.nodejs_20}/bin/node @@ -41,14 +36,14 @@ in for configFile in "''${configFiles[@]}"; do if [ -f ''${configFile} ]; then echo_ok "Using ''${configFile#./templates/} configuration" - + t="./config/''${configFile#./templates/}" t=$(echo $t | sed 's/_/\//g') ${pkgs'.coreutils}/bin/mkdir -p $(dirname $t) ${pkgs'.envsubst}/bin/envsubst < ''${configFile} > ''${t} fi done - + if [ ! -f ./config/vite.config.mjs ]; then echo_fail "Vite config not found" exit 1 @@ -59,6 +54,6 @@ in exit 1 fi - echo_step "Cleaning up" + echo_step "Cleaning up" '' diff --git a/source/components/datatable/change-button.mjs b/source/components/datatable/change-button.mjs index 2f649b974..4553387fa 100644 --- a/source/components/datatable/change-button.mjs +++ b/source/components/datatable/change-button.mjs @@ -20,7 +20,7 @@ import { CustomElement, registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; import { isString } from "../../types/is.mjs"; import { State } from "../form/types/state.mjs"; import "../form/state-button.mjs"; @@ -190,9 +190,8 @@ function initControlReferences() { const selector = this.getOption("dataset.selector"); if (isString(selector)) { - - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } @@ -206,8 +205,8 @@ function initControlReferences() { const selector2 = this.getOption("overlay.selector"); if (isString(selector2)) { - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } diff --git a/source/components/datatable/dataset.mjs b/source/components/datatable/dataset.mjs index 2b233ce34..36a28f1e1 100644 --- a/source/components/datatable/dataset.mjs +++ b/source/components/datatable/dataset.mjs @@ -12,33 +12,33 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {instanceSymbol, internalSymbol} from "../../constants.mjs"; -import {Pathfinder} from "../../data/pathfinder.mjs"; -import {getLinkedObjects, hasObjectLink} from "../../dom/attributes.mjs"; -import {customElementUpdaterLinkSymbol} from "../../dom/constants.mjs"; +import { instanceSymbol, internalSymbol } from "../../constants.mjs"; +import { Pathfinder } from "../../data/pathfinder.mjs"; +import { getLinkedObjects, hasObjectLink } from "../../dom/attributes.mjs"; +import { customElementUpdaterLinkSymbol } from "../../dom/constants.mjs"; import { - assembleMethodSymbol, - CustomElement, - attributeObserverSymbol, - registerCustomElement, + assembleMethodSymbol, + CustomElement, + attributeObserverSymbol, + registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; -import {isString} from "../../types/is.mjs"; -import {Observer} from "../../types/observer.mjs"; -import {clone} from "../../util/clone.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; +import { isString } from "../../types/is.mjs"; +import { Observer } from "../../types/observer.mjs"; +import { clone } from "../../util/clone.mjs"; import { - ATTRIBUTE_DATASOURCE_SELECTOR, - ATTRIBUTE_DATATABLE_INDEX, + ATTRIBUTE_DATASOURCE_SELECTOR, + ATTRIBUTE_DATATABLE_INDEX, } from "./constants.mjs"; -import {Datasource} from "./datasource.mjs"; -import {DatasetStyleSheet} from "./stylesheet/dataset.mjs"; +import { Datasource } from "./datasource.mjs"; +import { DatasetStyleSheet } from "./stylesheet/dataset.mjs"; import { - handleDataSourceChanges, - datasourceLinkedElementSymbol, + handleDataSourceChanges, + datasourceLinkedElementSymbol, } from "./util.mjs"; -import {FormStyleSheet} from "../stylesheet/form.mjs"; +import { FormStyleSheet } from "../stylesheet/form.mjs"; -export {DataSet}; +export { DataSet }; /** * The data set component is used to show the data of a data source. @@ -79,184 +79,184 @@ export {DataSet}; * @summary A data set */ class DataSet extends CustomElement { - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/components/dataset@@instance"); - } - - /** - * This method determines which attributes are to be monitored by `attributeChangedCallback()`. - * - * @return {string[]} - * @since 1.15.0 - */ - static get observedAttributes() { - const attributes = super.observedAttributes; - attributes.push(ATTRIBUTE_DATATABLE_INDEX); - return attributes; - } - - /** - * To set the options via the html tag the attribute `data-monster-options` must be used. - * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} - * - * The individual configuration values can be found in the table. - * - * @property {Object} templates Template definitions - * @property {string} templates.main Main template - * @property {object} datasource The datasource - * @property {string} datasource.selector The selector of the datasource - * @property {object} mapping The mapping - * @property {string} mapping.data The data - * @property {number} mapping.index The index - * @property {Array} data The data - */ - get defaults() { - const obj = Object.assign({}, super.defaults, { - templates: { - main: getTemplate(), - }, - - datasource: { - selector: null, - }, - - mapping: { - data: "dataset", - index: 0, - }, - - data: {}, - }); - - updateOptionsFromArguments.call(this, obj); - return obj; - } - - /** - * - * @return {string} - */ - static getTag() { - return "monster-dataset"; - } - - write() { - return new Promise((resolve, reject) => { - if (!this[datasourceLinkedElementSymbol]) { - reject(new Error("No datasource")); - return; - } - - const internalUpdateCloneData = this.getInternalUpdateCloneData(); - if (!internalUpdateCloneData) { - reject(new Error("No update data")); - return; - } - - const internalData = internalUpdateCloneData?.["data"]; - if ( - internalData === undefined || - internalData === null || - internalData === "" - ) { - reject(new Error("No data")); - return; - } - - setTimeout(() => { - const path = this.getOption("mapping.data"); - const index = this.getOption("mapping.index"); - - let pathWithIndex; - - if (isString(path) && path !== "") { - pathWithIndex = path + "." + index; - } else { - pathWithIndex = index; - } - - const data = this[datasourceLinkedElementSymbol].data; - const unref = JSON.stringify(data); - const ref = JSON.parse(unref); - - new Pathfinder(ref).setVia(pathWithIndex, internalData); - - this[datasourceLinkedElementSymbol].data = ref; - - resolve(); - }, 0); - }); - } - - /** - * This method is responsible for assembling the component. - * - * It calls the parent's assemble method first, then initializes control references and event handlers. - * If the `datasource.selector` option is provided and is a string, it searches for the corresponding - * element in the DOM using that selector. - * - * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class. - * - * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component - * attaches an observer to the datasource's changes. - * - * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component. - * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges` - * method in the component's context. - */ - [assembleMethodSymbol]() { - super[assembleMethodSymbol](); - - // initControlReferences.call(self); - initEventHandler.call(this); - - const selector = this.getOption("datasource.selector"); - - if (isString(selector)) { - const element = findElementWithSelectorUpwards(this, selector); - if (element === null) { - throw new Error("the selector must match exactly one element"); - } - - if (!(element instanceof Datasource)) { - throw new TypeError("the element must be a datasource"); - } - - this[datasourceLinkedElementSymbol] = element; - element.datasource.attachObserver( - new Observer(handleDataSourceChanges.bind(this)), - ); - } - - this.attachObserver( - new Observer(() => { - handleDataSourceChanges.call(this); - }), - ); - } - - /** - * @return [CSSStyleSheet] - */ - static getCSSStyleSheet() { - return [FormStyleSheet, DatasetStyleSheet]; - } + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/components/dataset@@instance"); + } + + /** + * This method determines which attributes are to be monitored by `attributeChangedCallback()`. + * + * @return {string[]} + * @since 1.15.0 + */ + static get observedAttributes() { + const attributes = super.observedAttributes; + attributes.push(ATTRIBUTE_DATATABLE_INDEX); + return attributes; + } + + /** + * To set the options via the html tag the attribute `data-monster-options` must be used. + * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} + * + * The individual configuration values can be found in the table. + * + * @property {Object} templates Template definitions + * @property {string} templates.main Main template + * @property {object} datasource The datasource + * @property {string} datasource.selector The selector of the datasource + * @property {object} mapping The mapping + * @property {string} mapping.data The data + * @property {number} mapping.index The index + * @property {Array} data The data + */ + get defaults() { + const obj = Object.assign({}, super.defaults, { + templates: { + main: getTemplate(), + }, + + datasource: { + selector: null, + }, + + mapping: { + data: "dataset", + index: 0, + }, + + data: {}, + }); + + updateOptionsFromArguments.call(this, obj); + return obj; + } + + /** + * + * @return {string} + */ + static getTag() { + return "monster-dataset"; + } + + write() { + return new Promise((resolve, reject) => { + if (!this[datasourceLinkedElementSymbol]) { + reject(new Error("No datasource")); + return; + } + + const internalUpdateCloneData = this.getInternalUpdateCloneData(); + if (!internalUpdateCloneData) { + reject(new Error("No update data")); + return; + } + + const internalData = internalUpdateCloneData?.["data"]; + if ( + internalData === undefined || + internalData === null || + internalData === "" + ) { + reject(new Error("No data")); + return; + } + + setTimeout(() => { + const path = this.getOption("mapping.data"); + const index = this.getOption("mapping.index"); + + let pathWithIndex; + + if (isString(path) && path !== "") { + pathWithIndex = path + "." + index; + } else { + pathWithIndex = index; + } + + const data = this[datasourceLinkedElementSymbol].data; + const unref = JSON.stringify(data); + const ref = JSON.parse(unref); + + new Pathfinder(ref).setVia(pathWithIndex, internalData); + + this[datasourceLinkedElementSymbol].data = ref; + + resolve(); + }, 0); + }); + } + + /** + * This method is responsible for assembling the component. + * + * It calls the parent's assemble method first, then initializes control references and event handlers. + * If the `datasource.selector` option is provided and is a string, it searches for the corresponding + * element in the DOM using that selector. + * + * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class. + * + * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component + * attaches an observer to the datasource's changes. + * + * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component. + * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges` + * method in the component's context. + */ + [assembleMethodSymbol]() { + super[assembleMethodSymbol](); + + // initControlReferences.call(self); + initEventHandler.call(this); + + const selector = this.getOption("datasource.selector"); + + if (isString(selector)) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { + throw new Error("the selector must match exactly one element"); + } + + if (!(element instanceof Datasource)) { + throw new TypeError("the element must be a datasource"); + } + + this[datasourceLinkedElementSymbol] = element; + element.datasource.attachObserver( + new Observer(handleDataSourceChanges.bind(this)), + ); + } + + this.attachObserver( + new Observer(() => { + handleDataSourceChanges.call(this); + }), + ); + } + + /** + * @return [CSSStyleSheet] + */ + static getCSSStyleSheet() { + return [FormStyleSheet, DatasetStyleSheet]; + } } /** * @private */ function initEventHandler() { - this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => { - const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); - if (index) { - this.setOption("mapping.index", parseInt(index, 10)); - } - }; + this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => { + const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); + if (index) { + this.setOption("mapping.index", parseInt(index, 10)); + } + }; } /** @@ -264,17 +264,17 @@ function initEventHandler() { * @param {Object} options */ function updateOptionsFromArguments(options) { - const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); + const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX); - if (index !== null && index !== undefined) { - options.mapping.index = parseInt(index, 10); - } + if (index !== null && index !== undefined) { + options.mapping.index = parseInt(index, 10); + } - const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR); + const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR); - if (selector) { - options.datasource.selector = selector; - } + if (selector) { + options.datasource.selector = selector; + } } /** @@ -282,8 +282,8 @@ function updateOptionsFromArguments(options) { * @return {string} */ function getTemplate() { - // language=HTML - return ` + // language=HTML + return ` <div data-monster-role="control" part="control"> <slot></slot> </div> diff --git a/source/components/datatable/datasource/dom.mjs b/source/components/datatable/datasource/dom.mjs index 5b83a2e30..9a0b434f2 100644 --- a/source/components/datatable/datasource/dom.mjs +++ b/source/components/datatable/datasource/dom.mjs @@ -175,7 +175,7 @@ function updateDataSource() { data = Object.assign({}, d); }); - + if (data === null) { data = []; } diff --git a/source/components/datatable/datatable.mjs b/source/components/datatable/datatable.mjs index cb43ce25a..0ae22ebd1 100644 --- a/source/components/datatable/datatable.mjs +++ b/source/components/datatable/datatable.mjs @@ -65,7 +65,11 @@ import { } from "./util.mjs"; import "./columnbar.mjs"; import "./filter-button.mjs"; -import {findElementWithSelectorUpwards, getDocument, getWindow} from "../../dom/util.mjs"; +import { + findElementWithSelectorUpwards, + getDocument, + getWindow, +} from "../../dom/util.mjs"; import { addAttributeToken } from "../../dom/attributes.mjs"; import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs"; import { getDocumentTranslations } from "../../i18n/translations.mjs"; @@ -275,8 +279,8 @@ class DataTable extends CustomElement { const selector = this.getOption("datasource.selector"); if (isString(selector)) { - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } @@ -511,7 +515,7 @@ function getFilterConfigKey() { * @returns {Promise} */ function getHostConfig(callback) { - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return Promise.resolve({}); @@ -607,7 +611,7 @@ function updateConfigColumnBar() { map[option.name] = option.visible; } - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return; } @@ -814,7 +818,7 @@ function storeOrderStatement(doFetch) { const statement = createOrderStatement(headers); setDataSource.call(this, { orderBy: statement }, doFetch); - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return; } diff --git a/source/components/datatable/filter.mjs b/source/components/datatable/filter.mjs index ed4531059..22c905dc4 100644 --- a/source/components/datatable/filter.mjs +++ b/source/components/datatable/filter.mjs @@ -726,7 +726,7 @@ function initTabEvents() { } } - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return; } @@ -767,7 +767,7 @@ function updateFilterTabs() { return; } - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return; } @@ -1065,7 +1065,7 @@ function getControlValuesFromLabel(label) { * @returns {Promise<unknown>} */ function initFromConfig() { - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(isInstance(host, Host) && this.id)) { return Promise.resolve(); @@ -1108,7 +1108,7 @@ function initFromConfig() { * @private */ function updateConfig() { - const host = findElementWithSelectorUpwards( this,"monster-host"); + const host = findElementWithSelectorUpwards(this, "monster-host"); if (!(host && this.id)) { return; } diff --git a/source/components/datatable/pagination.mjs b/source/components/datatable/pagination.mjs index 93ce8c562..39eb4a6da 100644 --- a/source/components/datatable/pagination.mjs +++ b/source/components/datatable/pagination.mjs @@ -17,7 +17,7 @@ import { CustomElement, registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; import { ThemeStyleSheet } from "../stylesheet/theme.mjs"; import { ATTRIBUTE_DATASOURCE_SELECTOR } from "./constants.mjs"; import { Datasource } from "./datasource.mjs"; @@ -189,11 +189,11 @@ class Pagination extends CustomElement { const selector = this.getOption("datasource.selector", ""); if (isString(selector)) { - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } - + if (!(element instanceof Datasource)) { throw new TypeError("the element must be a datasource"); } diff --git a/source/components/datatable/save-button.mjs b/source/components/datatable/save-button.mjs index 9e3322e1e..097b53266 100644 --- a/source/components/datatable/save-button.mjs +++ b/source/components/datatable/save-button.mjs @@ -22,7 +22,7 @@ import { attributeObserverSymbol, registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; import { isString, isArray } from "../../types/is.mjs"; import { Observer } from "../../types/observer.mjs"; import { TokenList } from "../../types/tokenlist.mjs"; @@ -155,12 +155,11 @@ class SaveButton extends CustomElement { const selector = this.getOption("datasource.selector"); if (isString(selector)) { - - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } - + if (!(element instanceof Datasource)) { throw new TypeError("the element must be a datasource"); } diff --git a/source/components/datatable/status.mjs b/source/components/datatable/status.mjs index 79f617b11..bb85dc60c 100644 --- a/source/components/datatable/status.mjs +++ b/source/components/datatable/status.mjs @@ -17,7 +17,7 @@ import { CustomElement, registerCustomElement, } from "../../dom/customelement.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; import { ThemeStyleSheet } from "../stylesheet/theme.mjs"; import { Datasource } from "./datasource.mjs"; import { SpinnerStyleSheet } from "../stylesheet/spinner.mjs"; @@ -175,12 +175,11 @@ function initEventHandler() { const self = this; if (isString(selector)) { - - const element = findElementWithSelectorUpwards( this,selector); - if (element===null) { + const element = findElementWithSelectorUpwards(this, selector); + if (element === null) { throw new Error("the selector must match exactly one element"); } - + if (!(element instanceof Datasource)) { throw new TypeError("the element must be a datasource"); } diff --git a/source/components/datatable/stylesheet/embedded-pagination.mjs b/source/components/datatable/stylesheet/embedded-pagination.mjs index 3cfbc5da6..379c637b7 100644 --- a/source/components/datatable/stylesheet/embedded-pagination.mjs +++ b/source/components/datatable/stylesheet/embedded-pagination.mjs @@ -1,5 +1,5 @@ /** - * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved. + * Copyright © schukai GmbH and all contributing authors, 2024. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). @@ -8,8 +8,6 @@ * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact schukai GmbH. - * - * SPDX-License-Identifier: AGPL-3.0 */ import { addAttributeToken } from "../../../dom/attributes.mjs"; @@ -27,7 +25,7 @@ try { EmbeddedPaginationStyleSheet.insertRule( ` @layer embeddedpagination { -:where(html){line-height:1.15;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}:where(h1){font-size:2em;margin-block-end:.67em;margin-block-start:.67em}:where(dl,ol,ul) :where(dl,ol,ul){margin-block-end:0;margin-block-start:0}:where(hr){box-sizing:content-box;color:inherit;height:0}:where(abbr[title]){text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}:where(b,strong){font-weight:bolder}:where(code,kbd,pre,samp){font-family:monospace,monospace;font-size:1em}:where(small){font-size:80%}:where(table){border-color:currentColor;text-indent:0}:where(button,input,select){margin:0}:where(button){text-transform:none}:where(button,input:is([type=button i],[type=reset i],[type=submit i])){-webkit-appearance:button}:where(progress){vertical-align:baseline}:where(select){text-transform:none}:where(textarea){margin:0}:where(input[type=search i]){-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focus-inner{border-style:none;padding:0}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focusring{outline:1px dotted ButtonText}:where(:-moz-ui-invalid){box-shadow:none}:where(dialog){background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:fit-content}:where(dialog:not([open])){display:none}:where(summary){display:list-item}html{height:100%}body,html{min-height:calc(100vh - 40px)}body{box-sizing:border-box;margin:0;padding:0;word-break:break-word}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}[data-monster-role=control]{outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:after,:before,:root{--monster-font-family:-apple-system,BlinkMacSystemFont,\"Quicksand\",\"Segoe UI\",\"Roboto\",\"Oxygen\",\"Ubuntu\",\"Cantarell\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";--monster-color-primary-1:var(--monster-color-cinnamon-6);--monster-color-primary-2:var(--monster-color-cinnamon-6);--monster-color-primary-3:var(--monster-color-cinnamon-1);--monster-color-primary-4:var(--monster-color-cinnamon-1);--monster-bg-color-primary-1:var(--monster-color-cinnamon-1);--monster-bg-color-primary-2:var(--monster-color-cinnamon-2);--monster-bg-color-primary-3:var(--monster-color-cinnamon-3);--monster-bg-color-primary-4:var(--monster-color-cinnamon-6);--monster-color-secondary-1:var(--monster-color-red-4);--monster-color-secondary-2:var(--monster-color-red-4);--monster-color-secondary-3:var(--monster-color-red-1);--monster-color-secondary-4:var(--monster-color-red-1);--monster-bg-color-secondary-1:var(--monster-color-gray-1);--monster-bg-color-secondary-2:var(--monster-color-red-2);--monster-bg-color-secondary-3:var(--monster-color-red-3);--monster-bg-color-secondary-4:var(--monster-color-red-6);--monster-color-tertiary-1:var(--monster-color-magenta-4);--monster-color-tertiary-2:var(--monster-color-magenta-4);--monster-color-tertiary-3:var(--monster-color-magenta-6);--monster-color-tertiary-4:var(--monster-color-magenta-1);--monster-bg-color-tertiary-1:var(--monster-color-gray-1);--monster-bg-color-tertiary-2:var(--monster-color-magenta-1);--monster-bg-color-tertiary-3:var(--monster-color-magenta-2);--monster-bg-color-tertiary-4:var(--monster-color-magenta-6);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-4);--monster-color-destructive-3:var(--monster-color-red-6);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-4);--monster-bg-color-destructive-2:var(--monster-color-gray-1);--monster-bg-color-destructive-3:var(--monster-color-red-2);--monster-bg-color-destructive-4:var(--monster-color-red-5);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-4);--monster-color-success-3:var(--monster-color-green-6);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-3);--monster-bg-color-success-2:var(--monster-color-gray-1);--monster-bg-color-success-3:var(--monster-color-green-2);--monster-bg-color-success-4:var(--monster-color-green-5);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-4);--monster-color-warning-3:var(--monster-color-orange-6);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-3);--monster-bg-color-warning-2:var(--monster-color-gray-1);--monster-bg-color-warning-3:var(--monster-color-orange-2);--monster-bg-color-warning-4:var(--monster-color-orange-5);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-4);--monster-color-error-3:var(--monster-color-red-6);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-4);--monster-bg-color-error-2:var(--monster-color-gray-1);--monster-bg-color-error-3:var(--monster-color-red-2);--monster-bg-color-error-4:var(--monster-color-red-5);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-4);--monster-color-primary-disabled-4:var(--monster-color-gray-4);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-1);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-6);--monster-color-gradient-1:#833ab4;--monster-color-gradient-2:#fd1d1d;--monster-color-gradient-3:#fcb045;--monster-box-shadow-1:none;--monster-box-shadow-2:-1px 1px 10px 1px hsla(0,0%,76%,.61);--monster-text-shadow:none;--monster-theme-control-bg-color:var(--monster-gradient-tangerine-1);--monster-theme-control-color:var(--monster-gradient-tangerine-6);--monster-theme-control-border-color:var(--monster-gradient-tangerine-2);--monster-theme-control-hover-color:var(--monster-gradient-tangerine-6);--monster-theme-control-hover-bg-color:var(--monster-gradient-tangerine-2);--monster-theme-on-color:var(--monster-color-green-1);--monster-theme-on-bg-color:var(--monster-color-green-5);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-4);--monster-border-style:solid;--monster-border-width:2px;--monster-border-radius:0;--monster-popper-witharrrow-distance:-4px;--monster-z-index-default:0;--monster-z-index-outline:10;--monster-z-index-dropdown:200;--monster-z-index-dropdown-overlay:210;--monster-z-index-sticky:300;--monster-z-index-sticky-overlay:310;--monster-z-index-fixed:400;--monster-z-index-fixed-overlay:410;--monster-z-index-modal-backdrop:500;--monster-z-index-modal-backdrop-overlay:510;--monster-z-index-offcanvas:600;--monster-z-index-offcanvas-overlay:610;--monster-z-index-modal:700;--monster-z-index-modal-overlay:710;--monster-z-index-popover:800;--monster-z-index-popover-overlay:810;--monster-z-index-tooltip:800;--monster-z-index-tooltip-overlay:910;--monster-space-0:0;--monster-space-1:2px;--monster-space-2:4px;--monster-space-3:6px;--monster-space-4:10px;--monster-space-5:16px;--monster-space-6:26px;--monster-space-7:42px;--monster-breakpoint-0:480px;--monster-breakpoint-4:480px;--monster-breakpoint-7:768px;--monster-breakpoint-9:992px;--monster-breakpoint-12:1200px;--monster-dragger-width:1px;--monster-dragger-handle-width:4px;--monster-dragger-handle-height:50px}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-1:var(--monster-color-gray-1);--monster-color-primary-2:var(--monster-color-gray-1);--monster-color-primary-3:var(--monster-color-gray-6);--monster-color-primary-4:var(--monster-color-gray-6);--monster-bg-color-primary-1:var(--monster-color-gray-6);--monster-bg-color-primary-2:var(--monster-color-gray-3);--monster-bg-color-primary-3:var(--monster-color-gray-2);--monster-bg-color-primary-4:var(--monster-color-gray-1);--monster-color-secondary-1:var(--monster-color-red-1);--monster-color-secondary-2:var(--monster-color-red-1);--monster-color-secondary-3:var(--monster-color-red-6);--monster-color-secondary-4:var(--monster-color-red-4);--monster-bg-color-secondary-1:var(--monster-color-gray-6);--monster-bg-color-secondary-2:var(--monster-color-red-3);--monster-bg-color-secondary-3:var(--monster-color-red-2);--monster-bg-color-secondary-4:var(--monster-color-red-1);--monster-color-tertiary-1:var(--monster-color-magenta-1);--monster-color-tertiary-2:var(--monster-color-magenta-6);--monster-color-tertiary-3:var(--monster-color-magenta-4);--monster-color-tertiary-4:var(--monster-color-magenta-4);--monster-bg-color-tertiary-1:var(--monster-color-gray-6);--monster-bg-color-tertiary-2:var(--monster-color-magenta-2);--monster-bg-color-tertiary-3:var(--monster-color-magenta-1);--monster-bg-color-tertiary-4:var(--monster-color-magenta-1);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-3);--monster-color-destructive-3:var(--monster-color-red-4);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-5);--monster-bg-color-destructive-2:var(--monster-color-gray-6);--monster-bg-color-destructive-3:var(--monster-color-red-1);--monster-bg-color-destructive-4:var(--monster-color-red-4);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-2);--monster-color-success-3:var(--monster-color-green-4);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-5);--monster-bg-color-success-2:var(--monster-color-gray-6);--monster-bg-color-success-3:var(--monster-color-green-1);--monster-bg-color-success-4:var(--monster-color-green-3);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-3);--monster-color-warning-3:var(--monster-color-orange-4);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-5);--monster-bg-color-warning-2:var(--monster-color-gray-6);--monster-bg-color-warning-3:var(--monster-color-orange-1);--monster-bg-color-warning-4:var(--monster-color-orange-3);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-3);--monster-color-error-3:var(--monster-color-red-4);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-5);--monster-bg-color-error-2:var(--monster-color-gray-6);--monster-bg-color-error-3:var(--monster-color-red-1);--monster-bg-color-error-4:var(--monster-color-red-4);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-3);--monster-color-primary-disabled-4:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-6);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-1);--monster-theme-control-bg-color:var(--monster-color-gray-5);--monster-theme-control-color:var(--monster-color-gray-1);--monster-theme-control-border-color:var(--monster-color-gray-3);--monster-theme-control-hover-color:var(--monster-color-gray-1);--monster-theme-control-hover-bg-color:var(--monster-color-gray-6);--monster-theme-on-color:var(--monster-color-gray-6);--monster-theme-on-bg-color:var(--monster-color-gray-1);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-5)}}[data-monster-role=pagination]{box-sizing:border-box;display:flex;font-size:1rem;font-weight:400;justify-content:center;line-height:1.6;text-align:justify}[data-monster-role=pagination] ul{align-items:center;display:flex;flex-wrap:wrap;justify-content:center;list-style:none;margin:20px 0;padding-left:0}[data-monster-role=pagination] ul li{border-left:1px solid #000;margin:0;padding:0 10px}[data-monster-role=pagination] ul li a,[data-monster-role=pagination] ul li a:active,[data-monster-role=pagination] ul li a:focus,[data-monster-role=pagination] ul li a:hover,[data-monster-role=pagination] ul li a:link,[data-monster-role=pagination] ul li a:visited{background-color:var(--monster-theme-control-bg-color);color:var(--monster-theme-control-color);outline:none;padding:0 .4rem;text-decoration:none;width:-moz-max-content;width:max-content}[data-monster-role=pagination] ul li a:active,[data-monster-role=pagination] ul li a:focus,[data-monster-role=pagination] ul li a:hover{outline:none}[data-monster-role=pagination] ul li a:focus{outline:1px dashed var(--monster-color-selection-4);outline-offset:2px}@media (prefers-color-scheme:light){[data-monster-role=pagination] ul li a:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:2px}}[data-monster-role=pagination] ul li a.current{background-color:var(--monster-bg-color-primary-3);color:var(--monster-color-primary-3);cursor:unset}[data-monster-role=pagination] ul li a.disabled{cursor:not-allowed}[data-monster-role=pagination] ul li:first-child{border-left:none}@media (max-width:768px){[data-monster-role=pagination] ul li{padding:0 2px}[data-monster-role=pagination] ul li:first-child,[data-monster-role=pagination] ul li:nth-child(2){display:none}[data-monster-role=pagination] ul li:nth-child(3){border-left:none}} +:where(html){line-height:1.15;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}:where(h1){font-size:2em;margin-block-end:.67em;margin-block-start:.67em}:where(dl,ol,ul) :where(dl,ol,ul){margin-block-end:0;margin-block-start:0}:where(hr){box-sizing:content-box;color:inherit;height:0}:where(abbr[title]){text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}:where(b,strong){font-weight:bolder}:where(code,kbd,pre,samp){font-family:monospace,monospace;font-size:1em}:where(small){font-size:80%}:where(table){border-color:currentColor;text-indent:0}:where(button,input,select){margin:0}:where(button){text-transform:none}:where(button,input:is([type=button i],[type=reset i],[type=submit i])){-webkit-appearance:button}:where(progress){vertical-align:baseline}:where(select){text-transform:none}:where(textarea){margin:0}:where(input[type=search i]){-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focus-inner{border-style:none;padding:0}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focusring{outline:1px dotted ButtonText}:where(:-moz-ui-invalid){box-shadow:none}:where(dialog){background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:fit-content}:where(dialog:not([open])){display:none}:where(summary){display:list-item}html{height:100%}body,html{min-height:calc(100vh - 40px)}body{box-sizing:border-box;margin:0;padding:0;word-break:break-word}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}[data-monster-role=control]{outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:after,:before,:root{--monster-font-family:-apple-system,BlinkMacSystemFont,\"Quicksand\",\"Segoe UI\",\"Roboto\",\"Oxygen\",\"Ubuntu\",\"Cantarell\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";--monster-color-primary-1:var(--monster-color-gray-6);--monster-color-primary-2:var(--monster-color-gray-6);--monster-color-primary-3:var(--monster-color-cinnamon-1);--monster-color-primary-4:var(--monster-color-cinnamon-1);--monster-bg-color-primary-1:var(--monster-color-gray-1);--monster-bg-color-primary-2:var(--monster-color-gray-2);--monster-bg-color-primary-3:var(--monster-color-gray-6);--monster-bg-color-primary-4:var(--monster-color-gray-4);--monster-color-secondary-1:var(--monster-color-red-4);--monster-color-secondary-2:var(--monster-color-red-4);--monster-color-secondary-3:var(--monster-color-red-1);--monster-color-secondary-4:var(--monster-color-red-1);--monster-bg-color-secondary-1:var(--monster-color-gray-1);--monster-bg-color-secondary-2:var(--monster-color-red-2);--monster-bg-color-secondary-3:var(--monster-color-red-3);--monster-bg-color-secondary-4:var(--monster-color-red-6);--monster-color-tertiary-1:var(--monster-color-magenta-4);--monster-color-tertiary-2:var(--monster-color-magenta-4);--monster-color-tertiary-3:var(--monster-color-magenta-6);--monster-color-tertiary-4:var(--monster-color-magenta-1);--monster-bg-color-tertiary-1:var(--monster-color-gray-1);--monster-bg-color-tertiary-2:var(--monster-color-magenta-1);--monster-bg-color-tertiary-3:var(--monster-color-magenta-2);--monster-bg-color-tertiary-4:var(--monster-color-magenta-6);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-4);--monster-color-destructive-3:var(--monster-color-red-6);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-4);--monster-bg-color-destructive-2:var(--monster-color-gray-1);--monster-bg-color-destructive-3:var(--monster-color-red-2);--monster-bg-color-destructive-4:var(--monster-color-red-5);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-4);--monster-color-success-3:var(--monster-color-green-6);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-3);--monster-bg-color-success-2:var(--monster-color-gray-1);--monster-bg-color-success-3:var(--monster-color-green-2);--monster-bg-color-success-4:var(--monster-color-green-5);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-4);--monster-color-warning-3:var(--monster-color-orange-6);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-3);--monster-bg-color-warning-2:var(--monster-color-gray-1);--monster-bg-color-warning-3:var(--monster-color-orange-2);--monster-bg-color-warning-4:var(--monster-color-orange-5);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-4);--monster-color-error-3:var(--monster-color-red-6);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-4);--monster-bg-color-error-2:var(--monster-color-gray-1);--monster-bg-color-error-3:var(--monster-color-red-2);--monster-bg-color-error-4:var(--monster-color-red-5);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-4);--monster-color-primary-disabled-4:var(--monster-color-gray-4);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-1);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-6);--monster-color-gradient-1:#833ab4;--monster-color-gradient-2:#fd1d1d;--monster-color-gradient-3:#fcb045;--monster-box-shadow-1:none;--monster-box-shadow-2:-1px 1px 10px 1px hsla(0,0%,76%,.61);--monster-text-shadow:none;--monster-theme-control-bg-color:var(--monster-gradient-tangerine-1);--monster-theme-control-color:var(--monster-gradient-tangerine-6);--monster-theme-control-border-color:var(--monster-gradient-tangerine-2);--monster-theme-control-hover-color:var(--monster-gradient-tangerine-6);--monster-theme-control-hover-bg-color:var(--monster-gradient-tangerine-2);--monster-theme-on-color:var(--monster-color-green-1);--monster-theme-on-bg-color:var(--monster-color-green-5);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-4);--monster-border-style:solid;--monster-border-width:3px;--monster-border-radius:0;--monster-popper-witharrrow-distance:-4px;--monster-z-index-default:0;--monster-z-index-outline:10;--monster-z-index-dropdown:200;--monster-z-index-dropdown-overlay:210;--monster-z-index-sticky:300;--monster-z-index-sticky-overlay:310;--monster-z-index-fixed:400;--monster-z-index-fixed-overlay:410;--monster-z-index-modal-backdrop:500;--monster-z-index-modal-backdrop-overlay:510;--monster-z-index-offcanvas:600;--monster-z-index-offcanvas-overlay:610;--monster-z-index-modal:700;--monster-z-index-modal-overlay:710;--monster-z-index-popover:800;--monster-z-index-popover-overlay:810;--monster-z-index-tooltip:800;--monster-z-index-tooltip-overlay:910;--monster-space-0:0;--monster-space-1:2px;--monster-space-2:4px;--monster-space-3:6px;--monster-space-4:10px;--monster-space-5:16px;--monster-space-6:26px;--monster-space-7:42px;--monster-breakpoint-0:480px;--monster-breakpoint-4:480px;--monster-breakpoint-7:768px;--monster-breakpoint-9:992px;--monster-breakpoint-12:1200px;--monster-dragger-width:2px;--monster-dragger-handle-width:4px;--monster-dragger-handle-height:50px}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-1:var(--monster-color-gray-1);--monster-color-primary-2:var(--monster-color-gray-1);--monster-color-primary-3:var(--monster-color-gray-6);--monster-color-primary-4:var(--monster-color-gray-6);--monster-bg-color-primary-1:var(--monster-color-gray-6);--monster-bg-color-primary-2:var(--monster-color-gray-3);--monster-bg-color-primary-3:var(--monster-color-gray-2);--monster-bg-color-primary-4:var(--monster-color-gray-1);--monster-color-secondary-1:var(--monster-color-red-1);--monster-color-secondary-2:var(--monster-color-red-1);--monster-color-secondary-3:var(--monster-color-red-6);--monster-color-secondary-4:var(--monster-color-red-4);--monster-bg-color-secondary-1:var(--monster-color-gray-6);--monster-bg-color-secondary-2:var(--monster-color-red-3);--monster-bg-color-secondary-3:var(--monster-color-red-2);--monster-bg-color-secondary-4:var(--monster-color-red-1);--monster-color-tertiary-1:var(--monster-color-magenta-1);--monster-color-tertiary-2:var(--monster-color-magenta-6);--monster-color-tertiary-3:var(--monster-color-magenta-4);--monster-color-tertiary-4:var(--monster-color-magenta-4);--monster-bg-color-tertiary-1:var(--monster-color-gray-6);--monster-bg-color-tertiary-2:var(--monster-color-magenta-2);--monster-bg-color-tertiary-3:var(--monster-color-magenta-1);--monster-bg-color-tertiary-4:var(--monster-color-magenta-1);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-3);--monster-color-destructive-3:var(--monster-color-red-4);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-5);--monster-bg-color-destructive-2:var(--monster-color-gray-6);--monster-bg-color-destructive-3:var(--monster-color-red-1);--monster-bg-color-destructive-4:var(--monster-color-red-4);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-2);--monster-color-success-3:var(--monster-color-green-4);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-5);--monster-bg-color-success-2:var(--monster-color-gray-6);--monster-bg-color-success-3:var(--monster-color-green-1);--monster-bg-color-success-4:var(--monster-color-green-3);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-3);--monster-color-warning-3:var(--monster-color-orange-4);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-5);--monster-bg-color-warning-2:var(--monster-color-gray-6);--monster-bg-color-warning-3:var(--monster-color-orange-1);--monster-bg-color-warning-4:var(--monster-color-orange-3);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-3);--monster-color-error-3:var(--monster-color-red-4);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-5);--monster-bg-color-error-2:var(--monster-color-gray-6);--monster-bg-color-error-3:var(--monster-color-red-1);--monster-bg-color-error-4:var(--monster-color-red-4);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-3);--monster-color-primary-disabled-4:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-6);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-1);--monster-theme-control-bg-color:var(--monster-color-gray-5);--monster-theme-control-color:var(--monster-color-gray-1);--monster-theme-control-border-color:var(--monster-color-gray-3);--monster-theme-control-hover-color:var(--monster-color-gray-1);--monster-theme-control-hover-bg-color:var(--monster-color-gray-6);--monster-theme-on-color:var(--monster-color-gray-6);--monster-theme-on-bg-color:var(--monster-color-gray-1);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-5)}}[data-monster-role=pagination]{box-sizing:border-box;display:flex;font-size:1rem;font-weight:400;justify-content:center;line-height:1.6;text-align:justify}[data-monster-role=pagination] ul{align-items:center;display:flex;flex-wrap:wrap;justify-content:center;list-style:none;margin:20px 0;padding-left:0}[data-monster-role=pagination] ul li{border-left:1px solid #000;margin:0;padding:0 10px}[data-monster-role=pagination] ul li a,[data-monster-role=pagination] ul li a:active,[data-monster-role=pagination] ul li a:focus,[data-monster-role=pagination] ul li a:hover,[data-monster-role=pagination] ul li a:link,[data-monster-role=pagination] ul li a:visited{background-color:var(--monster-theme-control-bg-color);color:var(--monster-theme-control-color);outline:none;padding:0 .4rem;text-decoration:none;width:-moz-max-content;width:max-content}[data-monster-role=pagination] ul li a:active,[data-monster-role=pagination] ul li a:focus,[data-monster-role=pagination] ul li a:hover{outline:none}[data-monster-role=pagination] ul li a:focus{outline:1px dashed var(--monster-color-selection-4);outline-offset:2px}@media (prefers-color-scheme:light){[data-monster-role=pagination] ul li a:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:2px}}[data-monster-role=pagination] ul li a.current{background-color:var(--monster-bg-color-primary-3);color:var(--monster-color-primary-3);cursor:unset}[data-monster-role=pagination] ul li a.disabled{cursor:not-allowed}[data-monster-role=pagination] ul li:first-child{border-left:none}@media (max-width:768px){[data-monster-role=pagination] ul li{padding:0 2px}[data-monster-role=pagination] ul li:first-child,[data-monster-role=pagination] ul li:nth-child(2){display:none}[data-monster-role=pagination] ul li:nth-child(3){border-left:none}} }`, 0, ); diff --git a/source/components/form/select.mjs b/source/components/form/select.mjs index 143ae5e9f..c2dc02e6d 100644 --- a/source/components/form/select.mjs +++ b/source/components/form/select.mjs @@ -12,62 +12,62 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {instanceSymbol} from "../../constants.mjs"; -import {internalSymbol} from "../../constants.mjs"; -import {buildMap} from "../../data/buildmap.mjs"; -import {DeadMansSwitch} from "../../util/deadmansswitch.mjs"; -import {positionPopper} from "./util/floating-ui.mjs"; +import { instanceSymbol } from "../../constants.mjs"; +import { internalSymbol } from "../../constants.mjs"; +import { buildMap } from "../../data/buildmap.mjs"; +import { DeadMansSwitch } from "../../util/deadmansswitch.mjs"; +import { positionPopper } from "./util/floating-ui.mjs"; import { - addAttributeToken, - findClosestByAttribute, - removeAttributeToken, + addAttributeToken, + findClosestByAttribute, + removeAttributeToken, } from "../../dom/attributes.mjs"; import { - ATTRIBUTE_ERRORMESSAGE, - ATTRIBUTE_PREFIX, - ATTRIBUTE_ROLE, + ATTRIBUTE_ERRORMESSAGE, + ATTRIBUTE_PREFIX, + ATTRIBUTE_ROLE, } from "../../dom/constants.mjs"; -import {CustomControl} from "../../dom/customcontrol.mjs"; +import { CustomControl } from "../../dom/customcontrol.mjs"; import { - assembleMethodSymbol, - getSlottedElements, - registerCustomElement, - updaterTransformerMethodsSymbol, + assembleMethodSymbol, + getSlottedElements, + registerCustomElement, + updaterTransformerMethodsSymbol, } from "../../dom/customelement.mjs"; import { - findTargetElementFromEvent, - fireCustomEvent, - fireEvent, + findTargetElementFromEvent, + fireCustomEvent, + fireEvent, } from "../../dom/events.mjs"; -import {getDocument} from "../../dom/util.mjs"; -import {Formatter} from "../../text/formatter.mjs"; -import {getGlobal} from "../../types/global.mjs"; -import {ID} from "../../types/id.mjs"; +import { getDocument } from "../../dom/util.mjs"; +import { Formatter } from "../../text/formatter.mjs"; +import { getGlobal } from "../../types/global.mjs"; +import { ID } from "../../types/id.mjs"; import { - isArray, - isFunction, - isInteger, - isIterable, - isObject, - isPrimitive, - isString, + isArray, + isFunction, + isInteger, + isIterable, + isObject, + isPrimitive, + isString, } from "../../types/is.mjs"; -import {Observer} from "../../types/observer.mjs"; -import {ProxyObserver} from "../../types/proxyobserver.mjs"; -import {validateArray, validateString} from "../../types/validate.mjs"; -import {Processing} from "../../util/processing.mjs"; -import {STYLE_DISPLAY_MODE_BLOCK} from "./constants.mjs"; -import {SelectStyleSheet} from "./stylesheet/select.mjs"; +import { Observer } from "../../types/observer.mjs"; +import { ProxyObserver } from "../../types/proxyobserver.mjs"; +import { validateArray, validateString } from "../../types/validate.mjs"; +import { Processing } from "../../util/processing.mjs"; +import { STYLE_DISPLAY_MODE_BLOCK } from "./constants.mjs"; +import { SelectStyleSheet } from "./stylesheet/select.mjs"; import { - getDocumentTranslations, - Translations, + getDocumentTranslations, + Translations, } from "../../i18n/translations.mjs"; export { - Select, - popperElementSymbol, - getSummaryTemplate, - getSelectionTemplate, + Select, + popperElementSymbol, + getSummaryTemplate, + getSelectionTemplate, }; /** @@ -200,7 +200,7 @@ const popperFilterElementSymbol = Symbol("popperFilterElement"); * @type {symbol} */ const popperFilterContainerElementSymbol = Symbol( - "popperFilterContainerElement", + "popperFilterContainerElement", ); /** @@ -336,527 +336,520 @@ const FILTER_POSITION_INLINE = "inline"; * @fires Monster.Components.Form.event:monster-changed */ class Select extends CustomControl { - /** - * @extends CustomControl - */ - constructor() { - super(); - initOptionObserver.call(this); - } - - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - * @since 2.1.0 - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/components/form/select@@instance"); - } - - /** - * The current selection of the Select - * - * ``` - * e = document.querySelector('monster-select'); - * console.log(e.value) - * // ↦ 1 - * // ↦ ['1','2'] - * ``` - * - * @property {string|array} - */ - get value() { - return convertSelectionToValue.call(this, this.getOption("selection")); - } - - /** - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals} - * @return {boolean} - */ - static get formAssociated() { - return true; - } - - /** - * Set selection - * - * ``` - * e = document.querySelector('monster-select'); - * e.value=1 - * ``` - * - * @property {string|array} value - * @since 1.2.0 - * @throws {Error} unsupported type - */ - set value(value) { - const result = convertValueToSelection.call(this, value); - setSelection - .call(this, result.selection) - .then(() => { - }) - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - } - - /** - * To set the options via the html tag the attribute `data-monster-options` must be used. - * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} - * - * The individual configuration values can be found in the table. - * - * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown - * @property {boolean} delegatesFocus=false lorem [see mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus) - * @property {Object[]} options Selection of key identifier pairs available for selection and displayed in the dropdown. - * @property {string} options[].label - * @property {string} options[].value - * @property {string} options[].visibility hidden or visible - * @property {Array} selection Selected options - * @property {Integer} showMaxOptions=10 Maximum number of visible options before a scroll bar should be displayed. - * @property {string} type=radio Multiple (checkbox) or single selection (radio) - * @property {string} name=(random id) Name of the form field - * @property {string} url Load options from server per url - * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) - * @property {String} fetch.redirect=error - * @property {String} fetch.method=GET - * @property {String} fetch.mode=same-origin - * @property {String} fetch.credentials=same-origin - * @property {Object} fetch.headers={"accept":"application/json"}} - * @property {Object} labels - * @property {string} labels.cannot-be-loaded cannot be loaded - * @property {string} labels.no-options-available no options available - * @property {string} labels.select-an-option select an option - * @property {string} labels.no-option no option in the list, maybe you have to change the filter - * @property {Object} features List with features - * @property {Boolean} features.clearAll=true Display of a delete button to delete the entire selection - * @property {Boolean} features.clear=true Display of a delete key for deleting the specific selection - * @property {Boolean} features.lazyLoad=false Load options when first opening the dropdown - * @property {Boolean} features.closeOnSelect=false Close the dropdown when an option is selected (since 3.54.0) - * @property {Boolean} features.emptyValueIfNoOptions=false If no options are available, the selection is set to an empty array - * @property {Boolean} features.storeFetchedData=false Store fetched data in the object - * @property {Boolean} features.useStrictValueComparison=true Use strict value comparison for the selection - * @property {Boolean} filter.defaultValue=* Default filter value, if the filter is empty - * @property {Boolean} filter.mode=options Filter mode, values: options, remote, disabled - * @property {Object} templates Template definitions - * @property {string} templates.main Main template - * @property {string} templateMapping Mapping of the template placeholders - * @property {string} templateMapping.selected Selected Template - * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/) - * @property {string} popper.placement=bottom PopperJS placement - * @property {Object[]} modifiers={name:offset} PopperJS placement - * @property {Object} mapping - * @property {String} mapping.selector=* Path to select the appropriate entries - * @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key (**) - * @property {String} mapping.valueTemplate="" template with the value placeholders in the form ${name}, where name is the key - * @property {Monster.Components.Form~exampleFilterCallback|undefined} mapping.filter Filtering of values via a function - * @property {Object} formatter - * @property {Monster.Components.Form~formatterSelectionCallback|undefined} formatter.selection format selection label - */ - get defaults() { - return Object.assign( - {}, - super.defaults, - { - toggleEventType: ["click", "touch"], - delegatesFocus: false, - options: [], - selection: [], - showMaxOptions: 10, - type: "radio", - name: new ID("s").toString(), - features: { - clearAll: true, - clear: true, - lazyLoad: false, - closeOnSelect: false, - emptyValueIfNoOptions: false, - storeFetchedData: false, - useStrictValueComparison: false, - }, - url: null, - labels: { - "cannot-be-loaded": "Cannot be loaded", - "no-options-available": noOptionsAvailableMessage, - "click-to-load-options": clickToLoadOptionsMessage, - "select-an-option": "Select an option", - "summary-text": { - zero: "No entries were selected", - one: '<span class="monster-badge-primary-pill">1</span> entry was selected', - other: - '<span class="monster-badge-primary-pill">${count}</span> entries were selected', - }, - "no-options": - "Unfortunately, there are no options available in the list.", - "no-options-found": - "No options are available in the list. Please consider modifying the filter.", - }, - messages: { - control: null, - selected: null, - emptyOptions: null, - }, - fetch: { - redirect: "error", - method: "GET", - mode: "same-origin", - credentials: "same-origin", - headers: { - accept: "application/json", - }, - }, - filter: { - defaultValue: "*", - mode: FILTER_MODE_DISABLED, - position: FILTER_POSITION_INLINE, - }, - classes: { - badge: "monster-badge-primary", - statusOrRemoveBadge: "empty", - }, - mapping: { - selector: "*", - labelTemplate: "", - valueTemplate: "", - filter: null, - }, - formatter: { - selection: buildSelectionLabel, - }, - templates: { - main: getTemplate(), - }, - templateMapping: { - /** with the attribute `data-monster-selected-template` the template for the selected options can be defined. */ - selected: getSelectionTemplate(), - }, - - popper: { - placement: "bottom", - middleware: ["flip", "offset:1"], - }, - }, - initOptionsFromArguments.call(this), - ); - } - - /** - * @return {Monster.Components.Form.Select} - */ - [assembleMethodSymbol]() { - const self = this; - super[assembleMethodSymbol](); - - initControlReferences.call(self); - initEventHandler.call(self); - - const lazyLoadFlag = self.getOption("features.lazyLoad"); - - if (self.hasAttribute("value")) { - new Processing(10, () => { - this.value = this.getAttribute("value"); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - } - - if (self.getOption("url") !== null && !lazyLoadFlag) { - self.fetch() - } - - let lastValue = self.value; - self[internalSymbol].attachObserver( - new Observer(function () { - if (isObject(this) && this instanceof ProxyObserver) { - const n = this.getSubject()?.options?.value; - - if (lastValue !== n) { - lastValue = n; - setSelection - .call(self, n) - .then(() => { - }) - .catch((e) => { - addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`); - }); - } - } - }), - ); - - areOptionsAvailableAndInit.call(self); - - return this; - } - - /** - * - * @returns {*} - * @throws {Error} storeFetchedData is not enabled - * @since 3.66.0 - */ - getLastFetchedData() { - - if (this.getOption("features.storeFetchedData") === false) { - throw new Error("storeFetchedData is not enabled"); - } - - return this?.[lastFetchedDataSymbol]; - } - - /** - * The Button.click() method simulates a click on the internal button element. - * - * @since 3.27.0 - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click} - */ - click() { - if (this.getOption("disabled") === true) { - return; - } - - toggle.call(this); - } - - /** - * The Button.focus() method sets focus on the internal button element. - * - * @since 3.27.0 - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus} - */ - focus(options) { - if (this.getOption("disabled") === true) { - return; - } - - new Processing(() => { - gatherState.call(this); - focusFilter.call(this, options); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); - }); - } - - /** - * The Button.blur() method removes focus from the internal button element. - * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur - */ - blur() { - new Processing(() => { - gatherState.call(this); - blurFilter.call(this); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); - }); - } - - /** - * If no url is specified, the options are taken from the Component itself. - * - * @param {string|URL} url URL to fetch the options - * @return {Promise} - */ - fetch(url) { - - if (url instanceof URL) { - url = url.toString(); - } - - if (url !== undefined && url !== null) { - url = validateString(url); - } else { - url = this.getOption("url"); - if (url === null) { - return Promise.reject(new Error("No url defined")); - } - } - - hide.call(this); - - return new Promise((resolve, reject) => { - setStatusOrRemoveBadges.call(this, "loading"); - - new Processing(10, () => { - - this.setOption("options", []); - - fetchData - .call(this, url) - .then((map) => { - this[isLoadingSymbol] = false; - if ( - isObject(map) || - isArray(map) || - map instanceof Set || - map instanceof Map - ) { - - - this.importOptions(map); - this[lastFetchedDataSymbol] = map; - - let result; - const selection = this.getOption("selection") - if (selection) { - result = setSelection.call(this, selection); - } else if (this.hasAttribute("value")) { - result = setSelection.call(this, this.getAttribute("value")); - } else { - result = setSelection.call(this, []); - } - - setTimeout(() => { - setStatusOrRemoveBadges.call(this, "closed"); - resolve(); - }, 10); - - return result; - } - - setStatusOrRemoveBadges.call(this, "error"); - reject(new Error("invalid response")); - }) - .catch((e) => { - this[isLoadingSymbol] = false; - setStatusOrRemoveBadges.call(this, "error"); - reject(e); - }); - - }).run().catch((e) => { - setStatusOrRemoveBadges.call(this, "error"); - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - - }); - } - - /** - * @return {void} - */ - connectedCallback() { - super.connectedCallback(); - const document = getDocument(); - - for (const [, type] of Object.entries(["click", "touch"])) { - // close on outside ui-events - document.addEventListener(type, this[closeEventHandler]); - } - - parseSlotsToOptions.call(this); - attachResizeObserver.call(this); - updatePopper.call(this); - - new Processing(() => { - gatherState.call(this); - focusFilter.call(this); - }).run(); - } - - /** - * @return {void} - */ - disconnectedCallback() { - super.disconnectedCallback(); - const document = getDocument(); - - // close on outside ui-events - for (const [, type] of Object.entries(["click", "touch"])) { - document.removeEventListener(type, this[closeEventHandler]); - } - - disconnectResizeObserver.call(this); - } - - /** - * Import Select Options from dataset - * Not to be confused with the control defaults/options - * - * @since 0.16.0 - * @param {array|object|Map|Set} data - * @return {Select} - * @throws {Error} map is not iterable - * @throws {Error} missing label configuration - */ - importOptions(data) { - const mappingOptions = this.getOption("mapping", {}); - const selector = mappingOptions?.["selector"]; - const labelTemplate = mappingOptions?.["labelTemplate"]; - const valueTemplate = mappingOptions?.["valueTemplate"]; - const filter = mappingOptions?.["filter"]; - - let flag = false; - if (labelTemplate === "") { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template"); - flag = true; - } - - if (valueTemplate === "") { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty value template"); - flag = true; - } - - if (flag === true) { - throw new Error("missing label configuration"); - } - - const map = buildMap(data, selector, labelTemplate, valueTemplate, filter); - - const options = []; - if (!isIterable(map)) { - throw new Error("map is not iterable"); - } - - const visibility = "visible"; - - map.forEach((label, value) => { - options.push({ - value, - label, - visibility, - data: map.get(value), - }); - }); - - runAsOptionLengthChanged.call(this, map.size); - this.setOption("options", options); - - fireCustomEvent(this, "monster-options-set", { - options, - }); - - return this; - } - - /** - * @private - * @return {Select} - */ - calcAndSetOptionsDimension() { - calcAndSetOptionsDimension.call(this); - return this; - } - - /** - * - * @return {string} - */ - static getTag() { - return "monster-select"; - } - - /** - * - * @return {CSSStyleSheet[]} - */ - static getCSSStyleSheet() { - return [SelectStyleSheet]; - } + /** + * @extends CustomControl + */ + constructor() { + super(); + initOptionObserver.call(this); + } + + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + * @since 2.1.0 + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/components/form/select@@instance"); + } + + /** + * The current selection of the Select + * + * ``` + * e = document.querySelector('monster-select'); + * console.log(e.value) + * // ↦ 1 + * // ↦ ['1','2'] + * ``` + * + * @property {string|array} + */ + get value() { + return convertSelectionToValue.call(this, this.getOption("selection")); + } + + /** + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals} + * @return {boolean} + */ + static get formAssociated() { + return true; + } + + /** + * Set selection + * + * ``` + * e = document.querySelector('monster-select'); + * e.value=1 + * ``` + * + * @property {string|array} value + * @since 1.2.0 + * @throws {Error} unsupported type + */ + set value(value) { + const result = convertValueToSelection.call(this, value); + setSelection + .call(this, result.selection) + .then(() => {}) + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + } + + /** + * To set the options via the html tag the attribute `data-monster-options` must be used. + * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} + * + * The individual configuration values can be found in the table. + * + * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown + * @property {boolean} delegatesFocus=false lorem [see mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus) + * @property {Object[]} options Selection of key identifier pairs available for selection and displayed in the dropdown. + * @property {string} options[].label + * @property {string} options[].value + * @property {string} options[].visibility hidden or visible + * @property {Array} selection Selected options + * @property {Integer} showMaxOptions=10 Maximum number of visible options before a scroll bar should be displayed. + * @property {string} type=radio Multiple (checkbox) or single selection (radio) + * @property {string} name=(random id) Name of the form field + * @property {string} url Load options from server per url + * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) + * @property {String} fetch.redirect=error + * @property {String} fetch.method=GET + * @property {String} fetch.mode=same-origin + * @property {String} fetch.credentials=same-origin + * @property {Object} fetch.headers={"accept":"application/json"}} + * @property {Object} labels + * @property {string} labels.cannot-be-loaded cannot be loaded + * @property {string} labels.no-options-available no options available + * @property {string} labels.select-an-option select an option + * @property {string} labels.no-option no option in the list, maybe you have to change the filter + * @property {Object} features List with features + * @property {Boolean} features.clearAll=true Display of a delete button to delete the entire selection + * @property {Boolean} features.clear=true Display of a delete key for deleting the specific selection + * @property {Boolean} features.lazyLoad=false Load options when first opening the dropdown + * @property {Boolean} features.closeOnSelect=false Close the dropdown when an option is selected (since 3.54.0) + * @property {Boolean} features.emptyValueIfNoOptions=false If no options are available, the selection is set to an empty array + * @property {Boolean} features.storeFetchedData=false Store fetched data in the object + * @property {Boolean} features.useStrictValueComparison=true Use strict value comparison for the selection + * @property {Boolean} filter.defaultValue=* Default filter value, if the filter is empty + * @property {Boolean} filter.mode=options Filter mode, values: options, remote, disabled + * @property {Object} templates Template definitions + * @property {string} templates.main Main template + * @property {string} templateMapping Mapping of the template placeholders + * @property {string} templateMapping.selected Selected Template + * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/) + * @property {string} popper.placement=bottom PopperJS placement + * @property {Object[]} modifiers={name:offset} PopperJS placement + * @property {Object} mapping + * @property {String} mapping.selector=* Path to select the appropriate entries + * @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key (**) + * @property {String} mapping.valueTemplate="" template with the value placeholders in the form ${name}, where name is the key + * @property {Monster.Components.Form~exampleFilterCallback|undefined} mapping.filter Filtering of values via a function + * @property {Object} formatter + * @property {Monster.Components.Form~formatterSelectionCallback|undefined} formatter.selection format selection label + */ + get defaults() { + return Object.assign( + {}, + super.defaults, + { + toggleEventType: ["click", "touch"], + delegatesFocus: false, + options: [], + selection: [], + showMaxOptions: 10, + type: "radio", + name: new ID("s").toString(), + features: { + clearAll: true, + clear: true, + lazyLoad: false, + closeOnSelect: false, + emptyValueIfNoOptions: false, + storeFetchedData: false, + useStrictValueComparison: false, + }, + url: null, + labels: { + "cannot-be-loaded": "Cannot be loaded", + "no-options-available": noOptionsAvailableMessage, + "click-to-load-options": clickToLoadOptionsMessage, + "select-an-option": "Select an option", + "summary-text": { + zero: "No entries were selected", + one: '<span class="monster-badge-primary-pill">1</span> entry was selected', + other: + '<span class="monster-badge-primary-pill">${count}</span> entries were selected', + }, + "no-options": + "Unfortunately, there are no options available in the list.", + "no-options-found": + "No options are available in the list. Please consider modifying the filter.", + }, + messages: { + control: null, + selected: null, + emptyOptions: null, + }, + fetch: { + redirect: "error", + method: "GET", + mode: "same-origin", + credentials: "same-origin", + headers: { + accept: "application/json", + }, + }, + filter: { + defaultValue: "*", + mode: FILTER_MODE_DISABLED, + position: FILTER_POSITION_INLINE, + }, + classes: { + badge: "monster-badge-primary", + statusOrRemoveBadge: "empty", + }, + mapping: { + selector: "*", + labelTemplate: "", + valueTemplate: "", + filter: null, + }, + formatter: { + selection: buildSelectionLabel, + }, + templates: { + main: getTemplate(), + }, + templateMapping: { + /** with the attribute `data-monster-selected-template` the template for the selected options can be defined. */ + selected: getSelectionTemplate(), + }, + + popper: { + placement: "bottom", + middleware: ["flip", "offset:1"], + }, + }, + initOptionsFromArguments.call(this), + ); + } + + /** + * @return {Monster.Components.Form.Select} + */ + [assembleMethodSymbol]() { + const self = this; + super[assembleMethodSymbol](); + + initControlReferences.call(self); + initEventHandler.call(self); + + const lazyLoadFlag = self.getOption("features.lazyLoad"); + + if (self.hasAttribute("value")) { + new Processing(10, () => { + this.value = this.getAttribute("value"); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + } + + if (self.getOption("url") !== null && !lazyLoadFlag) { + self.fetch(); + } + + let lastValue = self.value; + self[internalSymbol].attachObserver( + new Observer(function () { + if (isObject(this) && this instanceof ProxyObserver) { + const n = this.getSubject()?.options?.value; + + if (lastValue !== n) { + lastValue = n; + setSelection + .call(self, n) + .then(() => {}) + .catch((e) => { + addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`); + }); + } + } + }), + ); + + areOptionsAvailableAndInit.call(self); + + return this; + } + + /** + * + * @returns {*} + * @throws {Error} storeFetchedData is not enabled + * @since 3.66.0 + */ + getLastFetchedData() { + if (this.getOption("features.storeFetchedData") === false) { + throw new Error("storeFetchedData is not enabled"); + } + + return this?.[lastFetchedDataSymbol]; + } + + /** + * The Button.click() method simulates a click on the internal button element. + * + * @since 3.27.0 + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click} + */ + click() { + if (this.getOption("disabled") === true) { + return; + } + + toggle.call(this); + } + + /** + * The Button.focus() method sets focus on the internal button element. + * + * @since 3.27.0 + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus} + */ + focus(options) { + if (this.getOption("disabled") === true) { + return; + } + + new Processing(() => { + gatherState.call(this); + focusFilter.call(this, options); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); + }); + } + + /** + * The Button.blur() method removes focus from the internal button element. + * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur + */ + blur() { + new Processing(() => { + gatherState.call(this); + blurFilter.call(this); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); + }); + } + + /** + * If no url is specified, the options are taken from the Component itself. + * + * @param {string|URL} url URL to fetch the options + * @return {Promise} + */ + fetch(url) { + if (url instanceof URL) { + url = url.toString(); + } + + if (url !== undefined && url !== null) { + url = validateString(url); + } else { + url = this.getOption("url"); + if (url === null) { + return Promise.reject(new Error("No url defined")); + } + } + + hide.call(this); + + return new Promise((resolve, reject) => { + setStatusOrRemoveBadges.call(this, "loading"); + + new Processing(10, () => { + this.setOption("options", []); + + fetchData + .call(this, url) + .then((map) => { + this[isLoadingSymbol] = false; + if ( + isObject(map) || + isArray(map) || + map instanceof Set || + map instanceof Map + ) { + this.importOptions(map); + this[lastFetchedDataSymbol] = map; + + let result; + const selection = this.getOption("selection"); + if (selection) { + result = setSelection.call(this, selection); + } else if (this.hasAttribute("value")) { + result = setSelection.call(this, this.getAttribute("value")); + } else { + result = setSelection.call(this, []); + } + + setTimeout(() => { + setStatusOrRemoveBadges.call(this, "closed"); + resolve(); + }, 10); + + return result; + } + + setStatusOrRemoveBadges.call(this, "error"); + reject(new Error("invalid response")); + }) + .catch((e) => { + this[isLoadingSymbol] = false; + setStatusOrRemoveBadges.call(this, "error"); + reject(e); + }); + }) + .run() + .catch((e) => { + setStatusOrRemoveBadges.call(this, "error"); + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + }); + } + + /** + * @return {void} + */ + connectedCallback() { + super.connectedCallback(); + const document = getDocument(); + + for (const [, type] of Object.entries(["click", "touch"])) { + // close on outside ui-events + document.addEventListener(type, this[closeEventHandler]); + } + + parseSlotsToOptions.call(this); + attachResizeObserver.call(this); + updatePopper.call(this); + + new Processing(() => { + gatherState.call(this); + focusFilter.call(this); + }).run(); + } + + /** + * @return {void} + */ + disconnectedCallback() { + super.disconnectedCallback(); + const document = getDocument(); + + // close on outside ui-events + for (const [, type] of Object.entries(["click", "touch"])) { + document.removeEventListener(type, this[closeEventHandler]); + } + + disconnectResizeObserver.call(this); + } + + /** + * Import Select Options from dataset + * Not to be confused with the control defaults/options + * + * @since 0.16.0 + * @param {array|object|Map|Set} data + * @return {Select} + * @throws {Error} map is not iterable + * @throws {Error} missing label configuration + */ + importOptions(data) { + const mappingOptions = this.getOption("mapping", {}); + const selector = mappingOptions?.["selector"]; + const labelTemplate = mappingOptions?.["labelTemplate"]; + const valueTemplate = mappingOptions?.["valueTemplate"]; + const filter = mappingOptions?.["filter"]; + + let flag = false; + if (labelTemplate === "") { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template"); + flag = true; + } + + if (valueTemplate === "") { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty value template"); + flag = true; + } + + if (flag === true) { + throw new Error("missing label configuration"); + } + + const map = buildMap(data, selector, labelTemplate, valueTemplate, filter); + + const options = []; + if (!isIterable(map)) { + throw new Error("map is not iterable"); + } + + const visibility = "visible"; + + map.forEach((label, value) => { + options.push({ + value, + label, + visibility, + data: map.get(value), + }); + }); + + runAsOptionLengthChanged.call(this, map.size); + this.setOption("options", options); + + fireCustomEvent(this, "monster-options-set", { + options, + }); + + return this; + } + + /** + * @private + * @return {Select} + */ + calcAndSetOptionsDimension() { + calcAndSetOptionsDimension.call(this); + return this; + } + + /** + * + * @return {string} + */ + static getTag() { + return "monster-select"; + } + + /** + * + * @return {CSSStyleSheet[]} + */ + static getCSSStyleSheet() { + return [SelectStyleSheet]; + } } /** @@ -871,64 +864,64 @@ class Select extends CustomControl { * @return {object} */ function initOptionsFromArguments() { - const options = {}; - - const template = this.getAttribute("data-monster-selected-template"); - if (isString(template)) { - if (!options["templateMapping"]) options["templateMapping"] = {}; - - switch (template) { - case "summary": - case "default": - options["templateMapping"]["selected"] = getSummaryTemplate(); - break; - case "selected": - options["templateMapping"]["selected"] = getSelectionTemplate(); - break; - default: - addAttributeToken( - this, - ATTRIBUTE_ERRORMESSAGE, - "invalid template, use summary or selected", - ); - } - } - - return options; + const options = {}; + + const template = this.getAttribute("data-monster-selected-template"); + if (isString(template)) { + if (!options["templateMapping"]) options["templateMapping"] = {}; + + switch (template) { + case "summary": + case "default": + options["templateMapping"]["selected"] = getSummaryTemplate(); + break; + case "selected": + options["templateMapping"]["selected"] = getSelectionTemplate(); + break; + default: + addAttributeToken( + this, + ATTRIBUTE_ERRORMESSAGE, + "invalid template, use summary or selected", + ); + } + } + + return options; } /** * @private */ function attachResizeObserver() { - // against flickering - this[resizeObserverSymbol] = new ResizeObserver((entries) => { - if (this[timerCallbackSymbol] instanceof DeadMansSwitch) { - try { - this[timerCallbackSymbol].touch(); - return; - } catch (e) { - delete this[timerCallbackSymbol]; - } - } - - this[timerCallbackSymbol] = new DeadMansSwitch(200, () => { - updatePopper.call(this); - delete this[timerCallbackSymbol]; - }); - }); - - this[resizeObserverSymbol].observe(this.parentElement); + // against flickering + this[resizeObserverSymbol] = new ResizeObserver((entries) => { + if (this[timerCallbackSymbol] instanceof DeadMansSwitch) { + try { + this[timerCallbackSymbol].touch(); + return; + } catch (e) { + delete this[timerCallbackSymbol]; + } + } + + this[timerCallbackSymbol] = new DeadMansSwitch(200, () => { + updatePopper.call(this); + delete this[timerCallbackSymbol]; + }); + }); + + this[resizeObserverSymbol].observe(this.parentElement); } function disconnectResizeObserver() { - if (this[resizeObserverSymbol] instanceof ResizeObserver) { - this[resizeObserverSymbol].disconnect(); - } + if (this[resizeObserverSymbol] instanceof ResizeObserver) { + this[resizeObserverSymbol].disconnect(); + } } function getSelectionTemplate() { - return `<div data-monster-role="selection" + return `<div data-monster-role="selection" data-monster-insert="selection path:selection" role="search" ><input type="text" role="searchbox" part="inline-filter" name="inline-filter" @@ -940,7 +933,7 @@ function getSelectionTemplate() { } function getSummaryTemplate() { - return `<div data-monster-role="selection" role="search"> + return `<div data-monster-role="selection" role="search"> <input type="text" role="searchbox" part="inline-filter" name="inline-filter" data-monster-role="filter" @@ -956,35 +949,35 @@ function getSummaryTemplate() { * @private */ function parseSlotsToOptions() { - let options = this.getOption("options"); - if (!isIterable(options)) { - options = []; - } - - let counter = 1; - getSlottedElements.call(this, "div").forEach((node) => { - let value = (counter++).toString(); - let visibility = "visible"; - - if (node.hasAttribute("data-monster-value")) { - value = node.getAttribute("data-monster-value"); - } - - if (node.style.display === "none") { - visibility = "hidden"; - } - - const label = node.outerHTML; - - options.push({ - value, - label, - visibility, - }); - }); - - runAsOptionLengthChanged.call(this, options.length); - this.setOption("options", options); + let options = this.getOption("options"); + if (!isIterable(options)) { + options = []; + } + + let counter = 1; + getSlottedElements.call(this, "div").forEach((node) => { + let value = (counter++).toString(); + let visibility = "visible"; + + if (node.hasAttribute("data-monster-value")) { + value = node.getAttribute("data-monster-value"); + } + + if (node.style.display === "none") { + visibility = "hidden"; + } + + const label = node.outerHTML; + + options.push({ + value, + label, + visibility, + }); + }); + + runAsOptionLengthChanged.call(this, options.length); + this.setOption("options", options); } /** @@ -994,39 +987,39 @@ function parseSlotsToOptions() { * @param {int} targetLength */ function runAsOptionLengthChanged(targetLength) { - const self = this; - - if (!self[optionsElementSymbol]) { - return; - } - - const callback = function (mutationsList, observer) { - const run = false; - for (const mutation of mutationsList) { - if (mutation.type === "childList") { - const run = true; - break; - } - } - - if (run === true) { - const nodes = self[optionsElementSymbol].querySelectorAll( - `div[${ATTRIBUTE_ROLE}=option]`, - ); - - if (nodes.length === targetLength) { - checkOptionState.call(self); - observer.disconnect(); - } - } - }; - - const observer = new MutationObserver(callback); - observer.observe(self[optionsElementSymbol], { - attributes: false, - childList: true, - subtree: true, - }); + const self = this; + + if (!self[optionsElementSymbol]) { + return; + } + + const callback = function (mutationsList, observer) { + const run = false; + for (const mutation of mutationsList) { + if (mutation.type === "childList") { + const run = true; + break; + } + } + + if (run === true) { + const nodes = self[optionsElementSymbol].querySelectorAll( + `div[${ATTRIBUTE_ROLE}=option]`, + ); + + if (nodes.length === targetLength) { + checkOptionState.call(self); + observer.disconnect(); + } + } + }; + + const observer = new MutationObserver(callback); + observer.observe(self[optionsElementSymbol], { + attributes: false, + childList: true, + subtree: true, + }); } /** @@ -1035,38 +1028,38 @@ function runAsOptionLengthChanged(targetLength) { * @return {*} */ function buildSelectionLabel(value) { - const options = this.getOption("options"); - - for (let i = 0; i < options.length; i++) { - let o = options?.[i]; - let l, v, v2; - - if (this.getOption("features.useStrictValueComparison") === true) { - v = value; - } else { - v = `${value}`; - } - - if (isPrimitive(o) && o === value) { - return o; - } else if (!isObject(o)) { - continue; - } - - if (this.getOption("features.useStrictValueComparison") === true) { - l = o?.["label"] - v2 = o?.["value"] - } else { - l = `${o?.["label"]}`; - v2 = `${o?.["value"]}`; - } - - if (v2 === v) { - return l; - } - } - - return undefined; + const options = this.getOption("options"); + + for (let i = 0; i < options.length; i++) { + let o = options?.[i]; + let l, v, v2; + + if (this.getOption("features.useStrictValueComparison") === true) { + v = value; + } else { + v = `${value}`; + } + + if (isPrimitive(o) && o === value) { + return o; + } else if (!isObject(o)) { + continue; + } + + if (this.getOption("features.useStrictValueComparison") === true) { + l = o?.["label"]; + v2 = o?.["value"]; + } else { + l = `${o?.["label"]}`; + v2 = `${o?.["value"]}`; + } + + if (v2 === v) { + return l; + } + } + + return undefined; } /** @@ -1076,17 +1069,17 @@ function buildSelectionLabel(value) { * @throws {Error} no value found */ function getSelectionLabel(value) { - const callback = this.getOption("formatter.selection"); - if (isFunction(callback)) { - const label = callback.call(this, value); - if (isString(label)) return label; - } + const callback = this.getOption("formatter.selection"); + if (isFunction(callback)) { + const label = callback.call(this, value); + if (isString(label)) return label; + } - if (isString(value) || isInteger(value)) { - return `${value}`; - } + if (isString(value) || isInteger(value)) { + return `${value}`; + } - return this.getOption("labels.cannot-be-loaded", value); + return this.getOption("labels.cannot-be-loaded", value); } /** @@ -1094,25 +1087,25 @@ function getSelectionLabel(value) { * @param {Event} event */ function handleToggleKeyboardEvents(event) { - switch (event?.["code"]) { - case "Escape": - toggle.call(this); - event.preventDefault(); - break; - case "Space": - toggle.call(this); - event.preventDefault(); - break; - case "ArrowDown": - show.call(this); - activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); - event.preventDefault(); - break; - case "ArrowUp": - hide.call(this); - event.preventDefault(); - break; - } + switch (event?.["code"]) { + case "Escape": + toggle.call(this); + event.preventDefault(); + break; + case "Space": + toggle.call(this); + event.preventDefault(); + break; + case "ArrowDown": + show.call(this); + activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); + event.preventDefault(); + break; + case "ArrowUp": + hide.call(this); + event.preventDefault(); + break; + } } /** @@ -1122,38 +1115,35 @@ function handleToggleKeyboardEvents(event) { * @this CustomElement */ function initOptionObserver() { - const self = this; - - self.attachObserver( - new Observer(function () { - new Processing(() => { - try { - self.updateI18n(); - } catch (e) { - } - try { - areOptionsAvailableAndInit.call(self); - } catch (e) { - } - - setSummaryAndControlText.call(self); - }).run(); - }), - ); + const self = this; + + self.attachObserver( + new Observer(function () { + new Processing(() => { + try { + self.updateI18n(); + } catch (e) {} + try { + areOptionsAvailableAndInit.call(self); + } catch (e) {} + + setSummaryAndControlText.call(self); + }).run(); + }), + ); } function getDefaultTranslation() { - const translation = new Translations("en").assignTranslations( - this.getOption("labels", {}), - ); + const translation = new Translations("en").assignTranslations( + this.getOption("labels", {}), + ); - try { - const doc = getDocumentTranslations(); - translation.locale = doc.locale; - } catch (e) { - } + try { + const doc = getDocumentTranslations(); + translation.locale = doc.locale; + } catch (e) {} - return translation; + return translation; } /** @@ -1161,36 +1151,36 @@ function getDefaultTranslation() { * @returns {string|*} */ function setSummaryAndControlText() { - const translations = getDefaultTranslation.call(this); - const selections = this.getOption("selection"); - - const text = translations.getPluralRuleText( - "summary-text", - selections.length, - "", - ); - - const selectedText = new Formatter({ - count: String(selections.length), - }).format(text); - - this.setOption("messages.selected", selectedText); - - const current = this.getOption("messages.control"); - const msg = this.getOption("labels.select-an-option"); - - if ( - current === "" || - current === undefined || - current === msg || - current === null - ) { - if (selections === undefined || selections.length === 0) { - this.setOption("messages.control", msg); - } else { - this.setOption("messages.control", ""); - } - } + const translations = getDefaultTranslation.call(this); + const selections = this.getOption("selection"); + + const text = translations.getPluralRuleText( + "summary-text", + selections.length, + "", + ); + + const selectedText = new Formatter({ + count: String(selections.length), + }).format(text); + + this.setOption("messages.selected", selectedText); + + const current = this.getOption("messages.control"); + const msg = this.getOption("labels.select-an-option"); + + if ( + current === "" || + current === undefined || + current === msg || + current === null + ) { + if (selections === undefined || selections.length === 0) { + this.setOption("messages.control", msg); + } else { + this.setOption("messages.control", ""); + } + } } /** @@ -1198,9 +1188,9 @@ function setSummaryAndControlText() { * @return {NodeList} */ function getOptionElements() { - return this[optionsElementSymbol].querySelectorAll( - `[${ATTRIBUTE_ROLE}=option]`, - ); + return this[optionsElementSymbol].querySelectorAll( + `[${ATTRIBUTE_ROLE}=option]`, + ); } /** @@ -1226,82 +1216,82 @@ function getOptionElements() { * @private */ function calcAndSetOptionsDimension() { - const options = getOptionElements.call(this); - const container = this[optionsElementSymbol]; - if (!(container instanceof HTMLElement && options instanceof NodeList)) { - return; - } - - let visible = 0; - let optionHeight = 0; - const max = this.getOption("showMaxOptions", 10); - - let scrollFlag = false; - for (const [, option] of Object.entries(options)) { - const computedStyle = getGlobal().getComputedStyle(option); - if (computedStyle.display === "none") continue; - - let h = option.getBoundingClientRect().height; - h += parseInt(computedStyle.getPropertyValue("margin-top"), 10); - h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10); - optionHeight += h; - - visible++; - - if (visible > max) { - break; - } - } - - if (visible > max) { - visible = max; - scrollFlag = true; - } - - if (visible === 0) { - if (this.getOption("options").length === 0) { - this.setOption( - "messages.emptyOptions", - this.getOption("labels.no-options-available"), - ); - } else { - if (this.getOption("filter.mode") === FILTER_MODE_DISABLED) { - this.setOption( - "messages.emptyOptions", - this.getOption("labels.no-options-available"), - ); - } else { - this.setOption( - "messages.emptyOptions", - this.getOption("labels.no-options-found"), - ); - } - } - this[noOptionsAvailableElementSymbol].classList.remove("d-none"); - } else { - this[noOptionsAvailableElementSymbol].classList.add("d-none"); - } - - const styles = getGlobal().getComputedStyle(this[optionsElementSymbol]); - let padding = parseInt(styles.getPropertyValue("padding-top"), 10); - padding += parseInt(styles.getPropertyValue("padding-bottom"), 10); - - let margin = parseInt(styles.getPropertyValue("margin-top"), 10); - margin += parseInt(styles.getPropertyValue("margin-bottom"), 10); - - const containerHeight = optionHeight + padding + margin; - container.style.height = `${containerHeight}px`; - - if (scrollFlag === true) { - container.style.overflowY = "scroll"; - } else { - container.style.overflowY = "auto"; - } - - const domRect = this[controlElementSymbol].getBoundingClientRect(); - - this[popperElementSymbol].style.width = `${domRect.width}px`; - container.style.overflowX = "auto"; + const options = getOptionElements.call(this); + const container = this[optionsElementSymbol]; + if (!(container instanceof HTMLElement && options instanceof NodeList)) { + return; + } + + let visible = 0; + let optionHeight = 0; + const max = this.getOption("showMaxOptions", 10); + + let scrollFlag = false; + for (const [, option] of Object.entries(options)) { + const computedStyle = getGlobal().getComputedStyle(option); + if (computedStyle.display === "none") continue; + + let h = option.getBoundingClientRect().height; + h += parseInt(computedStyle.getPropertyValue("margin-top"), 10); + h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10); + optionHeight += h; + + visible++; + + if (visible > max) { + break; + } + } + + if (visible > max) { + visible = max; + scrollFlag = true; + } + + if (visible === 0) { + if (this.getOption("options").length === 0) { + this.setOption( + "messages.emptyOptions", + this.getOption("labels.no-options-available"), + ); + } else { + if (this.getOption("filter.mode") === FILTER_MODE_DISABLED) { + this.setOption( + "messages.emptyOptions", + this.getOption("labels.no-options-available"), + ); + } else { + this.setOption( + "messages.emptyOptions", + this.getOption("labels.no-options-found"), + ); + } + } + this[noOptionsAvailableElementSymbol].classList.remove("d-none"); + } else { + this[noOptionsAvailableElementSymbol].classList.add("d-none"); + } + + const styles = getGlobal().getComputedStyle(this[optionsElementSymbol]); + let padding = parseInt(styles.getPropertyValue("padding-top"), 10); + padding += parseInt(styles.getPropertyValue("padding-bottom"), 10); + + let margin = parseInt(styles.getPropertyValue("margin-top"), 10); + margin += parseInt(styles.getPropertyValue("margin-bottom"), 10); + + const containerHeight = optionHeight + padding + margin; + container.style.height = `${containerHeight}px`; + + if (scrollFlag === true) { + container.style.overflowY = "scroll"; + } else { + container.style.overflowY = "auto"; + } + + const domRect = this[controlElementSymbol].getBoundingClientRect(); + + this[popperElementSymbol].style.width = `${domRect.width}px`; + container.style.overflowX = "auto"; } /** @@ -1310,126 +1300,126 @@ function calcAndSetOptionsDimension() { * @throws {Error} no shadow-root is defined */ function activateCurrentOption(direction) { - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - let focused = this.shadowRoot.querySelector(`[${ATTRIBUTE_PREFIX}focused]`); - - if ( - !(focused instanceof HTMLElement) || - focused.matches("[data-monster-visibility=hidden]") - ) { - for (const [, e] of Object.entries( - this.shadowRoot.querySelectorAll(`[${ATTRIBUTE_ROLE}=option]`), - )) { - if (e.matches("[data-monster-visibility=visible]")) { - focused = e; - break; - } - } - } else { - if (direction === FOCUS_DIRECTION_DOWN) { - while (focused.nextSibling) { - focused = focused.nextSibling; - - if ( - focused instanceof HTMLElement && - focused.hasAttribute(ATTRIBUTE_ROLE) && - focused.getAttribute(ATTRIBUTE_ROLE) === "option" && - focused.matches("[data-monster-visibility=visible]") && - focused.matches(":not([data-monster-filtered=true])") - ) { - break; - } - } - } else { - let found = false; - while (focused.previousSibling) { - focused = focused.previousSibling; - if ( - focused instanceof HTMLElement && - focused.hasAttribute(ATTRIBUTE_ROLE) && - focused.getAttribute(ATTRIBUTE_ROLE) === "option" && - focused.matches("[data-monster-visibility=visible]") && - focused.matches(":not([data-monster-filtered=true])") - ) { - found = true; - break; - } - } - if (found === false) { - focusFilter.call(this); - } - } - } - - new Processing(() => { - if (focused instanceof HTMLElement) { - this.shadowRoot - .querySelectorAll(`[${ATTRIBUTE_PREFIX}focused]`) - .forEach((e) => { - e.removeAttribute(`${ATTRIBUTE_PREFIX}focused`); - }); - - focused.focus(); - focused.setAttribute(`${ATTRIBUTE_PREFIX}focused`, true); - } - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + let focused = this.shadowRoot.querySelector(`[${ATTRIBUTE_PREFIX}focused]`); + + if ( + !(focused instanceof HTMLElement) || + focused.matches("[data-monster-visibility=hidden]") + ) { + for (const [, e] of Object.entries( + this.shadowRoot.querySelectorAll(`[${ATTRIBUTE_ROLE}=option]`), + )) { + if (e.matches("[data-monster-visibility=visible]")) { + focused = e; + break; + } + } + } else { + if (direction === FOCUS_DIRECTION_DOWN) { + while (focused.nextSibling) { + focused = focused.nextSibling; + + if ( + focused instanceof HTMLElement && + focused.hasAttribute(ATTRIBUTE_ROLE) && + focused.getAttribute(ATTRIBUTE_ROLE) === "option" && + focused.matches("[data-monster-visibility=visible]") && + focused.matches(":not([data-monster-filtered=true])") + ) { + break; + } + } + } else { + let found = false; + while (focused.previousSibling) { + focused = focused.previousSibling; + if ( + focused instanceof HTMLElement && + focused.hasAttribute(ATTRIBUTE_ROLE) && + focused.getAttribute(ATTRIBUTE_ROLE) === "option" && + focused.matches("[data-monster-visibility=visible]") && + focused.matches(":not([data-monster-filtered=true])") + ) { + found = true; + break; + } + } + if (found === false) { + focusFilter.call(this); + } + } + } + + new Processing(() => { + if (focused instanceof HTMLElement) { + this.shadowRoot + .querySelectorAll(`[${ATTRIBUTE_PREFIX}focused]`) + .forEach((e) => { + e.removeAttribute(`${ATTRIBUTE_PREFIX}focused`); + }); + + focused.focus(); + focused.setAttribute(`${ATTRIBUTE_PREFIX}focused`, true); + } + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); } /** * @private */ function filterOptions() { - new Processing(() => { - let filterValue; - - switch (this.getOption("filter.position")) { - case FILTER_POSITION_INLINE: - if (this[inlineFilterElementSymbol] instanceof HTMLElement) { - filterValue = this[inlineFilterElementSymbol].value.toLowerCase(); - } else { - return; - } - - break; - case FILTER_POSITION_POPPER: - default: - if (this[popperFilterElementSymbol] instanceof HTMLInputElement) { - filterValue = this[popperFilterElementSymbol].value.toLowerCase(); - } else { - return; - } - } - - const options = this.getOption("options"); - for (const [i, option] of Object.entries(options)) { - if (option.label.toLowerCase().indexOf(filterValue) === -1) { - this.setOption(`options.${i}.filtered`, "true"); - } else { - this.setOption(`options.${i}.filtered`, undefined); - } - } - }) - .run() - .then(() => { - new Processing(100, () => { - calcAndSetOptionsDimension.call(this); - focusFilter.call(this); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - }) - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); + new Processing(() => { + let filterValue; + + switch (this.getOption("filter.position")) { + case FILTER_POSITION_INLINE: + if (this[inlineFilterElementSymbol] instanceof HTMLElement) { + filterValue = this[inlineFilterElementSymbol].value.toLowerCase(); + } else { + return; + } + + break; + case FILTER_POSITION_POPPER: + default: + if (this[popperFilterElementSymbol] instanceof HTMLInputElement) { + filterValue = this[popperFilterElementSymbol].value.toLowerCase(); + } else { + return; + } + } + + const options = this.getOption("options"); + for (const [i, option] of Object.entries(options)) { + if (option.label.toLowerCase().indexOf(filterValue) === -1) { + this.setOption(`options.${i}.filtered`, "true"); + } else { + this.setOption(`options.${i}.filtered`, undefined); + } + } + }) + .run() + .then(() => { + new Processing(100, () => { + calcAndSetOptionsDimension.call(this); + focusFilter.call(this); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + }) + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); } /** @@ -1437,37 +1427,37 @@ function filterOptions() { * @param {Event} event */ function handleFilterKeyboardEvents(event) { - const shiftKey = event?.["shiftKey"]; - - switch (event?.["code"]) { - case "Tab": - activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); - event.preventDefault(); - break; - case "Escape": - toggle.call(this); - event.preventDefault(); - break; - case "Tab" && shiftKey === true: - case "ArrowUp": - activateCurrentOption.call(this, FOCUS_DIRECTION_UP); - event.preventDefault(); - break; - case "Tab" && !shiftKey: - case "ArrowDown": - activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); - event.preventDefault(); - break; - default: - if ( - this.getOption("features.lazyLoad") === true && - this[lazyLoadDoneSymbol] !== true - ) { - this.click(); - } - - handleFilterKeyEvents.call(this); - } + const shiftKey = event?.["shiftKey"]; + + switch (event?.["code"]) { + case "Tab": + activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); + event.preventDefault(); + break; + case "Escape": + toggle.call(this); + event.preventDefault(); + break; + case "Tab" && shiftKey === true: + case "ArrowUp": + activateCurrentOption.call(this, FOCUS_DIRECTION_UP); + event.preventDefault(); + break; + case "Tab" && !shiftKey: + case "ArrowDown": + activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); + event.preventDefault(); + break; + default: + if ( + this.getOption("features.lazyLoad") === true && + this[lazyLoadDoneSymbol] !== true + ) { + this.click(); + } + + handleFilterKeyEvents.call(this); + } } /** @@ -1486,63 +1476,63 @@ function handleFilterKeyboardEvents(event) { * @returns {void} This method does not return anything. */ function handleFilterKeyEvents() { - if (this[keyFilterEventSymbol] instanceof DeadMansSwitch) { - try { - this[keyFilterEventSymbol].touch(); - return; - } catch (e) { - delete this[keyFilterEventSymbol]; - } - } - - this[keyFilterEventSymbol] = new DeadMansSwitch(200, () => { - if (this.getOption("filter.mode") !== FILTER_MODE_REMOTE) { - filterOptions.call(this); - } else { - filterFromRemote.call(this).catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - } - - delete this[keyFilterEventSymbol]; - }); + if (this[keyFilterEventSymbol] instanceof DeadMansSwitch) { + try { + this[keyFilterEventSymbol].touch(); + return; + } catch (e) { + delete this[keyFilterEventSymbol]; + } + } + + this[keyFilterEventSymbol] = new DeadMansSwitch(200, () => { + if (this.getOption("filter.mode") !== FILTER_MODE_REMOTE) { + filterOptions.call(this); + } else { + filterFromRemote.call(this).catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + } + + delete this[keyFilterEventSymbol]; + }); } /** * @private */ function filterFromRemote() { - if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) { - return; - } - - const optionUrl = this.getOption("url"); - if (!optionUrl) { - addAttributeToken( - this, - ATTRIBUTE_ERRORMESSAGE, - "Missing URL for Remote Filter.", - ); - return; - } - - return new Processing(() => { - const filterValue = encodeURI( - this[inlineFilterElementSymbol].value.toLowerCase(), - ); - let url = optionUrl; - if (filterValue.length > 0) { - url = new Formatter({filter: filterValue}).format(optionUrl); - } - - this.fetch(url) - .then(() => { - checkOptionState.call(this); - }) - .catch((e) => { - throw e; - }); - }).run(); + if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) { + return; + } + + const optionUrl = this.getOption("url"); + if (!optionUrl) { + addAttributeToken( + this, + ATTRIBUTE_ERRORMESSAGE, + "Missing URL for Remote Filter.", + ); + return; + } + + return new Processing(() => { + const filterValue = encodeURI( + this[inlineFilterElementSymbol].value.toLowerCase(), + ); + let url = optionUrl; + if (filterValue.length > 0) { + url = new Formatter({ filter: filterValue }).format(optionUrl); + } + + this.fetch(url) + .then(() => { + checkOptionState.call(this); + }) + .catch((e) => { + throw e; + }); + }).run(); } /** @@ -1551,50 +1541,50 @@ function filterFromRemote() { * @private */ function handleOptionKeyboardEvents(event) { - const shiftKey = event?.["shiftKey"]; - - switch (event?.["code"]) { - case "Escape": - toggle.call(this); - event.preventDefault(); - break; - case "Enter": - case "Space": - const path = event.composedPath(); - const element = path?.[0]; - if (element instanceof HTMLElement) { - const input = element.getElementsByTagName("input") - if (!input) { - return; - } - fireEvent(input, "click"); - } - event.preventDefault(); - break; - - case "Tab" && shiftKey === true: - case "ArrowUp": - activateCurrentOption.call(this, FOCUS_DIRECTION_UP); - event.preventDefault(); - break; - - case "Tab" && !shiftKey: - case "ArrowLeft": - case "ArrowRight": - // handled by tree select - break; - case "ArrowDown": - activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); - event.preventDefault(); - break; - default: - const p = event.composedPath(); - if (p?.[0] instanceof HTMLInputElement) { - return; - } - focusFilter.call(this); - break; - } + const shiftKey = event?.["shiftKey"]; + + switch (event?.["code"]) { + case "Escape": + toggle.call(this); + event.preventDefault(); + break; + case "Enter": + case "Space": + const path = event.composedPath(); + const element = path?.[0]; + if (element instanceof HTMLElement) { + const input = element.getElementsByTagName("input"); + if (!input) { + return; + } + fireEvent(input, "click"); + } + event.preventDefault(); + break; + + case "Tab" && shiftKey === true: + case "ArrowUp": + activateCurrentOption.call(this, FOCUS_DIRECTION_UP); + event.preventDefault(); + break; + + case "Tab" && !shiftKey: + case "ArrowLeft": + case "ArrowRight": + // handled by tree select + break; + case "ArrowDown": + activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN); + event.preventDefault(); + break; + default: + const p = event.composedPath(); + if (p?.[0] instanceof HTMLInputElement) { + return; + } + focusFilter.call(this); + break; + } } /** @@ -1602,33 +1592,33 @@ function handleOptionKeyboardEvents(event) { * @returns {string} */ function getFilterMode() { - switch (this.getOption("filter.mode")) { - case FILTER_MODE_OPTIONS: - return FILTER_MODE_OPTIONS; - case FILTER_MODE_REMOTE: - return FILTER_MODE_REMOTE; - default: - return FILTER_MODE_DISABLED; - } + switch (this.getOption("filter.mode")) { + case FILTER_MODE_OPTIONS: + return FILTER_MODE_OPTIONS; + case FILTER_MODE_REMOTE: + return FILTER_MODE_REMOTE; + default: + return FILTER_MODE_DISABLED; + } } /** * @private */ function blurFilter() { - if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) { - return; - } + if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) { + return; + } - if (getFilterMode.call(this) === FILTER_MODE_DISABLED) { - return; - } + if (getFilterMode.call(this) === FILTER_MODE_DISABLED) { + return; + } - this[popperFilterContainerElementSymbol].classList.remove("active"); - this[popperFilterContainerElementSymbol].blur(); + this[popperFilterContainerElementSymbol].classList.remove("active"); + this[popperFilterContainerElementSymbol].blur(); - this[inlineFilterElementSymbol].classList.remove("active"); - this[inlineFilterElementSymbol].blur(); + this[inlineFilterElementSymbol].classList.remove("active"); + this[inlineFilterElementSymbol].blur(); } /** @@ -1636,29 +1626,29 @@ function blurFilter() { * @param focusOptions */ function focusPopperFilter(focusOptions) { - this[popperFilterContainerElementSymbol].classList.remove("d-none"); - this[popperFilterElementSymbol].classList.add("active"); - this[inlineFilterElementSymbol].classList.remove("active"); - this[inlineFilterElementSymbol].classList.add("d-none"); - - if (!(this[popperFilterElementSymbol] instanceof HTMLElement)) { - addAttributeToken( - this, - ATTRIBUTE_ERRORMESSAGE, - "Missing Popper Filter Element.", - ); - return; - } - - // visibility is set to visible, because focus() does not work on invisible elements - // and the class definition is assigned later in the processing - setTimeout(() => { - if (focusOptions === undefined || focusOptions === null) { - this[popperFilterElementSymbol].focus(); - } else { - this[popperFilterElementSymbol].focus(focusOptions); - } - }, 100); + this[popperFilterContainerElementSymbol].classList.remove("d-none"); + this[popperFilterElementSymbol].classList.add("active"); + this[inlineFilterElementSymbol].classList.remove("active"); + this[inlineFilterElementSymbol].classList.add("d-none"); + + if (!(this[popperFilterElementSymbol] instanceof HTMLElement)) { + addAttributeToken( + this, + ATTRIBUTE_ERRORMESSAGE, + "Missing Popper Filter Element.", + ); + return; + } + + // visibility is set to visible, because focus() does not work on invisible elements + // and the class definition is assigned later in the processing + setTimeout(() => { + if (focusOptions === undefined || focusOptions === null) { + this[popperFilterElementSymbol].focus(); + } else { + this[popperFilterElementSymbol].focus(focusOptions); + } + }, 100); } /** @@ -1666,44 +1656,44 @@ function focusPopperFilter(focusOptions) { * @param focusOptions */ function focusInlineFilter(focusOptions) { - const options = this.getOption("options"); - if ( - (!isArray(options) || options.length === 0) && - this.getOption("filter.mode") !== FILTER_MODE_REMOTE - ) { - return; - } - - this[popperFilterContainerElementSymbol].classList.add("d-none"); - this[inlineFilterElementSymbol].classList.add("active"); - this[inlineFilterElementSymbol].classList.remove("d-none"); - - // visibility is set to visible, because focus() does not work on invisible elements - // and the class definition is assigned later in the processing - setTimeout(() => { - if (focusOptions === undefined || focusOptions === null) { - this[inlineFilterElementSymbol].focus(); - } else { - this[inlineFilterElementSymbol].focus(focusOptions); - } - }, 100); + const options = this.getOption("options"); + if ( + (!isArray(options) || options.length === 0) && + this.getOption("filter.mode") !== FILTER_MODE_REMOTE + ) { + return; + } + + this[popperFilterContainerElementSymbol].classList.add("d-none"); + this[inlineFilterElementSymbol].classList.add("active"); + this[inlineFilterElementSymbol].classList.remove("d-none"); + + // visibility is set to visible, because focus() does not work on invisible elements + // and the class definition is assigned later in the processing + setTimeout(() => { + if (focusOptions === undefined || focusOptions === null) { + this[inlineFilterElementSymbol].focus(); + } else { + this[inlineFilterElementSymbol].focus(focusOptions); + } + }, 100); } /** * @private */ function focusFilter(focusOptions) { - if (getFilterMode.call(this) === FILTER_MODE_DISABLED) { - this[popperFilterContainerElementSymbol].classList.add("d-none"); - this[inlineFilterElementSymbol].classList.add("d-none"); - return; - } + if (getFilterMode.call(this) === FILTER_MODE_DISABLED) { + this[popperFilterContainerElementSymbol].classList.add("d-none"); + this[inlineFilterElementSymbol].classList.add("d-none"); + return; + } - if (this.getOption("filter.position") === FILTER_POSITION_INLINE) { - return focusInlineFilter.call(this, focusOptions); - } + if (this.getOption("filter.position") === FILTER_POSITION_INLINE) { + return focusInlineFilter.call(this, focusOptions); + } - return focusPopperFilter.call(this, focusOptions); + return focusPopperFilter.call(this, focusOptions); } /** @@ -1713,41 +1703,39 @@ function focusFilter(focusOptions) { * @throws {Error} unsupported type */ function gatherState() { - - const type = this.getOption("type"); - if (["radio", "checkbox"].indexOf(type) === -1) { - throw new Error("unsupported type"); - } - - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - const selection = []; - const elements = this.shadowRoot.querySelectorAll( - `input[type=${type}]:checked`, - ); - - for (const e of elements) { - selection.push({ - label: getSelectionLabel.call(this, e.value), - value: e.value, - }); - } - - setSelection - .call(this, selection) - .then(() => { - }) - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); - }); - - if (this.getOption("features.closeOnSelect") === true) { - toggle.call(this); - } - - return this; + const type = this.getOption("type"); + if (["radio", "checkbox"].indexOf(type) === -1) { + throw new Error("unsupported type"); + } + + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + const selection = []; + const elements = this.shadowRoot.querySelectorAll( + `input[type=${type}]:checked`, + ); + + for (const e of elements) { + selection.push({ + label: getSelectionLabel.call(this, e.value), + value: e.value, + }); + } + + setSelection + .call(this, selection) + .then(() => {}) + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); + }); + + if (this.getOption("features.closeOnSelect") === true) { + toggle.call(this); + } + + return this; } /** @@ -1756,121 +1744,120 @@ function gatherState() { * @throws {Error} unsupported type */ function clearSelection() { - const type = this.getOption("type"); - if (["radio", "checkbox"].indexOf(type) === -1) { - throw new Error("unsupported type"); - } - - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - setSelection - .call(this, []) - .then(() => { - }) - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); - }); + const type = this.getOption("type"); + if (["radio", "checkbox"].indexOf(type) === -1) { + throw new Error("unsupported type"); + } + + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + setSelection + .call(this, []) + .then(() => {}) + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`); + }); } /** * @private */ function areOptionsAvailableAndInit() { - // prevent multiple calls - if (this[areOptionsAvailableAndInitSymbol] === undefined) { - this[areOptionsAvailableAndInitSymbol] = 0; - } - - if (this[areOptionsAvailableAndInitSymbol] > 0) { - this[areOptionsAvailableAndInitSymbol]--; - return true; - } - - this[areOptionsAvailableAndInitSymbol]++; - - const options = this.getOption("options"); - - if ( - options === undefined || - options === null || - (isArray(options) && options.length === 0) - ) { - setStatusOrRemoveBadges.call(this, "empty"); - - hide.call(this); - - let msg = this.getOption("labels.no-options-available"); - - if ( - this.getOption("url") !== null && - this.getOption("features.lazyLoad") === true && - this[lazyLoadDoneSymbol] !== true - ) { - msg = this.getOption("labels.click-to-load-options"); - } - - this.setOption("messages.control", msg); - this.setOption("messages.summary", ""); - - if (this.getOption("features.emptyValueIfNoOptions") === true) { - this.value = ""; - } - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage); - return false; - } - - const selections = this.getOption("selection"); - if ( - selections === undefined || - selections === null || - selections.length === 0 - ) { - this.setOption( - "messages.control", - this.getOption("labels.select-an-option"), - ); - } else { - this.setOption("messages.control", ""); - } - - this.setOption("messages.summary", setSummaryAndControlText.call(this)); - - let updated = false; - let valueCounter = 1; - for (const option of options) { - if (option?.visibility === undefined) { - option.visibility = "visible"; - updated = true; - } - - if (option?.value === undefined && option?.label === undefined) { - option.value = `${valueCounter++}`; - option.label = option.value; - updated = true; - continue; - } - - if (option?.value === undefined) { - option.value = option.label; - updated = true; - } - - if (option?.label === undefined) { - option.label = option.value; - updated = true; - } - } - - if (updated) { - this.setOption("options", options); - } - - setStatusOrRemoveBadges.call(this); - - removeAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage); - return true; + // prevent multiple calls + if (this[areOptionsAvailableAndInitSymbol] === undefined) { + this[areOptionsAvailableAndInitSymbol] = 0; + } + + if (this[areOptionsAvailableAndInitSymbol] > 0) { + this[areOptionsAvailableAndInitSymbol]--; + return true; + } + + this[areOptionsAvailableAndInitSymbol]++; + + const options = this.getOption("options"); + + if ( + options === undefined || + options === null || + (isArray(options) && options.length === 0) + ) { + setStatusOrRemoveBadges.call(this, "empty"); + + hide.call(this); + + let msg = this.getOption("labels.no-options-available"); + + if ( + this.getOption("url") !== null && + this.getOption("features.lazyLoad") === true && + this[lazyLoadDoneSymbol] !== true + ) { + msg = this.getOption("labels.click-to-load-options"); + } + + this.setOption("messages.control", msg); + this.setOption("messages.summary", ""); + + if (this.getOption("features.emptyValueIfNoOptions") === true) { + this.value = ""; + } + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage); + return false; + } + + const selections = this.getOption("selection"); + if ( + selections === undefined || + selections === null || + selections.length === 0 + ) { + this.setOption( + "messages.control", + this.getOption("labels.select-an-option"), + ); + } else { + this.setOption("messages.control", ""); + } + + this.setOption("messages.summary", setSummaryAndControlText.call(this)); + + let updated = false; + let valueCounter = 1; + for (const option of options) { + if (option?.visibility === undefined) { + option.visibility = "visible"; + updated = true; + } + + if (option?.value === undefined && option?.label === undefined) { + option.value = `${valueCounter++}`; + option.label = option.value; + updated = true; + continue; + } + + if (option?.value === undefined) { + option.value = option.label; + updated = true; + } + + if (option?.label === undefined) { + option.label = option.value; + updated = true; + } + } + + if (updated) { + this.setOption("options", options); + } + + setStatusOrRemoveBadges.call(this); + + removeAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage); + return true; } /** @@ -1878,30 +1865,30 @@ function areOptionsAvailableAndInit() { * @throws {Error} no shadow-root is defined */ function checkOptionState() { - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - const elements = this.shadowRoot.querySelectorAll( - `[${ATTRIBUTE_ROLE}=option] input`, - ); - - let selection = this.getOption("selection"); - if (!isArray(selection)) { - selection = []; - } - - const checkedValues = selection.map((a) => { - return a.value; - }); - - for (const e of elements) { - if (checkedValues.indexOf(e.value) !== -1) { - if (e.checked !== true) e.checked = true; - } else { - if (e.checked !== false) e.checked = false; - } - } + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + const elements = this.shadowRoot.querySelectorAll( + `[${ATTRIBUTE_ROLE}=option] input`, + ); + + let selection = this.getOption("selection"); + if (!isArray(selection)) { + selection = []; + } + + const checkedValues = selection.map((a) => { + return a.value; + }); + + for (const e of elements) { + if (checkedValues.indexOf(e.value) !== -1) { + if (e.checked !== true) e.checked = true; + } else { + if (e.checked !== false) e.checked = false; + } + } } /** @@ -1910,41 +1897,41 @@ function checkOptionState() { * @return {Object} */ function convertValueToSelection(value) { - const selection = []; - - if (isString(value)) { - value = value - .split(",") - .map((a) => { - return a.trim(); - }) - .filter((a) => { - return a !== ""; - }); - } - - if (isString(value) || isInteger(value)) { - selection.push({ - label: getSelectionLabel.call(this, value), - value: value, - }); - } else if (isArray(value)) { - for (const v of value) { - selection.push({ - label: getSelectionLabel.call(this, v), - value: v, - }); - } - - value = value.join(","); - } else { - throw new Error("unsupported type"); - } - - return { - selection: selection, - value: value, - }; + const selection = []; + + if (isString(value)) { + value = value + .split(",") + .map((a) => { + return a.trim(); + }) + .filter((a) => { + return a !== ""; + }); + } + + if (isString(value) || isInteger(value)) { + selection.push({ + label: getSelectionLabel.call(this, value), + value: value, + }); + } else if (isArray(value)) { + for (const v of value) { + selection.push({ + label: getSelectionLabel.call(this, v), + value: v, + }); + } + + value = value.join(","); + } else { + throw new Error("unsupported type"); + } + + return { + selection: selection, + value: value, + }; } /** @@ -1953,22 +1940,22 @@ function convertValueToSelection(value) { * @return {string} */ function convertSelectionToValue(selection) { - const value = []; - - if (isArray(selection)) { - for (const obj of selection) { - const v = obj?.["value"]; - if (v !== undefined) value.push(v); - } - } - - if (value.length === 0) { - return ""; - } else if (value.length === 1) { - return value.pop(); - } - - return value.join(","); + const value = []; + + if (isArray(selection)) { + for (const obj of selection) { + const v = obj?.["value"]; + if (v !== undefined) value.push(v); + } + } + + if (value.length === 0) { + return ""; + } else if (value.length === 1) { + return value.pop(); + } + + return value.join(","); } /** @@ -1978,59 +1965,58 @@ function convertSelectionToValue(selection) { * @throws {Error} no shadow-root is defined */ function setSelection(selection) { - - if (isString(selection)) { - const result = convertValueToSelection.call(this, selection); - selection = result?.selection; - } else if (selection === undefined) { - selection = []; - } - - this.setOption("selection", validateArray(selection)); - checkOptionState.call(this); - - try { - this?.setFormValue(this.value); - } catch (e) { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - } - - fireCustomEvent(this, "monster-selected", { - selection, - }); - - return new Processing(() => { - const CLASSNAME = "selected"; - - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - const notSelected = this.shadowRoot.querySelectorAll(":not(:checked)"); - - if (notSelected) { - notSelected.forEach((node) => { - const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`); - if (parent) { - parent.classList.remove(CLASSNAME); - } - }); - } - - const selected = this.shadowRoot.querySelectorAll(":checked"); - if (selected) { - selected.forEach((node) => { - const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`); - if (parent) { - parent.classList.add(CLASSNAME); - } - }); - } - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); + if (isString(selection)) { + const result = convertValueToSelection.call(this, selection); + selection = result?.selection; + } else if (selection === undefined) { + selection = []; + } + + this.setOption("selection", validateArray(selection)); + checkOptionState.call(this); + + try { + this?.setFormValue(this.value); + } catch (e) { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + } + + fireCustomEvent(this, "monster-selected", { + selection, + }); + + return new Processing(() => { + const CLASSNAME = "selected"; + + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + const notSelected = this.shadowRoot.querySelectorAll(":not(:checked)"); + + if (notSelected) { + notSelected.forEach((node) => { + const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`); + if (parent) { + parent.classList.remove(CLASSNAME); + } + }); + } + + const selected = this.shadowRoot.querySelectorAll(":checked"); + if (selected) { + selected.forEach((node) => { + const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`); + if (parent) { + parent.classList.add(CLASSNAME); + } + }); + } + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); } /** @@ -2041,124 +2027,125 @@ function setSelection(selection) { * @throws {TypeError} unsupported response */ function fetchData(url) { - if (!url) url = this.getOption("url"); - if (!url) return Promise.resolve(); - - const fetchOptions = this.getOption("fetch", {}); - - let delayWatch = false; - - // if fetch short time, do not show loading badge, because of flickering - setTimeout(() => { - if (delayWatch === true) return; - setStatusOrRemoveBadges.call(this, "loading"); - delayWatch = true; - }, 500); - - url = new Formatter({filter: this.getOption("filter.defaultValue")}).format( - url, - ); - - const global = getGlobal(); - return global - .fetch(url, fetchOptions) - .then((response) => { - delayWatch = true; - const contentType = response.headers.get("content-type"); - if (contentType && contentType.indexOf("application/json") !== -1) { - return response.text(); - } - - throw new TypeError(`unsupported response ${contentType}`); - }) - .then((text) => { - try { - return Promise.resolve(JSON.parse(String(text))); - } catch (e) { - throw new TypeError("the result cannot be parsed"); - } - }) - .catch((e) => { - delayWatch = true; - throw e; - }); + if (!url) url = this.getOption("url"); + if (!url) return Promise.resolve(); + + const fetchOptions = this.getOption("fetch", {}); + + let delayWatch = false; + + // if fetch short time, do not show loading badge, because of flickering + setTimeout(() => { + if (delayWatch === true) return; + setStatusOrRemoveBadges.call(this, "loading"); + delayWatch = true; + }, 500); + + url = new Formatter({ filter: this.getOption("filter.defaultValue") }).format( + url, + ); + + const global = getGlobal(); + return global + .fetch(url, fetchOptions) + .then((response) => { + delayWatch = true; + const contentType = response.headers.get("content-type"); + if (contentType && contentType.indexOf("application/json") !== -1) { + return response.text(); + } + + throw new TypeError(`unsupported response ${contentType}`); + }) + .then((text) => { + try { + return Promise.resolve(JSON.parse(String(text))); + } catch (e) { + throw new TypeError("the result cannot be parsed"); + } + }) + .catch((e) => { + delayWatch = true; + throw e; + }); } /** * @private */ function hide() { - this[popperElementSymbol].style.display = "none"; - setStatusOrRemoveBadges.call(this, "closed"); - removeAttributeToken(this[controlElementSymbol], "class", "open"); + this[popperElementSymbol].style.display = "none"; + setStatusOrRemoveBadges.call(this, "closed"); + removeAttributeToken(this[controlElementSymbol], "class", "open"); } /** * @private */ function show() { - if (this.getOption("disabled", undefined) === true) { - return; - } - - if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) { - return; - } - - focusFilter.call(this); - - const lazyLoadFlag = - this.getOption("features.lazyLoad") && this[lazyLoadDoneSymbol] !== true; - - if (lazyLoadFlag === true) { - this[lazyLoadDoneSymbol] = true; - setStatusOrRemoveBadges.call(this, "loading"); - - new Processing(200, () => { - this.fetch() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - setStatusOrRemoveBadges.call(this, "error"); - }); - }).run().catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - - return; - } - - const options = getOptionElements.call(this); - if (options.length === 0) { - return; - } - - this[popperElementSymbol].style.visibility = "hidden"; - this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK; - setStatusOrRemoveBadges.call(this, "open"); - - addAttributeToken(this[controlElementSymbol], "class", "open"); - - new Processing(() => { - calcAndSetOptionsDimension.call(this); - focusFilter.call(this); - this[popperElementSymbol].style.removeProperty("visibility"); - updatePopper.call(this); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); + if (this.getOption("disabled", undefined) === true) { + return; + } + + if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) { + return; + } + + focusFilter.call(this); + + const lazyLoadFlag = + this.getOption("features.lazyLoad") && this[lazyLoadDoneSymbol] !== true; + + if (lazyLoadFlag === true) { + this[lazyLoadDoneSymbol] = true; + setStatusOrRemoveBadges.call(this, "loading"); + + new Processing(200, () => { + this.fetch().catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + setStatusOrRemoveBadges.call(this, "error"); + }); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + + return; + } + + const options = getOptionElements.call(this); + if (options.length === 0) { + return; + } + + this[popperElementSymbol].style.visibility = "hidden"; + this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK; + setStatusOrRemoveBadges.call(this, "open"); + + addAttributeToken(this[controlElementSymbol], "class", "open"); + + new Processing(() => { + calcAndSetOptionsDimension.call(this); + focusFilter.call(this); + this[popperElementSymbol].style.removeProperty("visibility"); + updatePopper.call(this); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); } /** * @private */ function toggle() { - if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) { - hide.call(this); - } else { - show.call(this); - } + if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) { + hide.call(this); + } else { + show.call(this); + } } /** @@ -2167,188 +2154,188 @@ function toggle() { * @fires Monster.Components.Form.event:monster-selection-cleared */ function initEventHandler() { - const self = this; - - /** - * @param {Event} event - */ - self[clearOptionEventHandler] = (event) => { - const element = findTargetElementFromEvent( - event, - ATTRIBUTE_ROLE, - "remove-badge", - ); - - if (element instanceof HTMLElement) { - const badge = findClosestByAttribute(element, ATTRIBUTE_ROLE, "badge"); - if (badge instanceof HTMLElement) { - const value = badge.getAttribute(`${ATTRIBUTE_PREFIX}value`); - - let selection = self.getOption("selection"); - selection = selection.filter((b) => { - return value !== b.value; - }); - - setSelection - .call(self, selection) - .then(() => { - fireCustomEvent(self, "monster-selection-removed", { - value, - }); - }) - .catch((e) => { - addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - } - } - }; - - /** - * @param {Event} event - */ - self[closeEventHandler] = (event) => { - const path = event.composedPath(); - - for (const [, element] of Object.entries(path)) { - if (element === self) { - return; - } - } - hide.call(self); - }; - - /** - * @param {Event} event - */ - self[inputEventHandler] = (event) => { - const path = event.composedPath(); - const element = path?.[0]; - - if (element instanceof HTMLElement) { - if ( - element.hasAttribute(ATTRIBUTE_ROLE) && - element.getAttribute(ATTRIBUTE_ROLE) === "option-control" - ) { - fireCustomEvent(self, "monster-change", { - type: event.type, - value: element.value, - checked: element.checked, - }); - } else if ( - element.hasAttribute(ATTRIBUTE_ROLE) && - element.getAttribute(ATTRIBUTE_ROLE) === "filter" - ) { - } - } - }; - - /** - * @param {Event} event - */ - self[changeEventHandler] = (event) => { - gatherState.call(self); - fireCustomEvent(self, "monster-changed", event?.detail); - }; - - self[keyEventHandler] = (event) => { - const path = event.composedPath(); - const element = path.shift(); - - let role; - - if (element instanceof HTMLElement) { - if (element.hasAttribute(ATTRIBUTE_ROLE)) { - role = element.getAttribute(ATTRIBUTE_ROLE); - } else if (element === this) { - show.call(this); - // focusFilter.call(self); - } else { - const e = element.closest(`[${ATTRIBUTE_ROLE}]`); - if (e instanceof HTMLElement && e.hasAttribute(ATTRIBUTE_ROLE)) { - role = e.getAttribute(ATTRIBUTE_ROLE); - } - } - } else { - return; - } - - switch (role) { - case "filter": - handleFilterKeyboardEvents.call(self, event); - break; - case "option-label": - case "option-control": - case "option": - handleOptionKeyboardEvents.call(self, event); - break; - case "control": - case "toggle": - handleToggleKeyboardEvents.call(self, event); - break; - } - }; - - const types = self.getOption("toggleEventType", ["click"]); - - for (const [, type] of Object.entries(types)) { - self[controlElementSymbol] - .querySelector(`[${ATTRIBUTE_ROLE}="container"]`) - .addEventListener(type, function (event) { - const element = findTargetElementFromEvent( - event, - ATTRIBUTE_ROLE, - "remove-badge", - ); - if (element instanceof HTMLElement) { - return; - } - - toggle.call(self); - }); - - self[controlElementSymbol] - .querySelector(`[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`) - .addEventListener(type, function (event) { - if (self.getOption("disabled", undefined) === true) { - return; - } - - const path = event.composedPath(); - const element = path?.[0]; - if (element instanceof HTMLElement) { - const control = element.closest( - `[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`, - ); - if (control instanceof HTMLElement) { - if (control.classList.contains("clear")) { - clearSelection.call(self); - - fireCustomEvent(self, "monster-selection-cleared", {}); - } else { - const element = findTargetElementFromEvent( - event, - ATTRIBUTE_ROLE, - "remove-badge", - ); - if (element instanceof HTMLElement) { - return; - } - - toggle.call(self); - } - } - } - }); - - // badge, selection - self.addEventListener(type, self[clearOptionEventHandler]); - } - - self.addEventListener("monster-change", self[changeEventHandler]); - self.addEventListener("input", self[inputEventHandler]); - self.addEventListener("keydown", self[keyEventHandler]); - - return self; + const self = this; + + /** + * @param {Event} event + */ + self[clearOptionEventHandler] = (event) => { + const element = findTargetElementFromEvent( + event, + ATTRIBUTE_ROLE, + "remove-badge", + ); + + if (element instanceof HTMLElement) { + const badge = findClosestByAttribute(element, ATTRIBUTE_ROLE, "badge"); + if (badge instanceof HTMLElement) { + const value = badge.getAttribute(`${ATTRIBUTE_PREFIX}value`); + + let selection = self.getOption("selection"); + selection = selection.filter((b) => { + return value !== b.value; + }); + + setSelection + .call(self, selection) + .then(() => { + fireCustomEvent(self, "monster-selection-removed", { + value, + }); + }) + .catch((e) => { + addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + } + } + }; + + /** + * @param {Event} event + */ + self[closeEventHandler] = (event) => { + const path = event.composedPath(); + + for (const [, element] of Object.entries(path)) { + if (element === self) { + return; + } + } + hide.call(self); + }; + + /** + * @param {Event} event + */ + self[inputEventHandler] = (event) => { + const path = event.composedPath(); + const element = path?.[0]; + + if (element instanceof HTMLElement) { + if ( + element.hasAttribute(ATTRIBUTE_ROLE) && + element.getAttribute(ATTRIBUTE_ROLE) === "option-control" + ) { + fireCustomEvent(self, "monster-change", { + type: event.type, + value: element.value, + checked: element.checked, + }); + } else if ( + element.hasAttribute(ATTRIBUTE_ROLE) && + element.getAttribute(ATTRIBUTE_ROLE) === "filter" + ) { + } + } + }; + + /** + * @param {Event} event + */ + self[changeEventHandler] = (event) => { + gatherState.call(self); + fireCustomEvent(self, "monster-changed", event?.detail); + }; + + self[keyEventHandler] = (event) => { + const path = event.composedPath(); + const element = path.shift(); + + let role; + + if (element instanceof HTMLElement) { + if (element.hasAttribute(ATTRIBUTE_ROLE)) { + role = element.getAttribute(ATTRIBUTE_ROLE); + } else if (element === this) { + show.call(this); + // focusFilter.call(self); + } else { + const e = element.closest(`[${ATTRIBUTE_ROLE}]`); + if (e instanceof HTMLElement && e.hasAttribute(ATTRIBUTE_ROLE)) { + role = e.getAttribute(ATTRIBUTE_ROLE); + } + } + } else { + return; + } + + switch (role) { + case "filter": + handleFilterKeyboardEvents.call(self, event); + break; + case "option-label": + case "option-control": + case "option": + handleOptionKeyboardEvents.call(self, event); + break; + case "control": + case "toggle": + handleToggleKeyboardEvents.call(self, event); + break; + } + }; + + const types = self.getOption("toggleEventType", ["click"]); + + for (const [, type] of Object.entries(types)) { + self[controlElementSymbol] + .querySelector(`[${ATTRIBUTE_ROLE}="container"]`) + .addEventListener(type, function (event) { + const element = findTargetElementFromEvent( + event, + ATTRIBUTE_ROLE, + "remove-badge", + ); + if (element instanceof HTMLElement) { + return; + } + + toggle.call(self); + }); + + self[controlElementSymbol] + .querySelector(`[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`) + .addEventListener(type, function (event) { + if (self.getOption("disabled", undefined) === true) { + return; + } + + const path = event.composedPath(); + const element = path?.[0]; + if (element instanceof HTMLElement) { + const control = element.closest( + `[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`, + ); + if (control instanceof HTMLElement) { + if (control.classList.contains("clear")) { + clearSelection.call(self); + + fireCustomEvent(self, "monster-selection-cleared", {}); + } else { + const element = findTargetElementFromEvent( + event, + ATTRIBUTE_ROLE, + "remove-badge", + ); + if (element instanceof HTMLElement) { + return; + } + + toggle.call(self); + } + } + } + }); + + // badge, selection + self.addEventListener(type, self[clearOptionEventHandler]); + } + + self.addEventListener("monster-change", self[changeEventHandler]); + self.addEventListener("input", self[inputEventHandler]); + self.addEventListener("keydown", self[keyEventHandler]); + + return self; } /** @@ -2356,65 +2343,64 @@ function initEventHandler() { * @return {Select} */ function setStatusOrRemoveBadges(suggestion) { - setTimeout(() => { - - const selection = this.getOption("selection"); - - const clearAllFlag = - isArray(selection) && - selection.length > 0 && - this.getOption("features.clearAll") === true; - - const current = this.getOption("classes.statusOrRemoveBadge"); - - if (this[isLoadingSymbol] === true) { - if (current !== "loading") { - this.setOption("classes.statusOrRemoveBadge", "loading"); - } - return; - } - - if (suggestion === "loading") { - this[isLoadingSymbol] = true; - if (current !== "loading") { - this.setOption("classes.statusOrRemoveBadge", "loading"); - } - return; - } - - if (clearAllFlag) { - if (current !== "clear") { - this.setOption("classes.statusOrRemoveBadge", "clear"); - } - return; - } - - if (this[controlElementSymbol].classList.contains("open")) { - if (current !== "open") { - this.setOption("classes.statusOrRemoveBadge", "open"); - } - return; - } - - const options = this.getOption("options"); - if ( - options === undefined || - options === null || - (isArray(options) && options.length === 0) - ) { - if (current !== "empty") { - this.setOption("classes.statusOrRemoveBadge", "empty"); - } - return; - } - - if (suggestion) { - if (current !== suggestion) { - this.setOption("classes.statusOrRemoveBadge", suggestion); - } - return; - } - }, 2); + setTimeout(() => { + const selection = this.getOption("selection"); + + const clearAllFlag = + isArray(selection) && + selection.length > 0 && + this.getOption("features.clearAll") === true; + + const current = this.getOption("classes.statusOrRemoveBadge"); + + if (this[isLoadingSymbol] === true) { + if (current !== "loading") { + this.setOption("classes.statusOrRemoveBadge", "loading"); + } + return; + } + + if (suggestion === "loading") { + this[isLoadingSymbol] = true; + if (current !== "loading") { + this.setOption("classes.statusOrRemoveBadge", "loading"); + } + return; + } + + if (clearAllFlag) { + if (current !== "clear") { + this.setOption("classes.statusOrRemoveBadge", "clear"); + } + return; + } + + if (this[controlElementSymbol].classList.contains("open")) { + if (current !== "open") { + this.setOption("classes.statusOrRemoveBadge", "open"); + } + return; + } + + const options = this.getOption("options"); + if ( + options === undefined || + options === null || + (isArray(options) && options.length === 0) + ) { + if (current !== "empty") { + this.setOption("classes.statusOrRemoveBadge", "empty"); + } + return; + } + + if (suggestion) { + if (current !== suggestion) { + this.setOption("classes.statusOrRemoveBadge", suggestion); + } + return; + } + }, 2); } /** @@ -2423,68 +2409,68 @@ function setStatusOrRemoveBadges(suggestion) { * @throws {Error} no shadow-root is defined */ function initControlReferences() { - if (!this.shadowRoot) { - throw new Error("no shadow-root is defined"); - } - - this[controlElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=control]`, - ); - this[selectionElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=selection]`, - ); - this[containerElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=container]`, - ); - this[popperElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=popper]`, - ); - this[inlineFilterElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`, - ); - this[popperFilterElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=filter][name="popper-filter"]`, - ); - this[popperFilterContainerElementSymbol] = - this[popperFilterElementSymbol].parentElement; - this[optionsElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=options]`, - ); - this[noOptionsAvailableElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}="no-options"]`, - ); - this[statusOrRemoveBadgesElementSymbol] = this.shadowRoot.querySelector( - `[${ATTRIBUTE_ROLE}=status-or-remove-badges]`, - ); + if (!this.shadowRoot) { + throw new Error("no shadow-root is defined"); + } + + this[controlElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=control]`, + ); + this[selectionElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=selection]`, + ); + this[containerElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=container]`, + ); + this[popperElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=popper]`, + ); + this[inlineFilterElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`, + ); + this[popperFilterElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=filter][name="popper-filter"]`, + ); + this[popperFilterContainerElementSymbol] = + this[popperFilterElementSymbol].parentElement; + this[optionsElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=options]`, + ); + this[noOptionsAvailableElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}="no-options"]`, + ); + this[statusOrRemoveBadgesElementSymbol] = this.shadowRoot.querySelector( + `[${ATTRIBUTE_ROLE}=status-or-remove-badges]`, + ); } /** * @private */ function updatePopper() { - if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) { - return; - } - - if (this.getOption("disabled", false) === true) { - return; - } - - new Processing(() => { - calcAndSetOptionsDimension.call(this); - positionPopper.call( - this, - this[controlElementSymbol], - this[popperElementSymbol], - this.getOption("popper", {}), - ); - }) - .run() - .catch((e) => { - addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); - }); - - return this; + if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) { + return; + } + + if (this.getOption("disabled", false) === true) { + return; + } + + new Processing(() => { + calcAndSetOptionsDimension.call(this); + positionPopper.call( + this, + this[controlElementSymbol], + this[popperElementSymbol], + this.getOption("popper", {}), + ); + }) + .run() + .catch((e) => { + addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message); + }); + + return this; } /** @@ -2492,8 +2478,8 @@ function updatePopper() { * @return {string} */ function getTemplate() { - // language=HTML - return ` + // language=HTML + return ` <template id="options"> <div data-monster-role="option" tabindex="-1" data-monster-attributes=" diff --git a/source/components/form/stylesheet/select.mjs b/source/components/form/stylesheet/select.mjs index 9ba9a62f4..782933c23 100644 --- a/source/components/form/stylesheet/select.mjs +++ b/source/components/form/stylesheet/select.mjs @@ -10,10 +10,10 @@ * For more information about purchasing a commercial license, please contact schukai GmbH. */ -import {addAttributeToken} from "../../../dom/attributes.mjs"; -import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs"; +import { addAttributeToken } from "../../../dom/attributes.mjs"; +import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs"; -export {SelectStyleSheet} +export { SelectStyleSheet }; /** * @private @@ -22,10 +22,17 @@ export {SelectStyleSheet} const SelectStyleSheet = new CSSStyleSheet(); try { - SelectStyleSheet.insertRule(` + SelectStyleSheet.insertRule( + ` @layer select { .block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}.monster-border-primary-1,.monster-border-primary-2,.monster-border-primary-3,.monster-border-primary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-0{border-radius:0;border-style:none;border-width:0}.monster-border-primary-1{border-color:var(--monster-bg-color-primary-1)}.monster-border-primary-2{border-color:var(--monster-bg-color-primary-2)}.monster-border-primary-3{border-color:var(--monster-bg-color-primary-3)}.monster-border-primary-4{border-color:var(--monster-bg-color-primary-4)}.monster-border-secondary-1,.monster-border-secondary-2,.monster-border-secondary-3,.monster-border-secondary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-secondary-1{border-color:var(--monster-bg-color-secondary-1)}.monster-border-secondary-2{border-color:var(--monster-bg-color-secondary-2)}.monster-border-secondary-3{border-color:var(--monster-bg-color-secondary-3)}.monster-border-secondary-4{border-color:var(--monster-bg-color-secondary-4)}.monster-border-tertiary-1,.monster-border-tertiary-2,.monster-border-tertiary-3,.monster-border-tertiary-4{border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width)}.monster-border-tertiary-1{border-color:var(--monster-bg-color-tertiary-1)}.monster-border-tertiary-2{border-color:var(--monster-bg-color-tertiary-2)}.monster-border-tertiary-3{border-color:var(--monster-bg-color-tertiary-3)}.monster-border-tertiary-4{border-color:var(--monster-bg-color-tertiary-4)}[data-monster-role=control]{width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}.monster-badge-primary{padding:.25em .4em}.monster-badge-primary,.monster-badge-primary-pill{background-color:var(--monster-bg-color-primary-4);border-radius:.25rem;color:var(--monster-color-primary-4);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-primary-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-secondary{padding:.25em .4em}.monster-badge-secondary,.monster-badge-secondary-pill{background-color:var(--monster-bg-color-secondary-3);border-radius:.25rem;color:var(--monster-color-secondary-3);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-secondary-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-tertiary{padding:.25em .4em}.monster-badge-tertiary,.monster-badge-tertiary-pill{background-color:var(--monster-bg-color-tertiary-3);border-radius:.25rem;color:var(--monster-color-tertiary-3);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-tertiary-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-destructive{padding:.25em .4em}.monster-badge-destructive,.monster-badge-destructive-pill{background-color:var(--monster-bg-color-destructive-1);border-radius:.25rem;color:var(--monster-color-destructive-1);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-destructive-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-success{padding:.25em .4em}.monster-badge-success,.monster-badge-success-pill{background-color:var(--monster-bg-color-success-1);border-radius:.25rem;color:var(--monster-color-success-1);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-success-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-warning{padding:.25em .4em}.monster-badge-warning,.monster-badge-warning-pill{background-color:var(--monster-bg-color-warning-1);border-radius:.25rem;color:var(--monster-color-warning-1);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-warning-pill{border-radius:10rem;padding:.25em .6em}.monster-badge-error{padding:.25em .4em}.monster-badge-error,.monster-badge-error-pill{background-color:var(--monster-bg-color-error-1);border-radius:.25rem;color:var(--monster-color-error-1);display:inline-block;font-size:75%;font-weight:700;line-height:1;text-align:center;text-decoration:none;vertical-align:baseline;white-space:nowrap}.monster-badge-error-pill{border-radius:10rem;padding:.25em .6em}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}[data-monster-role=container]{-webkit-appearance:none;-moz-appearance:none;appearance:none;flex:4 0 90%;min-height:1.4em;overflow:auto;scrollbar-color:var(--monster-color-primary-1) var(--monster-color-primary-3);scrollbar-width:thin;width:100%}.d-none{display:none!important}div[data-monster-role=control]{display:flex;height:100%;position:relative}[data-monster-role=container].open{-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z'/%3E%3C/svg%3E\")}[data-monster-role=container].clear,[data-monster-role=container].open{background-color:var(--monster-bg-color-primary-2);-webkit-mask-position:center center;mask-position:center center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:.8em;mask-size:.8em}[data-monster-role=container].clear{-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\")}[data-monster-role=control]{accent-color:var(--monster-color-secondary-2);background-color:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-2);-o-border-image:initial;border-image:initial;border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-sizing:border-box;color:var(--monster-color-primary-1);display:flex;font-family:inherit;font-size:100%;margin:0;outline:none;padding:.4rem .6rem;width:-webkit-fill-available;width:-moz-available;width:fill-available}@media (prefers-color-scheme:light){[data-monster-role=control]{background-color:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-3);color:var(--monster-color-primary-1)}[data-monster-role=control]:focus{outline:1px dashed var(--monster-color-selection-4);outline-offset:2px}}[data-monster-role=control]:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}div[data-monster-role=selection]{align-items:center;display:flex;flex-direction:row;flex-wrap:wrap;gap:5px;justify-content:flex-start;margin:5px}[data-monster-role=option-control]{margin-right:8px}[data-monster-role=badge]{display:inline-flex}[data-monster-role=badge-label]{align-content:center;align-items:center;display:flex;flex-direction:row;gap:7px;justify-content:space-between}[data-monster-role=filter],[data-monster-role=popper-filter]{display:flex;flex-grow:200;order:99999999;visibility:hidden}[data-monster-role=filter].active{background-color:var(--monster-bg-color-primary-2);border:0;border-color:var(--monster-bg-color-primary-3);border-bottom:1px solid var(--monster-bg-color-primary-3);color:var(--monster-color-primary-2);min-width:40%;outline:none;visibility:visible}.active[data-monster-role=filter][name=popper-filter]{height:1.5em;margin:2.5em;padding:2px;width:calc(100% - var(--monster-border-width)*2)}.option-filter-control{align-items:center;background-color:var(--monster-bg-color-primary-2);display:flex;height:2.5em;margin:-1.1em -1.1em .3em}[data-monster-role=remove-badge]{background-color:var(--monster-bg-color-primary-2);height:16px;margin-left:5px;-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\");order:2}[data-monster-role=remove-badge],[data-monster-role=status-or-remove-badges]{-webkit-mask-position:center center;mask-position:center center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:.8em;mask-size:.8em;min-height:16px;width:16px}[data-monster-role=status-or-remove-badges]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--monster-bg-color-primary-4);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\")}.open[data-monster-role=status-or-remove-badges]{background-color:var(--monster-bg-color-primary-4);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z'/%3E%3C/svg%3E\")}.empty[data-monster-role=status-or-remove-badges]{background-color:var(--monster-bg-color-primary-4);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-dash-circle'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E%3Cpath d='M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-dash-circle'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E%3Cpath d='M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8'/%3E%3C/svg%3E\")}.clear[data-monster-role=status-or-remove-badges]{background-color:var(--monster-bg-color-primary-4);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E\")}.error[data-monster-role=status-or-remove-badges]{background-color:var(--monster-bg-color-error-1);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E%3Cpath d='M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E%3Cpath d='M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z'/%3E%3C/svg%3E\")}.loading[data-monster-role=status-or-remove-badges]{animation-duration:1s;animation-iteration-count:infinite;animation-name:activity;animation-timing-function:cubic-bezier(0,0,.2,1);background-color:var(--monster-bg-color-primary-4);-webkit-mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='activity'%3E%3Ccircle cx='8' cy='8' r='8'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='activity'%3E%3Ccircle cx='8' cy='8' r='8'/%3E%3C/svg%3E\")}@keyframes activity{0%{transform:scale(1)}50%{transform:scale(.1)}to{transform:scale(1)}}[data-monster-role=options]{box-sizing:border-box;display:flex;flex-direction:column;flex-grow:1;scrollbar-color:var(--monster-color-primary-1) var(--monster-color-primary-3);scrollbar-width:thin}[data-monster-role=option]{align-items:center;box-sizing:border-box;display:flex;padding:6px 5px}[data-monster-role=option] label{align-items:center;display:flex;flex-direction:row;justify-content:flex-start;width:100%}[data-monster-role=option] label>div{align-items:center;display:flex;flex-direction:row;justify-content:space-between;outline:none;width:100%}[data-monster-role=no-options]{background-color:var(--monster-bg-color-warning-4);color:var(--monster-color-warning-4);margin:1.1em 0 0 1.1em}.selected{background-color:var(--monster-bg-color-primary-2);color:var(--monster-color-primary-2)}[data-monster-role=option][data-monster-filtered=true],[data-monster-role=option][data-monster-visibility=hidden]{display:none}[data-monster-role=option][data-monster-focused=true]{outline:1px dashed var(--monster-color-selection-2);outline-offset:-2px}[data-monster-role=option]>input:focus,[data-monster-role=option]>label:focus{outline:none} -}`, 0); +}`, + 0, + ); } catch (e) { - addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + ""); + addAttributeToken( + document.getRootNode().querySelector("html"), + ATTRIBUTE_ERRORMESSAGE, + e + "", + ); } diff --git a/source/components/host/call-button.mjs b/source/components/host/call-button.mjs index 0be9dd426..00f7b6294 100644 --- a/source/components/host/call-button.mjs +++ b/source/components/host/call-button.mjs @@ -20,7 +20,10 @@ import { } from "../../dom/customelement.mjs"; import { CallButtonStyleSheet } from "./stylesheet/call-button.mjs"; import { isArray, isObject, isFunction } from "../../types/is.mjs"; -import {findElementWithSelectorUpwards, getDocument} from "../../dom/util.mjs"; +import { + findElementWithSelectorUpwards, + getDocument, +} from "../../dom/util.mjs"; import { ATTRIBUTE_PREFIX } from "../../dom/constants.mjs"; export { CallButton }; @@ -200,7 +203,6 @@ function initOptionsFromArguments() { * @throws {Error} The option references.callableSelector must be an array */ function initEventHandler() { - this[callButtonElementSymbol].addEventListener("click", (event) => { event.preventDefault(); @@ -217,7 +219,7 @@ function initEventHandler() { } for (const selector of selectors) { - const element = findElementWithSelectorUpwards( this,selector); + const element = findElementWithSelectorUpwards(this, selector); if (element instanceof HTMLElement && isFunction(element?.[call])) { element[call](); } diff --git a/source/components/layout/stylesheet/collapse.mjs b/source/components/layout/stylesheet/collapse.mjs index a6f04109d..8ac62b822 100644 --- a/source/components/layout/stylesheet/collapse.mjs +++ b/source/components/layout/stylesheet/collapse.mjs @@ -1,5 +1,5 @@ /** - * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved. + * Copyright © schukai GmbH and all contributing authors, 2024. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). @@ -8,8 +8,6 @@ * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact schukai GmbH. - * - * SPDX-License-Identifier: AGPL-3.0 */ import { addAttributeToken } from "../../../dom/attributes.mjs"; @@ -27,7 +25,7 @@ try { CollapseStyleSheet.insertRule( ` @layer collapse { -:where(html){line-height:1.15;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}:where(h1){font-size:2em;margin-block-end:.67em;margin-block-start:.67em}:where(dl,ol,ul) :where(dl,ol,ul){margin-block-end:0;margin-block-start:0}:where(hr){box-sizing:content-box;color:inherit;height:0}:where(abbr[title]){text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}:where(b,strong){font-weight:bolder}:where(code,kbd,pre,samp){font-family:monospace,monospace;font-size:1em}:where(small){font-size:80%}:where(table){border-color:currentColor;text-indent:0}:where(button,input,select){margin:0}:where(button){text-transform:none}:where(button,input:is([type=button i],[type=reset i],[type=submit i])){-webkit-appearance:button}:where(progress){vertical-align:baseline}:where(select){text-transform:none}:where(textarea){margin:0}:where(input[type=search i]){-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focus-inner{border-style:none;padding:0}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focusring{outline:1px dotted ButtonText}:where(:-moz-ui-invalid){box-shadow:none}:where(dialog){background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:fit-content}:where(dialog:not([open])){display:none}:where(summary){display:list-item}html{height:100%}body,html{min-height:calc(100vh - 40px)}body{box-sizing:border-box;margin:0;padding:0;word-break:break-word}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}.monster-button-primary,button{align-items:center;background-color:var(--monster-bg-color-primary-1);background-position:50%;border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);color:var(--monster-color-primary-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-primary{background-color:var(--monster-bg-color-primary-4);border-color:var(--monster-bg-color-primary-4);color:var(--monster-color-primary-4)}.monster-button-secondary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-bg-color-secondary-4);border-color:var(--monster-bg-color-secondary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-color-secondary-4)}.monster-button-secondary,.monster-button-tertiary{align-items:center;background-position:50%;box-shadow:var(--monster-box-shadow-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-tertiary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-bg-color-tertiary-4);border-color:var(--monster-bg-color-tertiary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-color-tertiary-4)}.monster-button-outline-primary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-primary-4);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-bg-color-primary-4)}.monster-button-outline-primary,.monster-button-outline-secondary{align-items:center;background-position:50%;box-shadow:var(--monster-box-shadow-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-outline-secondary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-secondary-4);border-color:var(--monster-bg-color-secondary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-bg-color-secondary-4)}.monster-button-outline-tertiary{align-items:center;background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-tertiary-4);background-position:50%;border-color:var(--monster-bg-color-tertiary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);color:var(--monster-color-primary-1);color:var(--monster-bg-color-tertiary-4);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}button:active,button:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}button:active{z-index:var(--monster-z-index-outline)}.monster-button-bar,.monster-button-group{align-content:center;align-items:stretch;display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-between}.monster-button-group{box-sizing:border-box;gap:0;margin:1rem 0}.monster-button-group>:not(:last-child){margin-right:calc(var(--monster-border-width)*-1)}.monster-button-group :hover{box-shadow:none}button:focus{outline:1px dashed var(--monster-color-selection-4);outline-offset:2px;z-index:var(--monster-z-index-outline)}@media (prefers-color-scheme:light){button:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:2px;z-index:var(--monster-z-index-outline)}}[data-monster-role=control]{outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:after,:before,:root{--monster-font-family:-apple-system,BlinkMacSystemFont,\"Quicksand\",\"Segoe UI\",\"Roboto\",\"Oxygen\",\"Ubuntu\",\"Cantarell\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";--monster-color-primary-1:var(--monster-color-cinnamon-6);--monster-color-primary-2:var(--monster-color-cinnamon-6);--monster-color-primary-3:var(--monster-color-cinnamon-1);--monster-color-primary-4:var(--monster-color-cinnamon-1);--monster-bg-color-primary-1:var(--monster-color-cinnamon-1);--monster-bg-color-primary-2:var(--monster-color-cinnamon-2);--monster-bg-color-primary-3:var(--monster-color-cinnamon-3);--monster-bg-color-primary-4:var(--monster-color-cinnamon-6);--monster-color-secondary-1:var(--monster-color-red-4);--monster-color-secondary-2:var(--monster-color-red-4);--monster-color-secondary-3:var(--monster-color-red-1);--monster-color-secondary-4:var(--monster-color-red-1);--monster-bg-color-secondary-1:var(--monster-color-gray-1);--monster-bg-color-secondary-2:var(--monster-color-red-2);--monster-bg-color-secondary-3:var(--monster-color-red-3);--monster-bg-color-secondary-4:var(--monster-color-red-6);--monster-color-tertiary-1:var(--monster-color-magenta-4);--monster-color-tertiary-2:var(--monster-color-magenta-4);--monster-color-tertiary-3:var(--monster-color-magenta-6);--monster-color-tertiary-4:var(--monster-color-magenta-1);--monster-bg-color-tertiary-1:var(--monster-color-gray-1);--monster-bg-color-tertiary-2:var(--monster-color-magenta-1);--monster-bg-color-tertiary-3:var(--monster-color-magenta-2);--monster-bg-color-tertiary-4:var(--monster-color-magenta-6);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-4);--monster-color-destructive-3:var(--monster-color-red-6);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-4);--monster-bg-color-destructive-2:var(--monster-color-gray-1);--monster-bg-color-destructive-3:var(--monster-color-red-2);--monster-bg-color-destructive-4:var(--monster-color-red-5);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-4);--monster-color-success-3:var(--monster-color-green-6);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-3);--monster-bg-color-success-2:var(--monster-color-gray-1);--monster-bg-color-success-3:var(--monster-color-green-2);--monster-bg-color-success-4:var(--monster-color-green-5);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-4);--monster-color-warning-3:var(--monster-color-orange-6);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-3);--monster-bg-color-warning-2:var(--monster-color-gray-1);--monster-bg-color-warning-3:var(--monster-color-orange-2);--monster-bg-color-warning-4:var(--monster-color-orange-5);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-4);--monster-color-error-3:var(--monster-color-red-6);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-4);--monster-bg-color-error-2:var(--monster-color-gray-1);--monster-bg-color-error-3:var(--monster-color-red-2);--monster-bg-color-error-4:var(--monster-color-red-5);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-4);--monster-color-primary-disabled-4:var(--monster-color-gray-4);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-1);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-6);--monster-color-gradient-1:#833ab4;--monster-color-gradient-2:#fd1d1d;--monster-color-gradient-3:#fcb045;--monster-box-shadow-1:none;--monster-box-shadow-2:-1px 1px 10px 1px hsla(0,0%,76%,.61);--monster-text-shadow:none;--monster-theme-control-bg-color:var(--monster-gradient-tangerine-1);--monster-theme-control-color:var(--monster-gradient-tangerine-6);--monster-theme-control-border-color:var(--monster-gradient-tangerine-2);--monster-theme-control-hover-color:var(--monster-gradient-tangerine-6);--monster-theme-control-hover-bg-color:var(--monster-gradient-tangerine-2);--monster-theme-on-color:var(--monster-color-green-1);--monster-theme-on-bg-color:var(--monster-color-green-5);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-4);--monster-border-style:solid;--monster-border-width:2px;--monster-border-radius:0;--monster-popper-witharrrow-distance:-4px;--monster-z-index-default:0;--monster-z-index-outline:10;--monster-z-index-dropdown:200;--monster-z-index-dropdown-overlay:210;--monster-z-index-sticky:300;--monster-z-index-sticky-overlay:310;--monster-z-index-fixed:400;--monster-z-index-fixed-overlay:410;--monster-z-index-modal-backdrop:500;--monster-z-index-modal-backdrop-overlay:510;--monster-z-index-offcanvas:600;--monster-z-index-offcanvas-overlay:610;--monster-z-index-modal:700;--monster-z-index-modal-overlay:710;--monster-z-index-popover:800;--monster-z-index-popover-overlay:810;--monster-z-index-tooltip:800;--monster-z-index-tooltip-overlay:910;--monster-space-0:0;--monster-space-1:2px;--monster-space-2:4px;--monster-space-3:6px;--monster-space-4:10px;--monster-space-5:16px;--monster-space-6:26px;--monster-space-7:42px;--monster-breakpoint-0:480px;--monster-breakpoint-4:480px;--monster-breakpoint-7:768px;--monster-breakpoint-9:992px;--monster-breakpoint-12:1200px;--monster-dragger-width:1px;--monster-dragger-handle-width:4px;--monster-dragger-handle-height:50px}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-1:var(--monster-color-gray-1);--monster-color-primary-2:var(--monster-color-gray-1);--monster-color-primary-3:var(--monster-color-gray-6);--monster-color-primary-4:var(--monster-color-gray-6);--monster-bg-color-primary-1:var(--monster-color-gray-6);--monster-bg-color-primary-2:var(--monster-color-gray-3);--monster-bg-color-primary-3:var(--monster-color-gray-2);--monster-bg-color-primary-4:var(--monster-color-gray-1);--monster-color-secondary-1:var(--monster-color-red-1);--monster-color-secondary-2:var(--monster-color-red-1);--monster-color-secondary-3:var(--monster-color-red-6);--monster-color-secondary-4:var(--monster-color-red-4);--monster-bg-color-secondary-1:var(--monster-color-gray-6);--monster-bg-color-secondary-2:var(--monster-color-red-3);--monster-bg-color-secondary-3:var(--monster-color-red-2);--monster-bg-color-secondary-4:var(--monster-color-red-1);--monster-color-tertiary-1:var(--monster-color-magenta-1);--monster-color-tertiary-2:var(--monster-color-magenta-6);--monster-color-tertiary-3:var(--monster-color-magenta-4);--monster-color-tertiary-4:var(--monster-color-magenta-4);--monster-bg-color-tertiary-1:var(--monster-color-gray-6);--monster-bg-color-tertiary-2:var(--monster-color-magenta-2);--monster-bg-color-tertiary-3:var(--monster-color-magenta-1);--monster-bg-color-tertiary-4:var(--monster-color-magenta-1);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-3);--monster-color-destructive-3:var(--monster-color-red-4);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-5);--monster-bg-color-destructive-2:var(--monster-color-gray-6);--monster-bg-color-destructive-3:var(--monster-color-red-1);--monster-bg-color-destructive-4:var(--monster-color-red-4);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-2);--monster-color-success-3:var(--monster-color-green-4);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-5);--monster-bg-color-success-2:var(--monster-color-gray-6);--monster-bg-color-success-3:var(--monster-color-green-1);--monster-bg-color-success-4:var(--monster-color-green-3);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-3);--monster-color-warning-3:var(--monster-color-orange-4);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-5);--monster-bg-color-warning-2:var(--monster-color-gray-6);--monster-bg-color-warning-3:var(--monster-color-orange-1);--monster-bg-color-warning-4:var(--monster-color-orange-3);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-3);--monster-color-error-3:var(--monster-color-red-4);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-5);--monster-bg-color-error-2:var(--monster-color-gray-6);--monster-bg-color-error-3:var(--monster-color-red-1);--monster-bg-color-error-4:var(--monster-color-red-4);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-3);--monster-color-primary-disabled-4:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-6);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-1);--monster-theme-control-bg-color:var(--monster-color-gray-5);--monster-theme-control-color:var(--monster-color-gray-1);--monster-theme-control-border-color:var(--monster-color-gray-3);--monster-theme-control-hover-color:var(--monster-color-gray-1);--monster-theme-control-hover-bg-color:var(--monster-color-gray-6);--monster-theme-on-color:var(--monster-color-gray-6);--monster-theme-on-bg-color:var(--monster-color-gray-1);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-5)}}span.monster-fx-ripple{animation:monster-fx-ripple .6s linear;background-color:hsla(0,0%,100%,.7);border-radius:50%;position:absolute;transform:scale(0)}@keyframes monster-fx-ripple{to{opacity:0;transform:scale(4)}}[data-monster-role=control]{font-size:1rem;font-weight:400;line-height:1.6;text-align:justify}.overflow-hidden[data-monster-role=control]{overflow:hidden}[data-monster-role=control] button{border-left:0;border-right:0;border-top:0}[data-monster-role=control] .button:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}[data-monster-role=control] [data-monster-role=detail]{box-sizing:border-box;font-size:1rem;font-weight:400;height:0;line-height:1.6;text-align:justify;transition:height .4s ease-in-out;width:100%}[data-monster-role=control] [data-monster-role=detail] .padding{padding:1rem}[data-monster-role=control] [data-monster-role=detail] .deco-line{background:linear-gradient(to right,var(--monster-color-gradient-1) 0,var(--monster-color-gradient-2) 50%,var(--monster-color-gradient-3) 100%);border:0;height:2px;margin:0;padding:0;transition:background .4s ease-in-out}@media (prefers-color-scheme:dark){[data-monster-role=control] [data-monster-role=detail] .deco-line{background:var(--monster-color-primary-1)}}[data-monster-role=control] .active[data-monster-role=detail]{height:var(--monster-height);transition:height .4s ease-in-out} +:where(html){line-height:1.15;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}:where(h1){font-size:2em;margin-block-end:.67em;margin-block-start:.67em}:where(dl,ol,ul) :where(dl,ol,ul){margin-block-end:0;margin-block-start:0}:where(hr){box-sizing:content-box;color:inherit;height:0}:where(abbr[title]){text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}:where(b,strong){font-weight:bolder}:where(code,kbd,pre,samp){font-family:monospace,monospace;font-size:1em}:where(small){font-size:80%}:where(table){border-color:currentColor;text-indent:0}:where(button,input,select){margin:0}:where(button){text-transform:none}:where(button,input:is([type=button i],[type=reset i],[type=submit i])){-webkit-appearance:button}:where(progress){vertical-align:baseline}:where(select){text-transform:none}:where(textarea){margin:0}:where(input[type=search i]){-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focus-inner{border-style:none;padding:0}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focusring{outline:1px dotted ButtonText}:where(:-moz-ui-invalid){box-shadow:none}:where(dialog){background-color:#fff;border:solid;color:#000;height:-moz-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:fit-content}:where(dialog:not([open])){display:none}:where(summary){display:list-item}html{height:100%}body,html{min-height:calc(100vh - 40px)}body{box-sizing:border-box;margin:0;padding:0;word-break:break-word}.block{display:block}.inline{display:inline}.inline-block{display:inline-block}.grid{display:grid}.inline-grid{display:inline-grid}.flex{display:flex}.inline-flex{display:inline-flex}.hidden,.hide,.none{display:none}.visible{visibility:visible}.invisible{visibility:hidden}.monster-button-primary,button{align-items:center;background-color:var(--monster-bg-color-primary-1);background-position:50%;border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);color:var(--monster-color-primary-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-primary{background-color:var(--monster-bg-color-primary-4);border-color:var(--monster-bg-color-primary-4);color:var(--monster-color-primary-4)}.monster-button-secondary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-bg-color-secondary-4);border-color:var(--monster-bg-color-secondary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-color-secondary-4)}.monster-button-secondary,.monster-button-tertiary{align-items:center;background-position:50%;box-shadow:var(--monster-box-shadow-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-tertiary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-bg-color-tertiary-4);border-color:var(--monster-bg-color-tertiary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-color-tertiary-4)}.monster-button-outline-primary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-primary-4);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-bg-color-primary-4)}.monster-button-outline-primary,.monster-button-outline-secondary{align-items:center;background-position:50%;box-shadow:var(--monster-box-shadow-1);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}.monster-button-outline-secondary{background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-secondary-4);border-color:var(--monster-bg-color-secondary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);color:var(--monster-color-primary-1);color:var(--monster-bg-color-secondary-4)}.monster-button-outline-tertiary{align-items:center;background-color:var(--monster-bg-color-primary-1);background-color:var(--monster-color-tertiary-4);background-position:50%;border-color:var(--monster-bg-color-tertiary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);color:var(--monster-color-primary-1);color:var(--monster-bg-color-tertiary-4);cursor:pointer;display:flex;font-family:var(--monster-font-family);font-size:1rem;font-weight:400;gap:.4rem;justify-content:center;line-height:1.5;outline:none;overflow:hidden;padding:.375rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:-webkit-fill-available;width:-moz-available;width:stretch}button:active,button:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}button:active{z-index:var(--monster-z-index-outline)}.monster-button-bar,.monster-button-group{align-content:center;align-items:stretch;display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-between}.monster-button-group{box-sizing:border-box;gap:0;margin:1rem 0}.monster-button-group>:not(:last-child){margin-right:calc(var(--monster-border-width)*-1)}.monster-button-group :hover{box-shadow:none}button:focus{outline:1px dashed var(--monster-color-selection-4);outline-offset:2px;z-index:var(--monster-z-index-outline)}@media (prefers-color-scheme:light){button:focus{outline:1px dashed var(--monster-color-selection-3);outline-offset:2px;z-index:var(--monster-z-index-outline)}}[data-monster-role=control]{outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:after,:before,:root{--monster-font-family:-apple-system,BlinkMacSystemFont,\"Quicksand\",\"Segoe UI\",\"Roboto\",\"Oxygen\",\"Ubuntu\",\"Cantarell\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";--monster-color-primary-1:var(--monster-color-gray-6);--monster-color-primary-2:var(--monster-color-gray-6);--monster-color-primary-3:var(--monster-color-cinnamon-1);--monster-color-primary-4:var(--monster-color-cinnamon-1);--monster-bg-color-primary-1:var(--monster-color-gray-1);--monster-bg-color-primary-2:var(--monster-color-gray-2);--monster-bg-color-primary-3:var(--monster-color-gray-6);--monster-bg-color-primary-4:var(--monster-color-gray-4);--monster-color-secondary-1:var(--monster-color-red-4);--monster-color-secondary-2:var(--monster-color-red-4);--monster-color-secondary-3:var(--monster-color-red-1);--monster-color-secondary-4:var(--monster-color-red-1);--monster-bg-color-secondary-1:var(--monster-color-gray-1);--monster-bg-color-secondary-2:var(--monster-color-red-2);--monster-bg-color-secondary-3:var(--monster-color-red-3);--monster-bg-color-secondary-4:var(--monster-color-red-6);--monster-color-tertiary-1:var(--monster-color-magenta-4);--monster-color-tertiary-2:var(--monster-color-magenta-4);--monster-color-tertiary-3:var(--monster-color-magenta-6);--monster-color-tertiary-4:var(--monster-color-magenta-1);--monster-bg-color-tertiary-1:var(--monster-color-gray-1);--monster-bg-color-tertiary-2:var(--monster-color-magenta-1);--monster-bg-color-tertiary-3:var(--monster-color-magenta-2);--monster-bg-color-tertiary-4:var(--monster-color-magenta-6);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-4);--monster-color-destructive-3:var(--monster-color-red-6);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-4);--monster-bg-color-destructive-2:var(--monster-color-gray-1);--monster-bg-color-destructive-3:var(--monster-color-red-2);--monster-bg-color-destructive-4:var(--monster-color-red-5);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-4);--monster-color-success-3:var(--monster-color-green-6);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-3);--monster-bg-color-success-2:var(--monster-color-gray-1);--monster-bg-color-success-3:var(--monster-color-green-2);--monster-bg-color-success-4:var(--monster-color-green-5);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-4);--monster-color-warning-3:var(--monster-color-orange-6);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-3);--monster-bg-color-warning-2:var(--monster-color-gray-1);--monster-bg-color-warning-3:var(--monster-color-orange-2);--monster-bg-color-warning-4:var(--monster-color-orange-5);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-4);--monster-color-error-3:var(--monster-color-red-6);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-4);--monster-bg-color-error-2:var(--monster-color-gray-1);--monster-bg-color-error-3:var(--monster-color-red-2);--monster-bg-color-error-4:var(--monster-color-red-5);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-4);--monster-color-primary-disabled-4:var(--monster-color-gray-4);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-1);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-6);--monster-color-gradient-1:#833ab4;--monster-color-gradient-2:#fd1d1d;--monster-color-gradient-3:#fcb045;--monster-box-shadow-1:none;--monster-box-shadow-2:-1px 1px 10px 1px hsla(0,0%,76%,.61);--monster-text-shadow:none;--monster-theme-control-bg-color:var(--monster-gradient-tangerine-1);--monster-theme-control-color:var(--monster-gradient-tangerine-6);--monster-theme-control-border-color:var(--monster-gradient-tangerine-2);--monster-theme-control-hover-color:var(--monster-gradient-tangerine-6);--monster-theme-control-hover-bg-color:var(--monster-gradient-tangerine-2);--monster-theme-on-color:var(--monster-color-green-1);--monster-theme-on-bg-color:var(--monster-color-green-5);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-4);--monster-border-style:solid;--monster-border-width:3px;--monster-border-radius:0;--monster-popper-witharrrow-distance:-4px;--monster-z-index-default:0;--monster-z-index-outline:10;--monster-z-index-dropdown:200;--monster-z-index-dropdown-overlay:210;--monster-z-index-sticky:300;--monster-z-index-sticky-overlay:310;--monster-z-index-fixed:400;--monster-z-index-fixed-overlay:410;--monster-z-index-modal-backdrop:500;--monster-z-index-modal-backdrop-overlay:510;--monster-z-index-offcanvas:600;--monster-z-index-offcanvas-overlay:610;--monster-z-index-modal:700;--monster-z-index-modal-overlay:710;--monster-z-index-popover:800;--monster-z-index-popover-overlay:810;--monster-z-index-tooltip:800;--monster-z-index-tooltip-overlay:910;--monster-space-0:0;--monster-space-1:2px;--monster-space-2:4px;--monster-space-3:6px;--monster-space-4:10px;--monster-space-5:16px;--monster-space-6:26px;--monster-space-7:42px;--monster-breakpoint-0:480px;--monster-breakpoint-4:480px;--monster-breakpoint-7:768px;--monster-breakpoint-9:992px;--monster-breakpoint-12:1200px;--monster-dragger-width:2px;--monster-dragger-handle-width:4px;--monster-dragger-handle-height:50px}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-1:var(--monster-color-gray-1);--monster-color-primary-2:var(--monster-color-gray-1);--monster-color-primary-3:var(--monster-color-gray-6);--monster-color-primary-4:var(--monster-color-gray-6);--monster-bg-color-primary-1:var(--monster-color-gray-6);--monster-bg-color-primary-2:var(--monster-color-gray-3);--monster-bg-color-primary-3:var(--monster-color-gray-2);--monster-bg-color-primary-4:var(--monster-color-gray-1);--monster-color-secondary-1:var(--monster-color-red-1);--monster-color-secondary-2:var(--monster-color-red-1);--monster-color-secondary-3:var(--monster-color-red-6);--monster-color-secondary-4:var(--monster-color-red-4);--monster-bg-color-secondary-1:var(--monster-color-gray-6);--monster-bg-color-secondary-2:var(--monster-color-red-3);--monster-bg-color-secondary-3:var(--monster-color-red-2);--monster-bg-color-secondary-4:var(--monster-color-red-1);--monster-color-tertiary-1:var(--monster-color-magenta-1);--monster-color-tertiary-2:var(--monster-color-magenta-6);--monster-color-tertiary-3:var(--monster-color-magenta-4);--monster-color-tertiary-4:var(--monster-color-magenta-4);--monster-bg-color-tertiary-1:var(--monster-color-gray-6);--monster-bg-color-tertiary-2:var(--monster-color-magenta-2);--monster-bg-color-tertiary-3:var(--monster-color-magenta-1);--monster-bg-color-tertiary-4:var(--monster-color-magenta-1);--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-3);--monster-color-destructive-3:var(--monster-color-red-4);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-5);--monster-bg-color-destructive-2:var(--monster-color-gray-6);--monster-bg-color-destructive-3:var(--monster-color-red-1);--monster-bg-color-destructive-4:var(--monster-color-red-4);--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-2);--monster-color-success-3:var(--monster-color-green-4);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-5);--monster-bg-color-success-2:var(--monster-color-gray-6);--monster-bg-color-success-3:var(--monster-color-green-1);--monster-bg-color-success-4:var(--monster-color-green-3);--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-3);--monster-color-warning-3:var(--monster-color-orange-4);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-5);--monster-bg-color-warning-2:var(--monster-color-gray-6);--monster-bg-color-warning-3:var(--monster-color-orange-1);--monster-bg-color-warning-4:var(--monster-color-orange-3);--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-3);--monster-color-error-3:var(--monster-color-red-4);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-5);--monster-bg-color-error-2:var(--monster-color-gray-6);--monster-bg-color-error-3:var(--monster-color-red-1);--monster-bg-color-error-4:var(--monster-color-red-4);--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6);--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-3);--monster-color-primary-disabled-4:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-6);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-1);--monster-theme-control-bg-color:var(--monster-color-gray-5);--monster-theme-control-color:var(--monster-color-gray-1);--monster-theme-control-border-color:var(--monster-color-gray-3);--monster-theme-control-hover-color:var(--monster-color-gray-1);--monster-theme-control-hover-bg-color:var(--monster-color-gray-6);--monster-theme-on-color:var(--monster-color-gray-6);--monster-theme-on-bg-color:var(--monster-color-gray-1);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-5)}}span.monster-fx-ripple{animation:monster-fx-ripple .6s linear;background-color:hsla(0,0%,100%,.7);border-radius:50%;position:absolute;transform:scale(0)}@keyframes monster-fx-ripple{to{opacity:0;transform:scale(4)}}[data-monster-role=control]{font-size:1rem;font-weight:400;line-height:1.6;text-align:justify}.overflow-hidden[data-monster-role=control]{overflow:hidden}[data-monster-role=control] button{border-left:0;border-right:0;border-top:0}[data-monster-role=control] .button:hover{box-shadow:var(--monster-box-shadow-2);transition:background .8s,color .25s .0833333333s}[data-monster-role=control] [data-monster-role=detail]{box-sizing:border-box;font-size:1rem;font-weight:400;height:0;line-height:1.6;text-align:justify;transition:height .4s ease-in-out;width:100%}[data-monster-role=control] [data-monster-role=detail] .padding{padding:1rem}[data-monster-role=control] [data-monster-role=detail] .deco-line{background:linear-gradient(to right,var(--monster-color-gradient-1) 0,var(--monster-color-gradient-2) 50%,var(--monster-color-gradient-3) 100%);border:0;height:2px;margin:0;padding:0;transition:background .4s ease-in-out}@media (prefers-color-scheme:dark){[data-monster-role=control] [data-monster-role=detail] .deco-line{background:var(--monster-color-primary-1)}}[data-monster-role=control] .active[data-monster-role=detail]{height:var(--monster-height);transition:height .4s ease-in-out} }`, 0, ); diff --git a/source/components/notify/message.mjs b/source/components/notify/message.mjs index 60e744b77..fd008ab31 100644 --- a/source/components/notify/message.mjs +++ b/source/components/notify/message.mjs @@ -218,9 +218,12 @@ class Message extends CustomElement { */ function startFadeout() { if (!this?.[timerSymbol]) { - this[timerSymbol] = setTimeout(() => { - removeSelf.call(this); - }, this.getOption("timeout", 1000)); + this[timerSymbol] = setTimeout( + () => { + removeSelf.call(this); + }, + this.getOption("timeout", 1000), + ); } } diff --git a/source/components/style/mixin/property.pcss b/source/components/style/mixin/property.pcss index b03b91f1a..4b9c6ae05 100644 --- a/source/components/style/mixin/property.pcss +++ b/source/components/style/mixin/property.pcss @@ -57,7 +57,7 @@ @define-mixin defaultBorderProperty { --monster-border-style: solid; - --monster-border-width: 2px; + --monster-border-width: 3px; --monster-border-radius: 0; } @@ -73,7 +73,7 @@ @define-mixin defaultDragAndDropProperty { - --monster-dragger-width: 1px; + --monster-dragger-width: 2px; --monster-dragger-handle-width: 4px; --monster-dragger-handle-height: 50px; } diff --git a/source/components/stylesheet/link.mjs b/source/components/stylesheet/link.mjs index 09a82633b..f249f9f95 100644 --- a/source/components/stylesheet/link.mjs +++ b/source/components/stylesheet/link.mjs @@ -1,5 +1,5 @@ /** - * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved. + * Copyright © schukai GmbH and all contributing authors, 2024. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). @@ -8,8 +8,6 @@ * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact schukai GmbH. - * - * SPDX-License-Identifier: AGPL-3.0 */ import { addAttributeToken } from "../../dom/attributes.mjs"; diff --git a/source/components/stylesheet/mixin/property.mjs b/source/components/stylesheet/mixin/property.mjs index 53819b862..c5451135c 100644 --- a/source/components/stylesheet/mixin/property.mjs +++ b/source/components/stylesheet/mixin/property.mjs @@ -10,10 +10,10 @@ * For more information about purchasing a commercial license, please contact schukai GmbH. */ -import {addAttributeToken} from "../../../dom/attributes.mjs"; -import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs"; +import { addAttributeToken } from "../../../dom/attributes.mjs"; +import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs"; -export {PropertyStyleSheet} +export { PropertyStyleSheet }; /** * @private @@ -22,10 +22,17 @@ export {PropertyStyleSheet} const PropertyStyleSheet = new CSSStyleSheet(); try { - PropertyStyleSheet.insertRule(` + PropertyStyleSheet.insertRule( + ` @layer property { -}`, 0); +}`, + 0, + ); } catch (e) { - addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + ""); + addAttributeToken( + document.getRootNode().querySelector("html"), + ATTRIBUTE_ERRORMESSAGE, + e + "", + ); } diff --git a/source/data/datasource/dom.mjs b/source/data/datasource/dom.mjs index bf7d4a607..262c03a13 100644 --- a/source/data/datasource/dom.mjs +++ b/source/data/datasource/dom.mjs @@ -12,12 +12,12 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {instanceSymbol} from "../../constants.mjs"; -import {findElementWithSelectorUpwards} from "../../dom/util.mjs"; -import {isObject} from "../../types/is.mjs"; -import {Datasource} from "../datasource.mjs"; +import { instanceSymbol } from "../../constants.mjs"; +import { findElementWithSelectorUpwards } from "../../dom/util.mjs"; +import { isObject } from "../../types/is.mjs"; +import { Datasource } from "../datasource.mjs"; -export {DomStorage}; +export { DomStorage }; /** * The DomStorage is a class that stores data in memory. @@ -27,93 +27,93 @@ export {DomStorage}; * @memberOf Monster.Data.Datasource */ class DomStorage extends Datasource { - /** - * @param {Object} [options] options contains definitions for the datasource. - */ - constructor(options) { - super(); + /** + * @param {Object} [options] options contains definitions for the datasource. + */ + constructor(options) { + super(); - if (isObject(options)) { - this.setOptions(options); - } - } + if (isObject(options)) { + this.setOptions(options); + } + } - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/data/datasource/storage/dom-storage"); - } + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/data/datasource/storage/dom-storage"); + } - /** - * @property {Object} defaults - * @property {Object} defaults.read - * @property {string} defaults.read.selector - * @property {Object} defaults.write - * @property {string} defaults.write.selector - */ - get defaults() { - return Object.assign({}, super.defaults, { - read: { - selector: undefined, - }, - write: { - selector: undefined, - }, - }); - } + /** + * @property {Object} defaults + * @property {Object} defaults.read + * @property {string} defaults.read.selector + * @property {Object} defaults.write + * @property {string} defaults.write.selector + */ + get defaults() { + return Object.assign({}, super.defaults, { + read: { + selector: undefined, + }, + write: { + selector: undefined, + }, + }); + } - /** - * @return {Promise} - * @throws {Error} The read selector is not defined - * @throws {Error} There are no storage element - */ - read() { - const selector = this.getOption("read.selector", undefined); - if (!selector) { - throw new Error("The read selector is not defined"); - } + /** + * @return {Promise} + * @throws {Error} The read selector is not defined + * @throws {Error} There are no storage element + */ + read() { + const selector = this.getOption("read.selector", undefined); + if (!selector) { + throw new Error("The read selector is not defined"); + } - const storage = findElementWithSelectorUpwards(this, selector); - if (!storage) { - throw new Error("There is no storage element"); - } + const storage = findElementWithSelectorUpwards(this, selector); + if (!storage) { + throw new Error("There is no storage element"); + } - return new Promise((resolve, reject) => { - try { - const data = JSON.parse(storage.innerHTML); - this.set(data); - resolve(data); - } catch (e) { - reject(e); - } - }); - } + return new Promise((resolve, reject) => { + try { + const data = JSON.parse(storage.innerHTML); + this.set(data); + resolve(data); + } catch (e) { + reject(e); + } + }); + } - /** - * @return {Promise} - * @throws {Error} The write selector is not defined - * @throws {Error} There are no storage element - */ - write() { - const selector = this.getOption("write.selector"); - if (!selector) { - throw new Error("The option write.selector is not defined"); - } + /** + * @return {Promise} + * @throws {Error} The write selector is not defined + * @throws {Error} There are no storage element + */ + write() { + const selector = this.getOption("write.selector"); + if (!selector) { + throw new Error("The option write.selector is not defined"); + } - const storage = findElementWithSelectorUpwards(this, selector); - if (!storage) { - throw new Error("There is no storage element"); - } + const storage = findElementWithSelectorUpwards(this, selector); + if (!storage) { + throw new Error("There is no storage element"); + } - return new Promise((resolve, reject) => { - try { - storage.innerHTML = JSON.stringify(this.get()); - resolve(storage); - } catch (e) { - reject(e); - } - }); - } + return new Promise((resolve, reject) => { + try { + storage.innerHTML = JSON.stringify(this.get()); + resolve(storage); + } catch (e) { + reject(e); + } + }); + } } diff --git a/source/dom/resource/data.mjs b/source/dom/resource/data.mjs index 0eaff437a..b698a9edd 100644 --- a/source/dom/resource/data.mjs +++ b/source/dom/resource/data.mjs @@ -12,28 +12,28 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {internalStateSymbol} from "../../constants.mjs"; -import {extend} from "../../data/extend.mjs"; -import {getGlobalFunction} from "../../types/global.mjs"; -import {addAttributeToken} from "../attributes.mjs"; +import { internalStateSymbol } from "../../constants.mjs"; +import { extend } from "../../data/extend.mjs"; +import { getGlobalFunction } from "../../types/global.mjs"; +import { addAttributeToken } from "../attributes.mjs"; import { - ATTRIBUTE_CLASS, - ATTRIBUTE_ERRORMESSAGE, - ATTRIBUTE_ID, - ATTRIBUTE_SRC, - ATTRIBUTE_TITLE, - ATTRIBUTE_TYPE, - TAG_SCRIPT, + ATTRIBUTE_CLASS, + ATTRIBUTE_ERRORMESSAGE, + ATTRIBUTE_ID, + ATTRIBUTE_SRC, + ATTRIBUTE_TITLE, + ATTRIBUTE_TYPE, + TAG_SCRIPT, } from "../constants.mjs"; import { - KEY_DOCUMENT, - KEY_QUERY, - referenceSymbol, - Resource, + KEY_DOCUMENT, + KEY_QUERY, + referenceSymbol, + Resource, } from "../resource.mjs"; -import {instanceSymbol} from "../../constants.mjs"; +import { instanceSymbol } from "../../constants.mjs"; -export {Data}; +export { Data }; /** * This class is used by the resource manager to embed data. @@ -45,59 +45,59 @@ export {Data}; * @summary A Data Resource class */ class Data extends Resource { - /** - * @property {string} mode=cors https://developer.mozilla.org/en-US/docs/Web/API/fetch - * @property {string} credentials=same-origin https://developer.mozilla.org/en-US/docs/Web/API/fetch - * @property {string} type=application/json {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type} - */ - get defaults() { - return extend({}, super.defaults, { - mode: "cors", - credentials: "same-origin", - type: "application/json", - }); - } - - /** - * - * @return {Monster.DOM.Resource.Data} - */ - create() { - createElement.call(this); - return this; - } - - /** - * This method appends the HTMLElement to the specified document - * - * throws {Error} target not found - * @return {Monster.DOM.Resource} - */ - connect() { - const self = this; - if (!(this[referenceSymbol] instanceof HTMLElement)) { - this.create(); - } - - appendToDocument.call(this); - return this; - } - - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - * @since 2.1.0 - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/dom/resource/data"); - } - - /** - * @return {string} - */ - static getURLAttribute() { - return ATTRIBUTE_SRC; - } + /** + * @property {string} mode=cors https://developer.mozilla.org/en-US/docs/Web/API/fetch + * @property {string} credentials=same-origin https://developer.mozilla.org/en-US/docs/Web/API/fetch + * @property {string} type=application/json {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type} + */ + get defaults() { + return extend({}, super.defaults, { + mode: "cors", + credentials: "same-origin", + type: "application/json", + }); + } + + /** + * + * @return {Monster.DOM.Resource.Data} + */ + create() { + createElement.call(this); + return this; + } + + /** + * This method appends the HTMLElement to the specified document + * + * throws {Error} target not found + * @return {Monster.DOM.Resource} + */ + connect() { + const self = this; + if (!(this[referenceSymbol] instanceof HTMLElement)) { + this.create(); + } + + appendToDocument.call(this); + return this; + } + + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + * @since 2.1.0 + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/dom/resource/data"); + } + + /** + * @return {string} + */ + static getURLAttribute() { + return ATTRIBUTE_SRC; + } } /** @@ -105,21 +105,21 @@ class Data extends Resource { * @return {Monster.DOM.Resource.Data} */ function createElement() { - const document = this.getOption(KEY_DOCUMENT); - this[referenceSymbol] = document.createElement(TAG_SCRIPT); - - for (const key of [ - ATTRIBUTE_TYPE, - ATTRIBUTE_ID, - ATTRIBUTE_CLASS, - ATTRIBUTE_TITLE, - ]) { - if (this.getOption(key) !== undefined) { - this[referenceSymbol][key] = this.getOption(key); - } - } - - return this; + const document = this.getOption(KEY_DOCUMENT); + this[referenceSymbol] = document.createElement(TAG_SCRIPT); + + for (const key of [ + ATTRIBUTE_TYPE, + ATTRIBUTE_ID, + ATTRIBUTE_CLASS, + ATTRIBUTE_TITLE, + ]) { + if (this.getOption(key) !== undefined) { + this[referenceSymbol][key] = this.getOption(key); + } + } + + return this; } /** @@ -128,41 +128,41 @@ function createElement() { * throws {Error} target not found */ function appendToDocument() { - const targetNode = document.querySelector(this.getOption(KEY_QUERY, "head")); - if (!(targetNode instanceof HTMLElement)) { - throw new Error("target not found"); - } - - targetNode.appendChild(this[referenceSymbol]); - - getGlobalFunction("fetch")(this.getOption(ATTRIBUTE_SRC), { - method: "GET", // *GET, POST, PUT, DELETE, etc. - mode: this.getOption("mode", "cors"), // no-cors, *cors, same-origin - cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached - credentials: this.getOption("credentials", "same-origin"), // include, *same-origin, omit - headers: { - Accept: this.getOption("type", "application/json"), - }, - redirect: "follow", // manual, *follow, error - referrerPolicy: "no-referrer", // no-referrer, - }) - .then((response) => { - return response.text(); - }) - .then((text) => { - const textNode = document.createTextNode(text); - this[referenceSymbol].appendChild(textNode); - - this[internalStateSymbol].getSubject()["loaded"] = true; - }) - .catch((e) => { - this[internalStateSymbol].setSubject({ - loaded: true, - error: e.toString(), - }); - - targetNode.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString()); - }); - - return this; + const targetNode = document.querySelector(this.getOption(KEY_QUERY, "head")); + if (!(targetNode instanceof HTMLElement)) { + throw new Error("target not found"); + } + + targetNode.appendChild(this[referenceSymbol]); + + getGlobalFunction("fetch")(this.getOption(ATTRIBUTE_SRC), { + method: "GET", // *GET, POST, PUT, DELETE, etc. + mode: this.getOption("mode", "cors"), // no-cors, *cors, same-origin + cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached + credentials: this.getOption("credentials", "same-origin"), // include, *same-origin, omit + headers: { + Accept: this.getOption("type", "application/json"), + }, + redirect: "follow", // manual, *follow, error + referrerPolicy: "no-referrer", // no-referrer, + }) + .then((response) => { + return response.text(); + }) + .then((text) => { + const textNode = document.createTextNode(text); + this[referenceSymbol].appendChild(textNode); + + this[internalStateSymbol].getSubject()["loaded"] = true; + }) + .catch((e) => { + this[internalStateSymbol].setSubject({ + loaded: true, + error: e.toString(), + }); + + targetNode.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString()); + }); + + return this; } diff --git a/source/dom/template.mjs b/source/dom/template.mjs index b0aa03613..10fc5a052 100644 --- a/source/dom/template.mjs +++ b/source/dom/template.mjs @@ -12,15 +12,15 @@ * SPDX-License-Identifier: AGPL-3.0 */ -import {Base} from "../types/base.mjs"; -import {getGlobalFunction, getGlobalObject} from "../types/global.mjs"; -import {validateInstance, validateString} from "../types/validate.mjs"; -import {ATTRIBUTE_TEMPLATE_PREFIX} from "./constants.mjs"; -import {getDocumentTheme} from "./theme.mjs"; -import {instanceSymbol} from "../constants.mjs"; -import {findElementWithIdUpwards} from "./util.mjs"; +import { Base } from "../types/base.mjs"; +import { getGlobalFunction, getGlobalObject } from "../types/global.mjs"; +import { validateInstance, validateString } from "../types/validate.mjs"; +import { ATTRIBUTE_TEMPLATE_PREFIX } from "./constants.mjs"; +import { getDocumentTheme } from "./theme.mjs"; +import { instanceSymbol } from "../constants.mjs"; +import { findElementWithIdUpwards } from "./util.mjs"; -export {Template}; +export { Template }; /** * The template class provides methods for creating templates. @@ -32,45 +32,45 @@ export {Template}; * @summary A template class */ class Template extends Base { - /** - * - * @param {HTMLTemplateElement} template - * @throws {TypeError} value is not an instance of - * @throws {TypeError} value is not a function - * @throws {Error} the function is not defined - */ - constructor(template) { - super(); - const HTMLTemplateElement = getGlobalFunction("HTMLTemplateElement"); - validateInstance(template, HTMLTemplateElement); - this.template = template; - } - - /** - * This method is called by the `instanceof` operator. - * @returns {symbol} - * @since 2.1.0 - */ - static get [instanceSymbol]() { - return Symbol.for("@schukai/monster/dom/resource/template"); - } - - /** - * - * @returns {HTMLTemplateElement} - */ - getTemplateElement() { - return this.template; - } - - /** - * - * @return {DocumentFragment} - * @throws {TypeError} value is not an instance of - */ - createDocumentFragment() { - return this.template.content.cloneNode(true); - } + /** + * + * @param {HTMLTemplateElement} template + * @throws {TypeError} value is not an instance of + * @throws {TypeError} value is not a function + * @throws {Error} the function is not defined + */ + constructor(template) { + super(); + const HTMLTemplateElement = getGlobalFunction("HTMLTemplateElement"); + validateInstance(template, HTMLTemplateElement); + this.template = template; + } + + /** + * This method is called by the `instanceof` operator. + * @returns {symbol} + * @since 2.1.0 + */ + static get [instanceSymbol]() { + return Symbol.for("@schukai/monster/dom/resource/template"); + } + + /** + * + * @returns {HTMLTemplateElement} + */ + getTemplateElement() { + return this.template; + } + + /** + * + * @return {DocumentFragment} + * @throws {TypeError} value is not an instance of + */ + createDocumentFragment() { + return this.template.content.cloneNode(true); + } } /** @@ -137,70 +137,70 @@ class Template extends Base { * @throws {TypeError} value is not a string */ export function findDocumentTemplate(id, currentNode) { - validateString(id); - - const document = getGlobalObject("document"); - const HTMLTemplateElement = getGlobalFunction("HTMLTemplateElement"); - const DocumentFragment = getGlobalFunction("DocumentFragment"); - const Document = getGlobalFunction("Document"); - - let prefixID; - - if ( - !( - currentNode instanceof Document || currentNode instanceof DocumentFragment - ) - ) { - if (currentNode instanceof Node) { - if (currentNode.hasAttribute(ATTRIBUTE_TEMPLATE_PREFIX)) { - prefixID = currentNode.getAttribute(ATTRIBUTE_TEMPLATE_PREFIX); - } - - currentNode = currentNode.getRootNode(); - - if ( - !( - currentNode instanceof Document || - currentNode instanceof DocumentFragment - ) - ) { - currentNode = currentNode.ownerDocument; - } - } - - if ( - !( - currentNode instanceof Document || - currentNode instanceof DocumentFragment - ) - ) { - currentNode = document; - } - } - - let template; - const theme = getDocumentTheme(); - - if (prefixID) { - const themedPrefixID = `${prefixID}-${id}-${theme.getName()}`; - - template = findElementWithIdUpwards(currentNode, themedPrefixID); - if (template instanceof HTMLTemplateElement) { - return new Template(template); - } - } - - const themedID = `${id}-${theme.getName()}`; - - template = findElementWithIdUpwards(currentNode, themedID); - if (template instanceof HTMLTemplateElement) { - return new Template(template); - } - - template = findElementWithIdUpwards(currentNode, id); - if (template instanceof HTMLTemplateElement) { - return new Template(template); - } - - throw new Error(`template ${id} not found.`); + validateString(id); + + const document = getGlobalObject("document"); + const HTMLTemplateElement = getGlobalFunction("HTMLTemplateElement"); + const DocumentFragment = getGlobalFunction("DocumentFragment"); + const Document = getGlobalFunction("Document"); + + let prefixID; + + if ( + !( + currentNode instanceof Document || currentNode instanceof DocumentFragment + ) + ) { + if (currentNode instanceof Node) { + if (currentNode.hasAttribute(ATTRIBUTE_TEMPLATE_PREFIX)) { + prefixID = currentNode.getAttribute(ATTRIBUTE_TEMPLATE_PREFIX); + } + + currentNode = currentNode.getRootNode(); + + if ( + !( + currentNode instanceof Document || + currentNode instanceof DocumentFragment + ) + ) { + currentNode = currentNode.ownerDocument; + } + } + + if ( + !( + currentNode instanceof Document || + currentNode instanceof DocumentFragment + ) + ) { + currentNode = document; + } + } + + let template; + const theme = getDocumentTheme(); + + if (prefixID) { + const themedPrefixID = `${prefixID}-${id}-${theme.getName()}`; + + template = findElementWithIdUpwards(currentNode, themedPrefixID); + if (template instanceof HTMLTemplateElement) { + return new Template(template); + } + } + + const themedID = `${id}-${theme.getName()}`; + + template = findElementWithIdUpwards(currentNode, themedID); + if (template instanceof HTMLTemplateElement) { + return new Template(template); + } + + template = findElementWithIdUpwards(currentNode, id); + if (template instanceof HTMLTemplateElement) { + return new Template(template); + } + + throw new Error(`template ${id} not found.`); } -- GitLab