From 3367fea887016d6ad824a023fc0529a682baa65c Mon Sep 17 00:00:00 2001 From: Philippe Torrel Date: Tue, 27 Oct 2026 14:34:42 +0100 Subject: [PATCH] --- .../uebungen/u17-18_validator-blur/.gitignore | 24 + .../u17-18_validator-blur/.oxlintrc.json | 8 + .../uebungen/u17-18_validator-blur/README.md | 16 + .../uebungen/u17-18_validator-blur/index.html | 14 + .../u17-18_validator-blur/package.json | 27 + .../u17-18_validator-blur/public/favicon.svg | 1 + .../u17-18_validator-blur/public/icons.svg | 24 + .../u17-18_validator-blur/src/App.jsx | 53 + .../u17-18_validator-blur/src/assets/hero.png | Bin 0 -> 13057 bytes .../src/assets/react.svg | 1 + .../u17-18_validator-blur/src/assets/vite.svg | 1 + .../src/components/common/Badge.jsx | 11 + .../src/components/forms/FormContact.jsx | 141 ++ .../src/components/navs/Navbar.jsx | 44 + .../u17-18_validator-blur/src/main.jsx | 21 + .../src/pages/AboutPage.jsx | 34 + .../src/pages/ContactPage.jsx | 16 + .../src/pages/HomePage.jsx | 10 + .../src/pages/UserPage.jsx | 25 + .../src/pages/UserProfilePage.jsx | 18 + .../src/routes/Router.jsx | 61 + .../src/styles/01_frameworks/_index.scss | 3 + .../bootstrap-5.3.8/_accordion.scss | 153 ++ .../01_frameworks/bootstrap-5.3.8/_alert.scss | 68 + .../01_frameworks/bootstrap-5.3.8/_badge.scss | 38 + .../bootstrap-5.3.8/_breadcrumb.scss | 40 + .../bootstrap-5.3.8/_button-group.scss | 147 ++ .../bootstrap-5.3.8/_buttons.scss | 216 ++ .../01_frameworks/bootstrap-5.3.8/_card.scss | 238 +++ .../bootstrap-5.3.8/_carousel.scss | 226 +++ .../01_frameworks/bootstrap-5.3.8/_close.scss | 66 + .../bootstrap-5.3.8/_containers.scss | 41 + .../bootstrap-5.3.8/_dropdown.scss | 250 +++ .../01_frameworks/bootstrap-5.3.8/_forms.scss | 9 + .../bootstrap-5.3.8/_functions.scss | 302 +++ .../01_frameworks/bootstrap-5.3.8/_grid.scss | 39 + .../bootstrap-5.3.8/_helpers.scss | 12 + .../bootstrap-5.3.8/_images.scss | 42 + .../bootstrap-5.3.8/_list-group.scss | 199 ++ .../01_frameworks/bootstrap-5.3.8/_maps.scss | 174 ++ .../bootstrap-5.3.8/_mixins.scss | 42 + .../01_frameworks/bootstrap-5.3.8/_modal.scss | 240 +++ .../01_frameworks/bootstrap-5.3.8/_nav.scss | 197 ++ .../bootstrap-5.3.8/_navbar.scss | 289 +++ .../bootstrap-5.3.8/_offcanvas.scss | 147 ++ .../bootstrap-5.3.8/_pagination.scss | 109 + .../bootstrap-5.3.8/_placeholders.scss | 51 + .../bootstrap-5.3.8/_popover.scss | 196 ++ .../bootstrap-5.3.8/_progress.scss | 68 + .../bootstrap-5.3.8/_reboot.scss | 617 ++++++ .../01_frameworks/bootstrap-5.3.8/_root.scss | 187 ++ .../bootstrap-5.3.8/_spinners.scss | 86 + .../bootstrap-5.3.8/_tables.scss | 171 ++ .../bootstrap-5.3.8/_toasts.scss | 73 + .../bootstrap-5.3.8/_tooltip.scss | 119 ++ .../bootstrap-5.3.8/_transitions.scss | 27 + .../01_frameworks/bootstrap-5.3.8/_type.scss | 106 + .../bootstrap-5.3.8/_utilities.scss | 806 ++++++++ .../bootstrap-5.3.8/_variables-dark.scss | 102 + .../bootstrap-5.3.8/_variables.scss | 1753 +++++++++++++++++ .../bootstrap-5.3.8/bootstrap-grid.scss | 62 + .../bootstrap-5.3.8/bootstrap-reboot.scss | 10 + .../bootstrap-5.3.8/bootstrap-utilities.scss | 19 + .../bootstrap-5.3.8/bootstrap.scss | 52 + .../forms/_floating-labels.scss | 97 + .../bootstrap-5.3.8/forms/_form-check.scss | 189 ++ .../bootstrap-5.3.8/forms/_form-control.scss | 214 ++ .../bootstrap-5.3.8/forms/_form-range.scss | 91 + .../bootstrap-5.3.8/forms/_form-select.scss | 80 + .../bootstrap-5.3.8/forms/_form-text.scss | 11 + .../bootstrap-5.3.8/forms/_input-group.scss | 132 ++ .../bootstrap-5.3.8/forms/_labels.scss | 36 + .../bootstrap-5.3.8/forms/_validation.scss | 12 + .../bootstrap-5.3.8/helpers/_clearfix.scss | 3 + .../bootstrap-5.3.8/helpers/_color-bg.scss | 7 + .../helpers/_colored-links.scss | 30 + .../bootstrap-5.3.8/helpers/_focus-ring.scss | 5 + .../bootstrap-5.3.8/helpers/_icon-link.scss | 25 + .../bootstrap-5.3.8/helpers/_position.scss | 36 + .../bootstrap-5.3.8/helpers/_ratio.scss | 26 + .../bootstrap-5.3.8/helpers/_stacks.scss | 15 + .../helpers/_stretched-link.scss | 15 + .../helpers/_text-truncation.scss | 7 + .../helpers/_visually-hidden.scss | 8 + .../bootstrap-5.3.8/helpers/_vr.scss | 8 + .../bootstrap-5.3.8/mixins/_alert.scss | 18 + .../bootstrap-5.3.8/mixins/_backdrop.scss | 14 + .../bootstrap-5.3.8/mixins/_banner.scss | 7 + .../mixins/_border-radius.scss | 78 + .../bootstrap-5.3.8/mixins/_box-shadow.scss | 24 + .../bootstrap-5.3.8/mixins/_breakpoints.scss | 127 ++ .../bootstrap-5.3.8/mixins/_buttons.scss | 70 + .../bootstrap-5.3.8/mixins/_caret.scss | 69 + .../bootstrap-5.3.8/mixins/_clearfix.scss | 9 + .../bootstrap-5.3.8/mixins/_color-mode.scss | 21 + .../bootstrap-5.3.8/mixins/_color-scheme.scss | 7 + .../bootstrap-5.3.8/mixins/_container.scss | 11 + .../bootstrap-5.3.8/mixins/_deprecate.scss | 10 + .../bootstrap-5.3.8/mixins/_forms.scss | 163 ++ .../bootstrap-5.3.8/mixins/_gradients.scss | 47 + .../bootstrap-5.3.8/mixins/_grid.scss | 151 ++ .../bootstrap-5.3.8/mixins/_image.scss | 16 + .../bootstrap-5.3.8/mixins/_list-group.scss | 26 + .../bootstrap-5.3.8/mixins/_lists.scss | 7 + .../bootstrap-5.3.8/mixins/_pagination.scss | 10 + .../bootstrap-5.3.8/mixins/_reset-text.scss | 17 + .../bootstrap-5.3.8/mixins/_resize.scss | 6 + .../mixins/_table-variants.scss | 24 + .../mixins/_text-truncate.scss | 8 + .../bootstrap-5.3.8/mixins/_transition.scss | 26 + .../bootstrap-5.3.8/mixins/_utilities.scss | 97 + .../mixins/_visually-hidden.scss | 38 + .../bootstrap-5.3.8/tests/jasmine.js | 16 + .../_auto-import-of-variables-dark.test.scss | 7 + .../tests/mixins/_box-shadow.test.scss | 188 ++ .../tests/mixins/_color-contrast.test.scss | 139 ++ .../tests/mixins/_color-modes.test.scss | 69 + .../_media-query-color-mode-full.test.scss | 8 + .../tests/mixins/_utilities.test.scss | 393 ++++ .../tests/sass-true/register.js | 14 + .../bootstrap-5.3.8/tests/sass-true/runner.js | 17 + .../tests/utilities/_api.test.scss | 75 + .../bootstrap-5.3.8/utilities/_api.scss | 47 + .../bootstrap-5.3.8/vendor/_rfs.scss | 348 ++++ .../01_frameworks/bulma-1.04/_index.scss | 10 + .../01_frameworks/bulma-1.04/base/_index.scss | 6 + .../bulma-1.04/base/animations.scss | 15 + .../bulma-1.04/base/generic.scss | 240 +++ .../bulma-1.04/base/minireset.scss | 92 + .../bulma-1.04/base/skeleton.scss | 114 ++ .../bulma-1.04/components/_index.scss | 13 + .../bulma-1.04/components/breadcrumb.scss | 139 ++ .../bulma-1.04/components/card.scss | 162 ++ .../bulma-1.04/components/dropdown.scss | 188 ++ .../bulma-1.04/components/menu.scss | 165 ++ .../bulma-1.04/components/message.scss | 183 ++ .../bulma-1.04/components/modal.scss | 164 ++ .../bulma-1.04/components/navbar.scss | 799 ++++++++ .../bulma-1.04/components/pagination.scss | 379 ++++ .../bulma-1.04/components/panel.scss | 218 ++ .../bulma-1.04/components/tabs.scss | 273 +++ .../bulma-1.04/elements/_index.scss | 16 + .../bulma-1.04/elements/block.scss | 6 + .../bulma-1.04/elements/box.scss | 59 + .../bulma-1.04/elements/button.scss | 659 +++++++ .../bulma-1.04/elements/content.scss | 289 +++ .../bulma-1.04/elements/delete.scss | 6 + .../bulma-1.04/elements/icon.scss | 67 + .../bulma-1.04/elements/image.scss | 64 + .../bulma-1.04/elements/loader.scss | 15 + .../bulma-1.04/elements/notification.scss | 105 + .../bulma-1.04/elements/progress.scss | 115 ++ .../bulma-1.04/elements/table.scss | 261 +++ .../bulma-1.04/elements/tag.scss | 219 ++ .../bulma-1.04/elements/title.scss | 130 ++ .../01_frameworks/bulma-1.04/form/_index.scss | 9 + .../bulma-1.04/form/checkbox-radio.scss | 36 + .../01_frameworks/bulma-1.04/form/file.scss | 330 ++++ .../bulma-1.04/form/input-textarea.scss | 115 ++ .../01_frameworks/bulma-1.04/form/select.scss | 144 ++ .../01_frameworks/bulma-1.04/form/shared.scss | 178 ++ .../01_frameworks/bulma-1.04/form/tools.scss | 352 ++++ .../01_frameworks/bulma-1.04/grid/_index.scss | 5 + .../bulma-1.04/grid/columns.scss | 961 +++++++++ .../01_frameworks/bulma-1.04/grid/grid.scss | 209 ++ .../bulma-1.04/helpers/_index.scss | 15 + .../bulma-1.04/helpers/aspect-ratio.scss | 12 + .../bulma-1.04/helpers/border.scss | 15 + .../bulma-1.04/helpers/color.scss | 344 ++++ .../bulma-1.04/helpers/flexbox.scss | 62 + .../bulma-1.04/helpers/float.scss | 28 + .../01_frameworks/bulma-1.04/helpers/gap.scss | 24 + .../bulma-1.04/helpers/other.scss | 19 + .../bulma-1.04/helpers/overflow.scss | 21 + .../bulma-1.04/helpers/position.scss | 19 + .../bulma-1.04/helpers/spacing.scss | 64 + .../bulma-1.04/helpers/typography.scss | 174 ++ .../bulma-1.04/helpers/visibility.scss | 221 +++ .../bulma-1.04/layout/_index.scss | 9 + .../bulma-1.04/layout/container.scss | 59 + .../bulma-1.04/layout/footer.scss | 23 + .../01_frameworks/bulma-1.04/layout/hero.scss | 273 +++ .../bulma-1.04/layout/level.scss | 107 + .../bulma-1.04/layout/media.scss | 106 + .../bulma-1.04/layout/section.scss | 38 + .../bulma-1.04/themes/_index.scss | 36 + .../01_frameworks/bulma-1.04/themes/dark.scss | 57 + .../bulma-1.04/themes/light.scss | 147 ++ .../bulma-1.04/themes/setup.scss | 174 ++ .../bulma-1.04/utilities/_index.scss | 7 + .../bulma-1.04/utilities/controls.scss | 85 + .../bulma-1.04/utilities/css-variables.scss | 502 +++++ .../utilities/derived-variables.scss | 112 ++ .../bulma-1.04/utilities/extends.scss | 34 + .../bulma-1.04/utilities/functions.scss | 310 +++ .../utilities/initial-variables.scss | 157 ++ .../bulma-1.04/utilities/mixins.scss | 462 +++++ .../src/styles/02_fonts/_index.scss | 3 + .../02_fonts/_playfair-display-v40-latin.scss | 96 + .../02_fonts/_source-sans-3-v19-latin.scss | 134 ++ .../src/styles/03_base/_colors.scss | 12 + .../src/styles/03_base/_index.scss | 5 + .../src/styles/03_base/_theme.scss | 46 + .../src/styles/03_base/_typography.scss | 9 + .../src/styles/03_base/_utils.scss | 0 .../src/styles/03_base/_variables.scss | 0 .../src/styles/04_plugins/_index.scss | 4 + .../core/foundation/animations.scss | 9 + .../04_plugins/splide-4.1.4/core/index.scss | 3 + .../core/object/modifiers/draggable.scss | 8 + .../core/object/modifiers/fade.scss | 18 + .../core/object/modifiers/index.scss | 4 + .../core/object/modifiers/rtl.scss | 5 + .../core/object/modifiers/ttb.scss | 9 + .../core/object/objects/container.scss | 6 + .../core/object/objects/index.scss | 10 + .../core/object/objects/list.scss | 17 + .../core/object/objects/pagination.scss | 26 + .../core/object/objects/progress.scss | 7 + .../core/object/objects/root.scss | 9 + .../core/object/objects/slide.scss | 14 + .../core/object/objects/spinner.scss | 21 + .../splide-4.1.4/core/object/objects/sr.scss | 12 + .../core/object/objects/toggle.scss | 22 + .../core/object/objects/track.scss | 7 + .../template/default/foundation/colors.scss | 8 + .../template/default/foundation/mixins.scss | 27 + .../splide-4.1.4/template/default/index.scss | 13 + .../default/object/modifiers/index.scss | 3 + .../default/object/modifiers/nav.scss | 37 + .../default/object/modifiers/rtl.scss | 28 + .../default/object/modifiers/ttb.scss | 54 + .../default/object/objects/arrow.scss | 105 + .../default/object/objects/index.scss | 5 + .../default/object/objects/pagination.scss | 80 + .../default/object/objects/progress.scss | 13 + .../default/object/objects/slide.scss | 42 + .../default/object/objects/toggle.scss | 19 + .../splide-4.1.4/themes/default/index.scss | 1 + .../splide-4.1.4/themes/sea-green/index.scss | 52 + .../sea-green/object/objects/arrow.scss | 17 + .../sea-green/object/objects/index.scss | 3 + .../themes/sea-green/object/objects/root.scss | 3 + .../splide-4.1.4/themes/skyblue/index.scss | 37 + .../04_plugins/toastify-1.12/_toastify.scss | 88 + .../src/styles/05_modules/_button.scss | 13 + .../src/styles/05_modules/_footer-main.scss | 37 + .../src/styles/05_modules/_header-main.scss | 83 + .../src/styles/05_modules/_index.scss | 8 + .../src/styles/05_modules/_inputAmount.scss | 29 + .../src/styles/05_modules/_logo-main.scss | 14 + .../src/styles/05_modules/_menu-main.scss | 60 + .../src/styles/05_modules/_nav-menu.scss | 6 + .../styles/05_modules/_product-manager.scss | 37 + .../src/styles/main.scss | 16 + .../src/utils/validators/validate.js | 28 + .../u17-18_validator-blur/vite.config.js | 15 + 06_react/uebungen/uebungen-17-18-react.zip | Bin 0 -> 278518 bytes .../02_react-with-forms/package-lock.json | 27 +- .../tag37/02_react-with-forms/package.json | 1 + .../forms/react-hook-form/FormContact.jsx | 83 +- 261 files changed, 24597 insertions(+), 48 deletions(-) create mode 100644 06_react/uebungen/u17-18_validator-blur/.gitignore create mode 100644 06_react/uebungen/u17-18_validator-blur/.oxlintrc.json create mode 100644 06_react/uebungen/u17-18_validator-blur/README.md create mode 100644 06_react/uebungen/u17-18_validator-blur/index.html create mode 100644 06_react/uebungen/u17-18_validator-blur/package.json create mode 100644 06_react/uebungen/u17-18_validator-blur/public/favicon.svg create mode 100644 06_react/uebungen/u17-18_validator-blur/public/icons.svg create mode 100644 06_react/uebungen/u17-18_validator-blur/src/App.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/assets/hero.png create mode 100644 06_react/uebungen/u17-18_validator-blur/src/assets/react.svg create mode 100644 06_react/uebungen/u17-18_validator-blur/src/assets/vite.svg create mode 100644 06_react/uebungen/u17-18_validator-blur/src/components/common/Badge.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/components/forms/FormContact.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/components/navs/Navbar.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/main.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/pages/AboutPage.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/pages/ContactPage.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/pages/HomePage.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/pages/UserPage.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/pages/UserProfilePage.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/routes/Router.jsx create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_accordion.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_alert.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_badge.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_breadcrumb.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_button-group.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_buttons.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_card.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_carousel.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_close.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_containers.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_dropdown.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_forms.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_functions.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_grid.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_helpers.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_images.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_list-group.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_maps.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_mixins.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_modal.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_nav.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_navbar.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_offcanvas.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_pagination.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_placeholders.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_popover.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_progress.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_reboot.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_root.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_spinners.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_tables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_toasts.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_tooltip.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_transitions.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_type.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_utilities.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_variables-dark.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_variables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-grid.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-reboot.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-utilities.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_floating-labels.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-check.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-control.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-range.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-select.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-text.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_input-group.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_labels.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/forms/_validation.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_clearfix.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_color-bg.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_colored-links.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_focus-ring.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_icon-link.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_position.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_ratio.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stacks.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stretched-link.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_text-truncation.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_visually-hidden.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_vr.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_alert.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_backdrop.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_banner.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_border-radius.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_box-shadow.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_breakpoints.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_buttons.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_caret.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_clearfix.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-mode.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-scheme.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_container.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_deprecate.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_forms.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_gradients.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_grid.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_image.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_list-group.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_lists.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_pagination.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_reset-text.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_resize.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_table-variants.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_text-truncate.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_transition.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_utilities.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_visually-hidden.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/jasmine.js create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_auto-import-of-variables-dark.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_box-shadow.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-contrast.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-modes.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_media-query-color-mode-full.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_utilities.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/register.js create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/runner.js create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/tests/utilities/_api.test.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/utilities/_api.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/vendor/_rfs.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/base/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/base/animations.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/base/generic.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/base/minireset.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/base/skeleton.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/breadcrumb.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/card.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/dropdown.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/menu.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/message.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/modal.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/navbar.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/pagination.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/panel.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/components/tabs.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/block.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/box.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/button.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/content.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/delete.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/icon.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/image.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/loader.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/notification.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/progress.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/table.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/tag.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/elements/title.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/checkbox-radio.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/file.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/input-textarea.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/select.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/shared.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/form/tools.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/grid/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/grid/columns.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/grid/grid.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/aspect-ratio.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/border.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/color.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/flexbox.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/float.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/gap.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/other.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/overflow.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/position.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/spacing.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/typography.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/helpers/visibility.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/container.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/footer.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/hero.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/level.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/media.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/layout/section.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/themes/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/themes/dark.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/themes/light.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/themes/setup.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/controls.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/css-variables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/derived-variables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/extends.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/functions.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/initial-variables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bulma-1.04/utilities/mixins.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/02_fonts/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/02_fonts/_playfair-display-v40-latin.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/02_fonts/_source-sans-3-v19-latin.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_colors.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_theme.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_typography.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_utils.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/03_base/_variables.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/foundation/animations.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/draggable.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/fade.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/rtl.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/ttb.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/container.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/list.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/pagination.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/progress.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/root.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/slide.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/spinner.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/sr.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/toggle.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/core/object/objects/track.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/foundation/colors.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/foundation/mixins.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/nav.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/rtl.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/ttb.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/arrow.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/pagination.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/progress.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/slide.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/toggle.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/default/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/sea-green/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/arrow.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/root.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/splide-4.1.4/themes/skyblue/index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/04_plugins/toastify-1.12/_toastify.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_button.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_footer-main.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_header-main.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_index.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_inputAmount.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_logo-main.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_menu-main.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_nav-menu.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/05_modules/_product-manager.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/styles/main.scss create mode 100644 06_react/uebungen/u17-18_validator-blur/src/utils/validators/validate.js create mode 100644 06_react/uebungen/u17-18_validator-blur/vite.config.js create mode 100644 06_react/uebungen/uebungen-17-18-react.zip diff --git a/06_react/uebungen/u17-18_validator-blur/.gitignore b/06_react/uebungen/u17-18_validator-blur/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/06_react/uebungen/u17-18_validator-blur/.oxlintrc.json b/06_react/uebungen/u17-18_validator-blur/.oxlintrc.json new file mode 100644 index 0000000..1255078 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/.oxlintrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "oxc"], + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/README.md b/06_react/uebungen/u17-18_validator-blur/README.md new file mode 100644 index 0000000..d937833 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/README.md @@ -0,0 +1,16 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the Oxlint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and Oxlint's TypeScript related rules in your project. diff --git a/06_react/uebungen/u17-18_validator-blur/index.html b/06_react/uebungen/u17-18_validator-blur/index.html new file mode 100644 index 0000000..2a7c876 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/index.html @@ -0,0 +1,14 @@ + + + + + + + + u17-u18 validator + + +
+ + + diff --git a/06_react/uebungen/u17-18_validator-blur/package.json b/06_react/uebungen/u17-18_validator-blur/package.json new file mode 100644 index 0000000..88c9f67 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/package.json @@ -0,0 +1,27 @@ +{ + "name": "u17-18_validator-blur", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "oxlint", + "preview": "vite preview" + }, + "dependencies": { + "bootstrap": "^5.3.8", + "react": "^19.3.1", + "react-dom": "^19.3.1", + "react-icons": "^5.7.0", + "react-router-dom": "^7.18.4" + }, + "devDependencies": { + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.2", + "oxlint": "^1.90.0", + "sass-embedded": "^1.106.1", + "vite": "^8.3.5" + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/public/favicon.svg b/06_react/uebungen/u17-18_validator-blur/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/06_react/uebungen/u17-18_validator-blur/public/icons.svg b/06_react/uebungen/u17-18_validator-blur/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/06_react/uebungen/u17-18_validator-blur/src/App.jsx b/06_react/uebungen/u17-18_validator-blur/src/App.jsx new file mode 100644 index 0000000..7a90280 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/App.jsx @@ -0,0 +1,53 @@ +import { Navigate } from 'react-router-dom'; +import Router from './routes/Router'; + +// components +import Navbar from './components/navs/Navbar'; + +function App() { + return ( + <> + + +
+ + +
+
+

Übung 17: Formularvalidierung über validator

+

+ Erweitere das Kontaktformular, um die Eingaben des Benutzers mit der validator-Bibliothek zu + validieren. Die validator-Bibliothek bietet eine Vielzahl von Funktionen zur Validierung von + Eingaben, z.B. für E-Mail-Adressen, URLs, Zahlen usw. +

+
    +
  • Installiere die validator-Bibliothek.
  • +
  • + Verwende die isEmail-Funktion, um die E-Mail-Adresse des Benutzers zu validieren. +
  • +
  • Überprüfe die Länge der Eingaben für firstname, lastname und message.
  • +
  • Zeige entsprechende Fehlermeldungen an, wenn die Eingaben ungültig sind.
  • +
+
+
+
+
+

Übung 18: Formularvalidierung nach Eingabe

+

+ Bisher haben wir die Formularvalidierung nur beim Absenden des Formulars durchgeführt. Erweitere das + Kontaktformular, um die Eingaben des Benutzers in Echtzeit zu validieren. Das bedeutet, dass die + Fehlermeldungen sofort angezeigt werden, wenn der Benutzer ein Feld verlässt und eine ungültige Eingabe + macht. +

+

+ Hinweis: Verwende das onBlur-Event, um die Validierung nach dem Verlassen + eines Feldes auszulösen. +

+
+
+
+ + ); +} + +export default App; diff --git a/06_react/uebungen/u17-18_validator-blur/src/assets/hero.png b/06_react/uebungen/u17-18_validator-blur/src/assets/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..02251f4b956c55af2d76fd0788124d7eee2b45eb GIT binary patch literal 13057 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 P00000NkvXXu0mjft=yBf literal 0 HcmV?d00001 diff --git a/06_react/uebungen/u17-18_validator-blur/src/assets/react.svg b/06_react/uebungen/u17-18_validator-blur/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/06_react/uebungen/u17-18_validator-blur/src/assets/vite.svg b/06_react/uebungen/u17-18_validator-blur/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/06_react/uebungen/u17-18_validator-blur/src/components/common/Badge.jsx b/06_react/uebungen/u17-18_validator-blur/src/components/common/Badge.jsx new file mode 100644 index 0000000..23cedae --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/components/common/Badge.jsx @@ -0,0 +1,11 @@ +const Badge = (props) => { + const { text = '', variant = 'secondary', color = '' } = props; + + return ( + + {text} + + ); + // {text}; +}; +export default Badge; diff --git a/06_react/uebungen/u17-18_validator-blur/src/components/forms/FormContact.jsx b/06_react/uebungen/u17-18_validator-blur/src/components/forms/FormContact.jsx new file mode 100644 index 0000000..0e4caa8 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/components/forms/FormContact.jsx @@ -0,0 +1,141 @@ +import { useState } from 'react'; +import validate from '../../utils/validators/validate'; + +const FormContact = (props) => { + // const { } = props; + + const [formData, setFormData] = useState({ + firstname: '', // + lastname: '', + email: '', + message: '', + }); + + const [errors, setErrors] = useState({}); + + // EventHandlers ======= + const handleSubmit = (e) => { + e.preventDefault(); // Standardverhalten (Versenden vom Formular) unterbinden. + + const form = e.currentTarget; + + const errors = validate(formData); + + if (Object.keys(errors).length === 0) { + console.log('Form submitted ....'); + // TODO: send over AJAX/Fetch + form.reset(); + setFormData({ + firstname: '', // + lastname: '', + email: '', + message: '', + }); + setErrors({}); + } else { + console.warn('Form submit error'); + setErrors(errors); + } + }; + + const handleChange = (e) => { + const { name, value } = e.target; + + setFormData((state) => ({ ...state, [name]: value })); + + // console.log({ [e.target.name]: e.target.value }); + // console.log('Formdata', formData); + }; + + return ( +
+
+
+
+ + +
OK
+
{errors?.firstname}
+
+
+
+
+ + +
OK
+
{errors?.lastname}
+
+
+
+ +
+
+
+ + +
OK
+
{errors?.email}
+
+
+
+ +
+
+
+ + +
OK
+
{errors?.message}
+
+
+
+ +
+
+
+ +
+
+
+
+ ); +}; +export default FormContact; diff --git a/06_react/uebungen/u17-18_validator-blur/src/components/navs/Navbar.jsx b/06_react/uebungen/u17-18_validator-blur/src/components/navs/Navbar.jsx new file mode 100644 index 0000000..bc70c62 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/components/navs/Navbar.jsx @@ -0,0 +1,44 @@ +import { NavLink } from 'react-router-dom'; + +const Navbar = (props) => { + return ( + + ); +}; + +export default Navbar; diff --git a/06_react/uebungen/u17-18_validator-blur/src/main.jsx b/06_react/uebungen/u17-18_validator-blur/src/main.jsx new file mode 100644 index 0000000..1f95cf7 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/main.jsx @@ -0,0 +1,21 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; + +import { BrowserRouter } from 'react-router-dom'; + +import App from './App.jsx'; + +// JS import +import 'bootstrap'; +// import 'bootstrap/dist/css/bootstrap.min.css'; +import './styles/main.scss'; + +const root = createRoot(document.getElementById('root')); + +root.render( + + + + + , +); diff --git a/06_react/uebungen/u17-18_validator-blur/src/pages/AboutPage.jsx b/06_react/uebungen/u17-18_validator-blur/src/pages/AboutPage.jsx new file mode 100644 index 0000000..0fbfc09 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/pages/AboutPage.jsx @@ -0,0 +1,34 @@ +const AboutPage = (props) => { + return ( +
+

About

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Minima, voluptatibus nobis molestiae, dignissimos id + dolores minus iste quisquam harum vitae rem dolorem debitis natus asperiores amet rerum ratione laboriosam quam. + Sit corporis voluptate laboriosam doloribus incidunt voluptatibus repellat. Excepturi vitae perferendis odit + enim, iusto, consequuntur assumenda corrupti autem eius minus explicabo tempore amet? Facere repudiandae, culpa + autem quae sint accusantium! Recusandae dicta itaque pariatur, veritatis voluptatem reprehenderit? Error facilis + fugit veritatis quam harum tempore dignissimos laboriosam commodi quod. Quas magnam modi saepe quae ab ipsam + amet veritatis molestias facilis odit? Quos nihil minus suscipit vel unde ipsa non quia ex quis obcaecati fugiat + animi nobis sit ducimus libero dolorem voluptates numquam, assumenda autem? Excepturi reprehenderit hic + aspernatur tempora, maiores nihil. Itaque quisquam expedita repellat voluptate, rem delectus sed, laborum dolor + minima nam ipsum possimus odit asperiores molestiae ex fugit sequi cupiditate doloremque tempora inventore + praesentium quo! Minima minus numquam aspernatur! Laudantium quisquam perspiciatis consectetur eos, nobis + doloribus reiciendis accusamus dolor quos cum cumque voluptatibus vero harum sapiente consequuntur eaque in quas + obcaecati. Et mollitia ex esse sint facilis fuga perferendis! Saepe ipsa voluptatum, nam labore corrupti, + laboriosam, sit ex explicabo facere laborum sunt natus eaque! Accusamus culpa harum repellendus iure, quasi, cum + architecto fugit ut est voluptatem cumque nisi recusandae? Cumque culpa sequi quis dolores nostrum omnis facilis + beatae quam similique, reiciendis nam modi hic libero natus blanditiis voluptatibus, magnam quos ea voluptate + odit commodi sapiente iusto dolor molestias! Blanditiis? Accusamus itaque nulla exercitationem. Maiores vitae at + dicta ipsam. Ullam eum excepturi eius, facere cumque nulla alias ab natus distinctio officia placeat possimus + optio commodi molestias repellendus voluptatem dicta delectus? Maxime aliquid numquam qui vitae doloribus + consectetur temporibus doloremque, perspiciatis sint quia obcaecati, nemo saepe velit odio nobis laborum. Natus + iure id nostrum quidem doloribus quae explicabo deserunt et quia? Labore dicta unde eum est esse reiciendis + maiores dignissimos temporibus ullam magnam, amet exercitationem praesentium voluptas, impedit sed alias, + eveniet voluptates nisi nulla dolore sequi similique fugit? Reiciendis, animi quibusdam? Pariatur sequi cum +

+
+ ); +}; + +export default AboutPage; diff --git a/06_react/uebungen/u17-18_validator-blur/src/pages/ContactPage.jsx b/06_react/uebungen/u17-18_validator-blur/src/pages/ContactPage.jsx new file mode 100644 index 0000000..fc53e25 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/pages/ContactPage.jsx @@ -0,0 +1,16 @@ +import FormContact from '../components/forms/FormContact'; + +const ContactPage = (props) => { + // const { } = props; + + return ( +
+

Contact

+

+ Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magnam alias dolor eveniet amet veniam, possimus qui +

+ +
+ ); +}; +export default ContactPage; diff --git a/06_react/uebungen/u17-18_validator-blur/src/pages/HomePage.jsx b/06_react/uebungen/u17-18_validator-blur/src/pages/HomePage.jsx new file mode 100644 index 0000000..dbe58d5 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/pages/HomePage.jsx @@ -0,0 +1,10 @@ +const HomePage = (props) => { + return ( +
+

Home

+

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad, voluptatibus.

+
+ ); +}; + +export default HomePage; diff --git a/06_react/uebungen/u17-18_validator-blur/src/pages/UserPage.jsx b/06_react/uebungen/u17-18_validator-blur/src/pages/UserPage.jsx new file mode 100644 index 0000000..7e837b9 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/pages/UserPage.jsx @@ -0,0 +1,25 @@ +import { Outlet } from 'react-router-dom'; + +const UserPage = (props) => { + // const { } = props; + + return ( +
+
+
+

User

+

The nestes user site:

+
+
+
+ +
+
+
+

© 2026 IA Donkey Fabric

+
+
+
+ ); +}; +export default UserPage; diff --git a/06_react/uebungen/u17-18_validator-blur/src/pages/UserProfilePage.jsx b/06_react/uebungen/u17-18_validator-blur/src/pages/UserProfilePage.jsx new file mode 100644 index 0000000..48c2d60 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/pages/UserProfilePage.jsx @@ -0,0 +1,18 @@ +import { useParams } from 'react-router-dom'; +import Badge from '../components/common/Badge'; + +const UserProfilePage = (props) => { + // const { } = props; + + const { userId } = useParams(); + + return ( +
+

+ User Profile +

+

Lorem ipsum dolor

+
+ ); +}; +export default UserProfilePage; diff --git a/06_react/uebungen/u17-18_validator-blur/src/routes/Router.jsx b/06_react/uebungen/u17-18_validator-blur/src/routes/Router.jsx new file mode 100644 index 0000000..e9472b9 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/routes/Router.jsx @@ -0,0 +1,61 @@ +import { Routes, Route, Navigate } from 'react-router-dom'; + +import About from '../pages/AboutPage'; +import Home from '../pages/HomePage'; +import Contact from '../pages/ContactPage'; +import UserProfilePage from '../pages/UserProfilePage'; +import UserPage from '../pages/UserPage'; + +// Prinzip einer geschützen Route-Komponente + +const checkAuth = () => { + // localStorage.setItem('token', 'secret-token'); + const token = localStorage.getItem('token'); + return token && token === 'secret-token' ? true : false; +}; + +const ProtectedRoute = (props) => { + const { redirectTo = '/', children } = props; + + const isAuthenticated = checkAuth(); // true | false // Authentication -Prüfung + + return isAuthenticated ? <>{children} : ; +}; + +const Router = (props) => { + // const { } = props; + + return ( + + {/* Static Routes */} + } /> + } /> + } /> + + {/* Dynamic Routes */} + Flights} /> + } /> + + {/* Nested Routes | Verschachtelte Routen */} + }> + Index} /> + Profile} /> + Dashboard} /> + + + {/* Protected Routes | Geschützte Routen */} + +
+

Admin Dashboard Page

+

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ad, ex?

+
+ + }>
+
+ ); +}; + +export default Router; diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/_index.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/_index.scss new file mode 100644 index 0000000..dcefbc9 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/_index.scss @@ -0,0 +1,3 @@ +// @import 'bootstrap-5.3.8/bootstrap-grid'; +@import 'bootstrap-5.3.8/bootstrap'; +// @import 'bulma-1.04/index' diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_accordion.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_accordion.scss new file mode 100644 index 0000000..e9f267f --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_accordion.scss @@ -0,0 +1,153 @@ +// +// Base styles +// + +.accordion { + // scss-docs-start accordion-css-vars + --#{$prefix}accordion-color: #{$accordion-color}; + --#{$prefix}accordion-bg: #{$accordion-bg}; + --#{$prefix}accordion-transition: #{$accordion-transition}; + --#{$prefix}accordion-border-color: #{$accordion-border-color}; + --#{$prefix}accordion-border-width: #{$accordion-border-width}; + --#{$prefix}accordion-border-radius: #{$accordion-border-radius}; + --#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius}; + --#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x}; + --#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y}; + --#{$prefix}accordion-btn-color: #{$accordion-button-color}; + --#{$prefix}accordion-btn-bg: #{$accordion-button-bg}; + --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)}; + --#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width}; + --#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform}; + --#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition}; + --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)}; + --#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow}; + --#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x}; + --#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y}; + --#{$prefix}accordion-active-color: #{$accordion-button-active-color}; + --#{$prefix}accordion-active-bg: #{$accordion-button-active-bg}; + // scss-docs-end accordion-css-vars +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x); + @include font-size($font-size-base); + color: var(--#{$prefix}accordion-btn-color); + text-align: left; // Reset button style + background-color: var(--#{$prefix}accordion-btn-bg); + border: 0; + @include border-radius(0); + overflow-anchor: none; + @include transition(var(--#{$prefix}accordion-transition)); + + &:not(.collapsed) { + color: var(--#{$prefix}accordion-active-color); + background-color: var(--#{$prefix}accordion-active-bg); + box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color); // stylelint-disable-line function-disallowed-list + + &::after { + background-image: var(--#{$prefix}accordion-btn-active-icon); + transform: var(--#{$prefix}accordion-btn-icon-transform); + } + } + + // Accordion icon + &::after { + flex-shrink: 0; + width: var(--#{$prefix}accordion-btn-icon-width); + height: var(--#{$prefix}accordion-btn-icon-width); + margin-left: auto; + content: ""; + background-image: var(--#{$prefix}accordion-btn-icon); + background-repeat: no-repeat; + background-size: var(--#{$prefix}accordion-btn-icon-width); + @include transition(var(--#{$prefix}accordion-btn-icon-transition)); + } + + &:hover { + z-index: 2; + } + + &:focus { + z-index: 3; + outline: 0; + box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow); + } +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + color: var(--#{$prefix}accordion-color); + background-color: var(--#{$prefix}accordion-bg); + border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color); + + &:first-of-type { + @include border-top-radius(var(--#{$prefix}accordion-border-radius)); + + > .accordion-header .accordion-button { + @include border-top-radius(var(--#{$prefix}accordion-inner-border-radius)); + } + } + + &:not(:first-of-type) { + border-top: 0; + } + + // Only set a border-radius on the last item if the accordion is collapsed + &:last-of-type { + @include border-bottom-radius(var(--#{$prefix}accordion-border-radius)); + + > .accordion-header .accordion-button { + &.collapsed { + @include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius)); + } + } + + > .accordion-collapse { + @include border-bottom-radius(var(--#{$prefix}accordion-border-radius)); + } + } +} + +.accordion-body { + padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x); +} + + +// Flush accordion items +// +// Remove borders and border-radius to keep accordion items edge-to-edge. + +.accordion-flush { + > .accordion-item { + border-right: 0; + border-left: 0; + @include border-radius(0); + + &:first-child { border-top: 0; } + &:last-child { border-bottom: 0; } + + // stylelint-disable selector-max-class + > .accordion-collapse, + > .accordion-header .accordion-button, + > .accordion-header .accordion-button.collapsed { + @include border-radius(0); + } + // stylelint-enable selector-max-class + } +} + +@if $enable-dark-mode { + @include color-mode(dark) { + .accordion-button::after { + --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)}; + --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)}; + } + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_alert.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_alert.scss new file mode 100644 index 0000000..b8cff9b --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_alert.scss @@ -0,0 +1,68 @@ +// +// Base styles +// + +.alert { + // scss-docs-start alert-css-vars + --#{$prefix}alert-bg: transparent; + --#{$prefix}alert-padding-x: #{$alert-padding-x}; + --#{$prefix}alert-padding-y: #{$alert-padding-y}; + --#{$prefix}alert-margin-bottom: #{$alert-margin-bottom}; + --#{$prefix}alert-color: inherit; + --#{$prefix}alert-border-color: transparent; + --#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}alert-border-color); + --#{$prefix}alert-border-radius: #{$alert-border-radius}; + --#{$prefix}alert-link-color: inherit; + // scss-docs-end alert-css-vars + + position: relative; + padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x); + margin-bottom: var(--#{$prefix}alert-margin-bottom); + color: var(--#{$prefix}alert-color); + background-color: var(--#{$prefix}alert-bg); + border: var(--#{$prefix}alert-border); + @include border-radius(var(--#{$prefix}alert-border-radius)); +} + +// Headings for larger alerts +.alert-heading { + // Specified to prevent conflicts of changing $headings-color + color: inherit; +} + +// Provide class for links that match alerts +.alert-link { + font-weight: $alert-link-font-weight; + color: var(--#{$prefix}alert-link-color); +} + + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissible { + padding-right: $alert-dismissible-padding-r; + + // Adjust close link position + .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: $stretched-link-z-index + 1; + padding: $alert-padding-y * 1.25 $alert-padding-x; + } +} + + +// scss-docs-start alert-modifiers +// Generate contextual modifier classes for colorizing the alert +@each $state in map-keys($theme-colors) { + .alert-#{$state} { + --#{$prefix}alert-color: var(--#{$prefix}#{$state}-text-emphasis); + --#{$prefix}alert-bg: var(--#{$prefix}#{$state}-bg-subtle); + --#{$prefix}alert-border-color: var(--#{$prefix}#{$state}-border-subtle); + --#{$prefix}alert-link-color: var(--#{$prefix}#{$state}-text-emphasis); + } +} +// scss-docs-end alert-modifiers diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_badge.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_badge.scss new file mode 100644 index 0000000..cc3d269 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_badge.scss @@ -0,0 +1,38 @@ +// Base class +// +// Requires one of the contextual, color modifier classes for `color` and +// `background-color`. + +.badge { + // scss-docs-start badge-css-vars + --#{$prefix}badge-padding-x: #{$badge-padding-x}; + --#{$prefix}badge-padding-y: #{$badge-padding-y}; + @include rfs($badge-font-size, --#{$prefix}badge-font-size); + --#{$prefix}badge-font-weight: #{$badge-font-weight}; + --#{$prefix}badge-color: #{$badge-color}; + --#{$prefix}badge-border-radius: #{$badge-border-radius}; + // scss-docs-end badge-css-vars + + display: inline-block; + padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x); + @include font-size(var(--#{$prefix}badge-font-size)); + font-weight: var(--#{$prefix}badge-font-weight); + line-height: 1; + color: var(--#{$prefix}badge-color); + text-align: center; + white-space: nowrap; + vertical-align: baseline; + @include border-radius(var(--#{$prefix}badge-border-radius)); + @include gradient-bg(); + + // Empty badges collapse automatically + &:empty { + display: none; + } +} + +// Quick fix for badges in buttons +.btn .badge { + position: relative; + top: -1px; +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_breadcrumb.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_breadcrumb.scss new file mode 100644 index 0000000..b8252ff --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_breadcrumb.scss @@ -0,0 +1,40 @@ +.breadcrumb { + // scss-docs-start breadcrumb-css-vars + --#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x}; + --#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y}; + --#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom}; + @include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size); + --#{$prefix}breadcrumb-bg: #{$breadcrumb-bg}; + --#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius}; + --#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color}; + --#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x}; + --#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color}; + // scss-docs-end breadcrumb-css-vars + + display: flex; + flex-wrap: wrap; + padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x); + margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom); + @include font-size(var(--#{$prefix}breadcrumb-font-size)); + list-style: none; + background-color: var(--#{$prefix}breadcrumb-bg); + @include border-radius(var(--#{$prefix}breadcrumb-border-radius)); +} + +.breadcrumb-item { + // The separator between breadcrumbs (by default, a forward-slash: "/") + + .breadcrumb-item { + padding-left: var(--#{$prefix}breadcrumb-item-padding-x); + + &::before { + float: left; // Suppress inline spacings and underlining of the separator + padding-right: var(--#{$prefix}breadcrumb-item-padding-x); + color: var(--#{$prefix}breadcrumb-divider-color); + content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"}; + } + } + + &.active { + color: var(--#{$prefix}breadcrumb-item-active-color); + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_button-group.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_button-group.scss new file mode 100644 index 0000000..78e1252 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_button-group.scss @@ -0,0 +1,147 @@ +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; // match .btn alignment given font-size hack above + + > .btn { + position: relative; + flex: 1 1 auto; + } + + // Bring the hover, focused, and "active" buttons to the front to overlay + // the borders properly + > .btn-check:checked + .btn, + > .btn-check:focus + .btn, + > .btn:hover, + > .btn:focus, + > .btn:active, + > .btn.active { + z-index: 1; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + + .input-group { + width: auto; + } +} + +.btn-group { + @include border-radius($btn-border-radius); + + // Prevent double borders when buttons are next to each other + > :not(.btn-check:first-child) + .btn, + > .btn-group:not(:first-child) { + margin-left: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list + } + + // Reset rounded corners + > .btn:not(:last-child):not(.dropdown-toggle), + > .btn.dropdown-toggle-split:first-child, + > .btn-group:not(:last-child) > .btn { + @include border-end-radius(0); + } + + // The left radius should be 0 if the button is: + // - the "third or more" child + // - the second child and the previous element isn't `.btn-check` (making it the first child visually) + // - part of a btn-group which isn't the first child + > .btn:nth-child(n + 3), + > :not(.btn-check) + .btn, + > .btn-group:not(:first-child) > .btn { + @include border-start-radius(0); + } +} + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-sm > .btn { @extend .btn-sm; } +.btn-group-lg > .btn { @extend .btn-lg; } + + +// +// Split button dropdowns +// + +.dropdown-toggle-split { + padding-right: $btn-padding-x * .75; + padding-left: $btn-padding-x * .75; + + &::after, + .dropup &::after, + .dropend &::after { + margin-left: 0; + } + + .dropstart &::before { + margin-right: 0; + } +} + +.btn-sm + .dropdown-toggle-split { + padding-right: $btn-padding-x-sm * .75; + padding-left: $btn-padding-x-sm * .75; +} + +.btn-lg + .dropdown-toggle-split { + padding-right: $btn-padding-x-lg * .75; + padding-left: $btn-padding-x-lg * .75; +} + + +// The clickable button for toggling the menu +// Set the same inset shadow as the :active state +.btn-group.show .dropdown-toggle { + @include box-shadow($btn-active-box-shadow); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + @include box-shadow(none); + } +} + + +// +// Vertical button groups +// + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; + + > .btn, + > .btn-group { + width: 100%; + } + + > .btn:not(:first-child), + > .btn-group:not(:first-child) { + margin-top: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list + } + + // Reset rounded corners + > .btn:not(:last-child):not(.dropdown-toggle), + > .btn-group:not(:last-child) > .btn { + @include border-bottom-radius(0); + } + + // The top radius should be 0 if the button is: + // - the "third or more" child + // - the second child and the previous element isn't `.btn-check` (making it the first child visually) + // - part of a btn-group which isn't the first child + > .btn:nth-child(n + 3), + > :not(.btn-check) + .btn, + > .btn-group:not(:first-child) > .btn { + @include border-top-radius(0); + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_buttons.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_buttons.scss new file mode 100644 index 0000000..caa4518 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_buttons.scss @@ -0,0 +1,216 @@ +// +// Base styles +// + +.btn { + // scss-docs-start btn-css-vars + --#{$prefix}btn-padding-x: #{$btn-padding-x}; + --#{$prefix}btn-padding-y: #{$btn-padding-y}; + --#{$prefix}btn-font-family: #{$btn-font-family}; + @include rfs($btn-font-size, --#{$prefix}btn-font-size); + --#{$prefix}btn-font-weight: #{$btn-font-weight}; + --#{$prefix}btn-line-height: #{$btn-line-height}; + --#{$prefix}btn-color: #{$btn-color}; + --#{$prefix}btn-bg: transparent; + --#{$prefix}btn-border-width: #{$btn-border-width}; + --#{$prefix}btn-border-color: transparent; + --#{$prefix}btn-border-radius: #{$btn-border-radius}; + --#{$prefix}btn-hover-border-color: transparent; + --#{$prefix}btn-box-shadow: #{$btn-box-shadow}; + --#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity}; + --#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} rgba(var(--#{$prefix}btn-focus-shadow-rgb), .5); + // scss-docs-end btn-css-vars + + display: inline-block; + padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x); + font-family: var(--#{$prefix}btn-font-family); + @include font-size(var(--#{$prefix}btn-font-size)); + font-weight: var(--#{$prefix}btn-font-weight); + line-height: var(--#{$prefix}btn-line-height); + color: var(--#{$prefix}btn-color); + text-align: center; + text-decoration: if($link-decoration == none, null, none); + white-space: $btn-white-space; + vertical-align: middle; + cursor: if($enable-button-pointers, pointer, null); + user-select: none; + border: var(--#{$prefix}btn-border-width) solid var(--#{$prefix}btn-border-color); + @include border-radius(var(--#{$prefix}btn-border-radius)); + @include gradient-bg(var(--#{$prefix}btn-bg)); + @include box-shadow(var(--#{$prefix}btn-box-shadow)); + @include transition($btn-transition); + + &:hover { + color: var(--#{$prefix}btn-hover-color); + text-decoration: if($link-hover-decoration == underline, none, null); + background-color: var(--#{$prefix}btn-hover-bg); + border-color: var(--#{$prefix}btn-hover-border-color); + } + + .btn-check + &:hover { + // override for the checkbox/radio buttons + color: var(--#{$prefix}btn-color); + background-color: var(--#{$prefix}btn-bg); + border-color: var(--#{$prefix}btn-border-color); + } + + &:focus-visible { + color: var(--#{$prefix}btn-hover-color); + @include gradient-bg(var(--#{$prefix}btn-hover-bg)); + border-color: var(--#{$prefix}btn-hover-border-color); + outline: 0; + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + + .btn-check:focus-visible + & { + border-color: var(--#{$prefix}btn-hover-border-color); + outline: 0; + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + + .btn-check:checked + &, + :not(.btn-check) + &:active, + &:first-child:active, + &.active, + &.show { + color: var(--#{$prefix}btn-active-color); + background-color: var(--#{$prefix}btn-active-bg); + // Remove CSS gradients if they're enabled + background-image: if($enable-gradients, none, null); + border-color: var(--#{$prefix}btn-active-border-color); + @include box-shadow(var(--#{$prefix}btn-active-shadow)); + + &:focus-visible { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + } + + .btn-check:checked:focus-visible + & { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + + &:disabled, + &.disabled, + fieldset:disabled & { + color: var(--#{$prefix}btn-disabled-color); + pointer-events: none; + background-color: var(--#{$prefix}btn-disabled-bg); + background-image: if($enable-gradients, none, null); + border-color: var(--#{$prefix}btn-disabled-border-color); + opacity: var(--#{$prefix}btn-disabled-opacity); + @include box-shadow(none); + } +} + + +// +// Alternate buttons +// + +// scss-docs-start btn-variant-loops +@each $color, $value in $theme-colors { + .btn-#{$color} { + @if $color == "light" { + @include button-variant( + $value, + $value, + $hover-background: shade-color($value, $btn-hover-bg-shade-amount), + $hover-border: shade-color($value, $btn-hover-border-shade-amount), + $active-background: shade-color($value, $btn-active-bg-shade-amount), + $active-border: shade-color($value, $btn-active-border-shade-amount) + ); + } @else if $color == "dark" { + @include button-variant( + $value, + $value, + $hover-background: tint-color($value, $btn-hover-bg-tint-amount), + $hover-border: tint-color($value, $btn-hover-border-tint-amount), + $active-background: tint-color($value, $btn-active-bg-tint-amount), + $active-border: tint-color($value, $btn-active-border-tint-amount) + ); + } @else { + @include button-variant($value, $value); + } + } +} + +@each $color, $value in $theme-colors { + .btn-outline-#{$color} { + @include button-outline-variant($value); + } +} +// scss-docs-end btn-variant-loops + + +// +// Link buttons +// + +// Make a button look and behave like a link +.btn-link { + --#{$prefix}btn-font-weight: #{$font-weight-normal}; + --#{$prefix}btn-color: #{$btn-link-color}; + --#{$prefix}btn-bg: transparent; + --#{$prefix}btn-border-color: transparent; + --#{$prefix}btn-hover-color: #{$btn-link-hover-color}; + --#{$prefix}btn-hover-border-color: transparent; + --#{$prefix}btn-active-color: #{$btn-link-hover-color}; + --#{$prefix}btn-active-border-color: transparent; + --#{$prefix}btn-disabled-color: #{$btn-link-disabled-color}; + --#{$prefix}btn-disabled-border-color: transparent; + --#{$prefix}btn-box-shadow: 0 0 0 #000; // Can't use `none` as keyword negates all values when used with multiple shadows + --#{$prefix}btn-focus-shadow-rgb: #{$btn-link-focus-shadow-rgb}; + + text-decoration: $link-decoration; + @if $enable-gradients { + background-image: none; + } + + &:hover, + &:focus-visible { + text-decoration: $link-hover-decoration; + } + + &:focus-visible { + color: var(--#{$prefix}btn-color); + } + + &:hover { + color: var(--#{$prefix}btn-hover-color); + } + + // No need for an active state here +} + + +// +// Button Sizes +// + +.btn-lg { + @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-border-radius-lg); +} + +.btn-sm { + @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm); +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_card.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_card.scss new file mode 100644 index 0000000..dcebe6a --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_card.scss @@ -0,0 +1,238 @@ +// +// Base styles +// + +.card { + // scss-docs-start card-css-vars + --#{$prefix}card-spacer-y: #{$card-spacer-y}; + --#{$prefix}card-spacer-x: #{$card-spacer-x}; + --#{$prefix}card-title-spacer-y: #{$card-title-spacer-y}; + --#{$prefix}card-title-color: #{$card-title-color}; + --#{$prefix}card-subtitle-color: #{$card-subtitle-color}; + --#{$prefix}card-border-width: #{$card-border-width}; + --#{$prefix}card-border-color: #{$card-border-color}; + --#{$prefix}card-border-radius: #{$card-border-radius}; + --#{$prefix}card-box-shadow: #{$card-box-shadow}; + --#{$prefix}card-inner-border-radius: #{$card-inner-border-radius}; + --#{$prefix}card-cap-padding-y: #{$card-cap-padding-y}; + --#{$prefix}card-cap-padding-x: #{$card-cap-padding-x}; + --#{$prefix}card-cap-bg: #{$card-cap-bg}; + --#{$prefix}card-cap-color: #{$card-cap-color}; + --#{$prefix}card-height: #{$card-height}; + --#{$prefix}card-color: #{$card-color}; + --#{$prefix}card-bg: #{$card-bg}; + --#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding}; + --#{$prefix}card-group-margin: #{$card-group-margin}; + // scss-docs-end card-css-vars + + position: relative; + display: flex; + flex-direction: column; + min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106 + height: var(--#{$prefix}card-height); + color: var(--#{$prefix}body-color); + word-wrap: break-word; + background-color: var(--#{$prefix}card-bg); + background-clip: border-box; + border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + @include border-radius(var(--#{$prefix}card-border-radius)); + @include box-shadow(var(--#{$prefix}card-box-shadow)); + + > hr { + margin-right: 0; + margin-left: 0; + } + + > .list-group { + border-top: inherit; + border-bottom: inherit; + + &:first-child { + border-top-width: 0; + @include border-top-radius(var(--#{$prefix}card-inner-border-radius)); + } + + &:last-child { + border-bottom-width: 0; + @include border-bottom-radius(var(--#{$prefix}card-inner-border-radius)); + } + } + + // Due to specificity of the above selector (`.card > .list-group`), we must + // use a child selector here to prevent double borders. + > .card-header + .list-group, + > .list-group + .card-footer { + border-top: 0; + } +} + +.card-body { + // Enable `flex-grow: 1` for decks and groups so that card blocks take up + // as much space as possible, ensuring footers are aligned to the bottom. + flex: 1 1 auto; + padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x); + color: var(--#{$prefix}card-color); +} + +.card-title { + margin-bottom: var(--#{$prefix}card-title-spacer-y); + color: var(--#{$prefix}card-title-color); +} + +.card-subtitle { + margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y)); // stylelint-disable-line function-disallowed-list + margin-bottom: 0; + color: var(--#{$prefix}card-subtitle-color); +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link { + &:hover { + text-decoration: if($link-hover-decoration == underline, none, null); + } + + + .card-link { + margin-left: var(--#{$prefix}card-spacer-x); + } +} + +// +// Optional textual caps +// + +.card-header { + padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x); + margin-bottom: 0; // Removes the default margin-bottom of + color: var(--#{$prefix}card-cap-color); + background-color: var(--#{$prefix}card-cap-bg); + border-bottom: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + + &:first-child { + @include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0); + } +} + +.card-footer { + padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x); + color: var(--#{$prefix}card-cap-color); + background-color: var(--#{$prefix}card-cap-bg); + border-top: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + + &:last-child { + @include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius)); + } +} + + +// +// Header navs +// + +.card-header-tabs { + margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y)); // stylelint-disable-line function-disallowed-list + margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + border-bottom: 0; + + .nav-link.active { + background-color: var(--#{$prefix}card-bg); + border-bottom-color: var(--#{$prefix}card-bg); + } +} + +.card-header-pills { + margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list +} + +// Card image +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: var(--#{$prefix}card-img-overlay-padding); + @include border-radius(var(--#{$prefix}card-inner-border-radius)); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch +} + +.card-img, +.card-img-top { + @include border-top-radius(var(--#{$prefix}card-inner-border-radius)); +} + +.card-img, +.card-img-bottom { + @include border-bottom-radius(var(--#{$prefix}card-inner-border-radius)); +} + + +// +// Card groups +// + +.card-group { + // The child selector allows nested `.card` within `.card-group` + // to display properly. + > .card { + margin-bottom: var(--#{$prefix}card-group-margin); + } + + @include media-breakpoint-up(sm) { + display: flex; + flex-flow: row wrap; + // The child selector allows nested `.card` within `.card-group` + // to display properly. + > .card { + flex: 1 0 0; + margin-bottom: 0; + + + .card { + margin-left: 0; + border-left: 0; + } + + // Handle rounded corners + @if $enable-rounded { + &:not(:last-child) { + @include border-end-radius(0); + + > .card-img-top, + > .card-header { + // stylelint-disable-next-line property-disallowed-list + border-top-right-radius: 0; + } + > .card-img-bottom, + > .card-footer { + // stylelint-disable-next-line property-disallowed-list + border-bottom-right-radius: 0; + } + } + + &:not(:first-child) { + @include border-start-radius(0); + + > .card-img-top, + > .card-header { + // stylelint-disable-next-line property-disallowed-list + border-top-left-radius: 0; + } + > .card-img-bottom, + > .card-footer { + // stylelint-disable-next-line property-disallowed-list + border-bottom-left-radius: 0; + } + } + } + } + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_carousel.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_carousel.scss new file mode 100644 index 0000000..5ebf6b1 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_carousel.scss @@ -0,0 +1,226 @@ +// Notes on the classes: +// +// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically) +// even when their scroll action started on a carousel, but for compatibility (with Firefox) +// we're preventing all actions instead +// 2. The .carousel-item-start and .carousel-item-end is used to indicate where +// the active slide is heading. +// 3. .active.carousel-item is the current slide. +// 4. .active.carousel-item-start and .active.carousel-item-end is the current +// slide in its in-transition state. Only one of these occurs at a time. +// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end +// is the upcoming slide in transition. + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; + @include clearfix(); +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + backface-visibility: hidden; + @include transition($carousel-transition); +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + + +// +// Alternate transitions +// + +.carousel-fade { + .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; + } + + .carousel-item.active, + .carousel-item-next.carousel-item-start, + .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; + } + + .active.carousel-item-start, + .active.carousel-item-end { + z-index: 0; + opacity: 0; + @include transition(opacity 0s $carousel-transition-duration); + } +} + + +// +// Left/right controls for nav +// + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + // Use flex for alignment (1-3) + display: flex; // 1. allow flex styles + align-items: center; // 2. vertically center contents + justify-content: center; // 3. horizontally center contents + width: $carousel-control-width; + padding: 0; + color: $carousel-control-color; + text-align: center; + background: none; + filter: var(--#{$prefix}carousel-control-icon-filter); + border: 0; + opacity: $carousel-control-opacity; + @include transition($carousel-control-transition); + + // Hover/focus state + &:hover, + &:focus { + color: $carousel-control-color; + text-decoration: none; + outline: 0; + opacity: $carousel-control-hover-opacity; + } +} +.carousel-control-prev { + left: 0; + background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null); +} +.carousel-control-next { + right: 0; + background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null); +} + +// Icons for within +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: $carousel-control-icon-width; + height: $carousel-control-icon-width; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + +.carousel-control-prev-icon { + background-image: escape-svg($carousel-control-prev-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-next-icon-bg) + "*/"}; +} +.carousel-control-next-icon { + background-image: escape-svg($carousel-control-next-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-prev-icon-bg) + "*/"}; +} + +// Optional indicator pips/controls +// +// Add a container (such as a list) with the following class and add an item (ideally a focusable control, +// like a button) with data-bs-target for each slide your carousel holds. + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + // Use the .carousel-control's width as margin so we don't overlay those + margin-right: $carousel-control-width; + margin-bottom: 1rem; + margin-left: $carousel-control-width; + + [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: $carousel-indicator-width; + height: $carousel-indicator-height; + padding: 0; + margin-right: $carousel-indicator-spacer; + margin-left: $carousel-indicator-spacer; + text-indent: -999px; + cursor: pointer; + background-color: var(--#{$prefix}carousel-indicator-active-bg); + background-clip: padding-box; + border: 0; + // Use transparent borders to increase the hit area by 10px on top and bottom. + border-top: $carousel-indicator-hit-area-height solid transparent; + border-bottom: $carousel-indicator-hit-area-height solid transparent; + opacity: $carousel-indicator-opacity; + @include transition($carousel-indicator-transition); + } + + .active { + opacity: $carousel-indicator-active-opacity; + } +} + + +// Optional captions +// +// + +.carousel-caption { + position: absolute; + right: (100% - $carousel-caption-width) * .5; + bottom: $carousel-caption-spacer; + left: (100% - $carousel-caption-width) * .5; + padding-top: $carousel-caption-padding-y; + padding-bottom: $carousel-caption-padding-y; + color: var(--#{$prefix}carousel-caption-color); + text-align: center; +} + +// Dark mode carousel + +@mixin carousel-dark() { + --#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg-dark}; + --#{$prefix}carousel-caption-color: #{$carousel-caption-color-dark}; + --#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter-dark}; +} + +.carousel-dark { + @include carousel-dark(); +} + +:root, +[data-bs-theme="light"] { + --#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg}; + --#{$prefix}carousel-caption-color: #{$carousel-caption-color}; + --#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter}; +} + +@if $enable-dark-mode { + @include color-mode(dark, true) { + @include carousel-dark(); + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_close.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_close.scss new file mode 100644 index 0000000..d53c96f --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_close.scss @@ -0,0 +1,66 @@ +// Transparent background and border properties included for button version. +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + +.btn-close { + // scss-docs-start close-css-vars + --#{$prefix}btn-close-color: #{$btn-close-color}; + --#{$prefix}btn-close-bg: #{ escape-svg($btn-close-bg) }; + --#{$prefix}btn-close-opacity: #{$btn-close-opacity}; + --#{$prefix}btn-close-hover-opacity: #{$btn-close-hover-opacity}; + --#{$prefix}btn-close-focus-shadow: #{$btn-close-focus-shadow}; + --#{$prefix}btn-close-focus-opacity: #{$btn-close-focus-opacity}; + --#{$prefix}btn-close-disabled-opacity: #{$btn-close-disabled-opacity}; + // scss-docs-end close-css-vars + + box-sizing: content-box; + width: $btn-close-width; + height: $btn-close-height; + padding: $btn-close-padding-y $btn-close-padding-x; + color: var(--#{$prefix}btn-close-color); + background: transparent var(--#{$prefix}btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements + filter: var(--#{$prefix}btn-close-filter); + border: 0; // for button elements + @include border-radius(); + opacity: var(--#{$prefix}btn-close-opacity); + + // Override 's hover style + &:hover { + color: var(--#{$prefix}btn-close-color); + text-decoration: none; + opacity: var(--#{$prefix}btn-close-hover-opacity); + } + + &:focus { + outline: 0; + box-shadow: var(--#{$prefix}btn-close-focus-shadow); + opacity: var(--#{$prefix}btn-close-focus-opacity); + } + + &:disabled, + &.disabled { + pointer-events: none; + user-select: none; + opacity: var(--#{$prefix}btn-close-disabled-opacity); + } +} + +@mixin btn-close-white() { + --#{$prefix}btn-close-filter: #{$btn-close-filter-dark}; +} + +.btn-close-white { + @include btn-close-white(); +} + +:root, +[data-bs-theme="light"] { + --#{$prefix}btn-close-filter: #{$btn-close-filter}; +} + +@if $enable-dark-mode { + @include color-mode(dark, true) { + @include btn-close-white(); + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_containers.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_containers.scss new file mode 100644 index 0000000..83b3138 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_containers.scss @@ -0,0 +1,41 @@ +// Container widths +// +// Set the container width, and override it for fixed navbars in media queries. + +@if $enable-container-classes { + // Single container class with breakpoint max-widths + .container, + // 100% wide container at all breakpoints + .container-fluid { + @include make-container(); + } + + // Responsive containers that are 100% wide until a breakpoint + @each $breakpoint, $container-max-width in $container-max-widths { + .container-#{$breakpoint} { + @extend .container-fluid; + } + + @include media-breakpoint-up($breakpoint, $grid-breakpoints) { + %responsive-container-#{$breakpoint} { + max-width: $container-max-width; + } + + // Extend each breakpoint which is smaller or equal to the current breakpoint + $extend-breakpoint: true; + + @each $name, $width in $grid-breakpoints { + @if ($extend-breakpoint) { + .container#{breakpoint-infix($name, $grid-breakpoints)} { + @extend %responsive-container-#{$breakpoint}; + } + + // Once the current breakpoint is reached, stop extending + @if ($breakpoint == $name) { + $extend-breakpoint: false; + } + } + } + } + } +} diff --git a/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_dropdown.scss b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_dropdown.scss new file mode 100644 index 0000000..587ebb4 --- /dev/null +++ b/06_react/uebungen/u17-18_validator-blur/src/styles/01_frameworks/bootstrap-5.3.8/_dropdown.scss @@ -0,0 +1,250 @@ +// The dropdown wrapper (`
`) +.dropup, +.dropend, +.dropdown, +.dropstart, +.dropup-center, +.dropdown-center { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; + + // Generate the caret automatically + @include caret(); +} + +// The dropdown menu +.dropdown-menu { + // scss-docs-start dropdown-css-vars + --#{$prefix}dropdown-zindex: #{$zindex-dropdown}; + --#{$prefix}dropdown-min-width: #{$dropdown-min-width}; + --#{$prefix}dropdown-padding-x: #{$dropdown-padding-x}; + --#{$prefix}dropdown-padding-y: #{$dropdown-padding-y}; + --#{$prefix}dropdown-spacer: #{$dropdown-spacer}; + @include rfs($dropdown-font-size, --#{$prefix}dropdown-font-size); + --#{$prefix}dropdown-color: #{$dropdown-color}; + --#{$prefix}dropdown-bg: #{$dropdown-bg}; + --#{$prefix}dropdown-border-color: #{$dropdown-border-color}; + --#{$prefix}dropdown-border-radius: #{$dropdown-border-radius}; + --#{$prefix}dropdown-border-width: #{$dropdown-border-width}; + --#{$prefix}dropdown-inner-border-radius: #{$dropdown-inner-border-radius}; + --#{$prefix}dropdown-divider-bg: #{$dropdown-divider-bg}; + --#{$prefix}dropdown-divider-margin-y: #{$dropdown-divider-margin-y}; + --#{$prefix}dropdown-box-shadow: #{$dropdown-box-shadow}; + --#{$prefix}dropdown-link-color: #{$dropdown-link-color}; + --#{$prefix}dropdown-link-hover-color: #{$dropdown-link-hover-color}; + --#{$prefix}dropdown-link-hover-bg: #{$dropdown-link-hover-bg}; + --#{$prefix}dropdown-link-active-color: #{$dropdown-link-active-color}; + --#{$prefix}dropdown-link-active-bg: #{$dropdown-link-active-bg}; + --#{$prefix}dropdown-link-disabled-color: #{$dropdown-link-disabled-color}; + --#{$prefix}dropdown-item-padding-x: #{$dropdown-item-padding-x}; + --#{$prefix}dropdown-item-padding-y: #{$dropdown-item-padding-y}; + --#{$prefix}dropdown-header-color: #{$dropdown-header-color}; + --#{$prefix}dropdown-header-padding-x: #{$dropdown-header-padding-x}; + --#{$prefix}dropdown-header-padding-y: #{$dropdown-header-padding-y}; + // scss-docs-end dropdown-css-vars + + position: absolute; + z-index: var(--#{$prefix}dropdown-zindex); + display: none; // none by default, but block on "open" of the menu + min-width: var(--#{$prefix}dropdown-min-width); + padding: var(--#{$prefix}dropdown-padding-y) var(--#{$prefix}dropdown-padding-x); + margin: 0; // Override default margin of ul + @include font-size(var(--#{$prefix}dropdown-font-size)); + color: var(--#{$prefix}dropdown-color); + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + list-style: none; + background-color: var(--#{$prefix}dropdown-bg); + background-clip: padding-box; + border: var(--#{$prefix}dropdown-border-width) solid var(--#{$prefix}dropdown-border-color); + @include border-radius(var(--#{$prefix}dropdown-border-radius)); + @include box-shadow(var(--#{$prefix}dropdown-box-shadow)); + + &[data-bs-popper] { + top: 100%; + left: 0; + margin-top: var(--#{$prefix}dropdown-spacer); + } + + @if $dropdown-padding-y == 0 { + > .dropdown-item:first-child, + > li:first-child .dropdown-item { + @include border-top-radius(var(--#{$prefix}dropdown-inner-border-radius)); + } + > .dropdown-item:last-child, + > li:last-child .dropdown-item { + @include border-bottom-radius(var(--#{$prefix}dropdown-inner-border-radius)); + } + + } +} + +// scss-docs-start responsive-breakpoints +// We deliberately hardcode the `bs-` prefix because we check +// this custom property in JS to determine Popper's positioning + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .dropdown-menu#{$infix}-start { + --bs-position: start; + + &[data-bs-popper] { + right: auto; + left: 0; + } + } + + .dropdown-menu#{$infix}-end { + --bs-position: end; + + &[data-bs-popper] { + right: 0; + left: auto; + } + } + } +} +// scss-docs-end responsive-breakpoints + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// Just add .dropup after the standard .dropdown class and you're set. +.dropup { + .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(up); + } +} + +.dropend { + .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(end); + &::after { + vertical-align: 0; + } + } +} + +.dropstart { + .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(start); + &::before { + vertical-align: 0; + } + } +} + + +// Dividers (basically an `
`) within the dropdown +.dropdown-divider { + height: 0; + margin: var(--#{$prefix}dropdown-divider-margin-y) 0; + overflow: hidden; + border-top: 1px solid var(--#{$prefix}dropdown-divider-bg); + opacity: 1; // Revisit in v6 to de-dupe styles that conflict with
element +} + +// Links, buttons, and more within the dropdown menu +// +// `
@@ -106,9 +93,13 @@ const FormContact = (props) => { id="textarea-message" cols="30" rows="5" - onChange={handleChange} + {...register('message', { + required: 'Message invalid', + minLength: { value: 10, message: 'Message to short' }, + maxLength: { value: 1000, message: 'Message to long' }, + })} className={`form-control ${errors.message ? 'is-invalid' : ''}`}> -
{errors?.message || 'Error'}
+
{errors?.message?.message || 'Error'}